From patchwork Wed Nov 18 01:43:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Colitti X-Patchwork-Id: 545841 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id C048C14076B for ; Wed, 18 Nov 2015 12:44:18 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b=h+CqEkWU; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755207AbbKRBoN (ORCPT ); Tue, 17 Nov 2015 20:44:13 -0500 Received: from mail-pa0-f43.google.com ([209.85.220.43]:34496 "EHLO mail-pa0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755187AbbKRBoK (ORCPT ); Tue, 17 Nov 2015 20:44:10 -0500 Received: by padhx2 with SMTP id hx2so26860262pad.1 for ; Tue, 17 Nov 2015 17:44:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=epga8Se1rM/dLL9loBEHS949HPKfWG03o1oYf6IHRjc=; b=h+CqEkWUju5JgYJZncqeuBH2/gJzVD/SFsC1uMrszJV911eL/k8gQbTFbOYnD06fOF OfPxfV4mnvF04udyJiZ7cWAHINLT6b6yPRS/ns8LwtbiAJ4lxY1mSGshviD0ntQznA++ 2E4qLMufGazFDPJMLk0e1QJA3Rtut3DVvK89KvG52+hJdT7Gu53wxPtVJKsKDXj3E2aK qjAsViZeGnGggiDz0jccPoWZ4yX1+g+inMhNrX2KR0xi2ESXJ05RaSevoBpgvmLdQCoX b9QruU32Nu2un7kA/8n0vLDVEfx2Zk+clS9O7CMLRhlV2tF26R0uPLLYzDldkA4LYubM S3Lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=epga8Se1rM/dLL9loBEHS949HPKfWG03o1oYf6IHRjc=; b=BWPDSgchzfEnbsFCdHhHUSfKahXjSHF6RYTSK994uJRMom1dBFySnwTku8MaKMUQk1 z5UeeG7V2LEMyapqS/5Sv4H8VEXk140oBhbVfDSuANoJBJg2y/uWIyHB6W8FQEsKCjlu maJOlHE6NgDXRKIL8WHnrwWgUWFujXBcJz4JHskGvKPy0A9myVMlKiaLM87sVDflKPw+ lt6THVZrmdtFrf4Lr0sCvSWpgs+k/rofYmMhui/0ZoFBQredR9OWARcVxv7HbLEQbNxq 7gD1iUvNbEw1YpaYZpiNVpOxmgfbH65mRng7xbziEIF3KHUmkouVuOXLb56g6m+N/Yx7 ktYQ== X-Gm-Message-State: ALoCoQngi8jWnsJKkY74EDLXdmyOH8LVe+DfgO3OXY6Kj2XqxNpwvstwUUm3qvIf+QZVtDEJ5+sy X-Received: by 10.68.184.132 with SMTP id eu4mr68049480pbc.122.1447811050040; Tue, 17 Nov 2015 17:44:10 -0800 (PST) Received: from drone.tok.corp.google.com ([100.103.2.119]) by smtp.gmail.com with ESMTPSA id yi8sm269445pab.22.2015.11.17.17.44.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 17 Nov 2015 17:44:09 -0800 (PST) From: Lorenzo Colitti To: netdev@vger.kernel.org Cc: edumazet@google.com, ek@google.com, maze@google.com, dtor@google.com, Lorenzo Colitti Subject: [PATCH 2/4] net: diag: Add the ability to destroy a socket from userspace. Date: Wed, 18 Nov 2015 10:43:42 +0900 Message-Id: <1447811024-8553-3-git-send-email-lorenzo@google.com> X-Mailer: git-send-email 2.6.0.rc2.230.g3dd15c0 In-Reply-To: <1447811024-8553-1-git-send-email-lorenzo@google.com> References: <1447811024-8553-1-git-send-email-lorenzo@google.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This allows a privileged userspace process, such as a connection manager or system administration tool, to close sockets belonging to other apps when the network they were established on has disconnected. It is needed on laptops and mobile hosts to ensure that network switches / disconnects do not result in applications being blocked for long periods of time (minutes) in read or connect calls on TCP sockets that will never succeed because the IP address they are bound to is no longer on the system. Closing the sockets causes these calls to fail fast and allows the apps to reconnect on another network. For many years Android kernels have supported this via an out-of-tree SIOCKILLADDR ioctl that is called on every RTM_DELADDR event, but this solution is cleaner, more robust and more flexible: the connection manager can iterate over all connections on the deleted IP address and close all of them. It can also be used to close all sockets opened by a given app process, for example if the user has restricted that app from using the network. This patch adds a SOCK_DESTROY operation and a destroy function pointer to sock_diag_handler. It does not include any implementation code. Signed-off-by: Lorenzo Colitti --- include/linux/sock_diag.h | 1 + include/uapi/linux/sock_diag.h | 1 + net/core/sock_diag.c | 11 ++++++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h index fddebc6..e15e8e2 100644 --- a/include/linux/sock_diag.h +++ b/include/linux/sock_diag.h @@ -15,6 +15,7 @@ struct sock_diag_handler { __u8 family; int (*dump)(struct sk_buff *skb, struct nlmsghdr *nlh); int (*get_info)(struct sk_buff *skb, struct sock *sk); + int (*destroy)(struct sk_buff *skb, struct nlmsghdr *nlh); }; int sock_diag_register(const struct sock_diag_handler *h); diff --git a/include/uapi/linux/sock_diag.h b/include/uapi/linux/sock_diag.h index 49230d3..bae2d80 100644 --- a/include/uapi/linux/sock_diag.h +++ b/include/uapi/linux/sock_diag.h @@ -4,6 +4,7 @@ #include #define SOCK_DIAG_BY_FAMILY 20 +#define SOCK_DESTROY 21 struct sock_diag_req { __u8 sdiag_family; diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 0c1d58d..64e3d81 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -214,7 +214,7 @@ void sock_diag_unregister(const struct sock_diag_handler *hnld) } EXPORT_SYMBOL_GPL(sock_diag_unregister); -static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) +static int __sock_diag_cmd(struct sk_buff *skb, struct nlmsghdr *nlh) { int err; struct sock_diag_req *req = nlmsg_data(nlh); @@ -234,8 +234,12 @@ static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) hndl = sock_diag_handlers[req->sdiag_family]; if (hndl == NULL) err = -ENOENT; - else + else if (nlh->nlmsg_type == SOCK_DIAG_BY_FAMILY) err = hndl->dump(skb, nlh); + else if (nlh->nlmsg_type == SOCK_DESTROY && hndl->destroy) + err = hndl->destroy(skb, nlh); + else + err = -EOPNOTSUPP; mutex_unlock(&sock_diag_table_mutex); return err; @@ -261,7 +265,8 @@ static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return ret; case SOCK_DIAG_BY_FAMILY: - return __sock_diag_rcv_msg(skb, nlh); + case SOCK_DESTROY: + return __sock_diag_cmd(skb, nlh); default: return -EINVAL; }