Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754852Ab0AOIKv (ORCPT ); Fri, 15 Jan 2010 03:10:51 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754367Ab0AOIKr (ORCPT ); Fri, 15 Jan 2010 03:10:47 -0500 Received: from lists.laptop.org ([18.85.2.145]:37588 "EHLO mail.laptop.org" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752950Ab0AOIKo (ORCPT ); Fri, 15 Jan 2010 03:10:44 -0500 Date: Fri, 15 Jan 2010 03:13:08 -0500 From: Michael Stone To: linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org, linux-security-module@vger.kernel.org, Andi Kleen , David Lang , Oliver Hartkopp , Alan Cox , Herbert Xu , Valdis Kletnieks , Bryan Donlan , Evgeniy Polyakov , "C. Scott Ananian" , James Morris , "Eric W. Biederman" , Bernie Innocenti , Mark Seaborn , Randy Dunlap , =?iso-8859-1?Q?Am=E9rico?= Wang , Tetsuo Handa , Samir Bellabes , Casey Schaufler , "Serge E. Hallyn" , Pavel Machek , Al Viro , Kyle Moffett , Andrew Morgan , Michael Stone Subject: disablenetwork (v5): Require CAP_SETPCAP to enable disablenetwork. Message-ID: <20100115081308.GA14443@heat> References: <20100115081028.GA14004@heat> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20100115081028.GA14004@heat> User-Agent: Mutt/1.5.18 (2008-05-17) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We implement this check by allocating a new flag bit in task_struct->network and by propagating its semantics throughout the disablenetwork facility. Signed-off-by: Michael Stone --- include/linux/prctl.h | 8 +++++--- kernel/sys.c | 14 +++++++++++++- security/disablenetwork.c | 15 ++++++++------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/linux/prctl.h b/include/linux/prctl.h index 4eb4110..4fdb417 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h @@ -105,8 +105,10 @@ /* Get/set process disable-network flags */ #define PR_SET_NETWORK 35 #define PR_GET_NETWORK 36 -# define PR_NETWORK_ON 0 -# define PR_NETWORK_OFF 1 -# define PR_NETWORK_ALL_FLAGS 1 +# define PR_NETWORK_ON 0 +# define PR_NETWORK_ENABLE_DN 1 +# define PR_NETWORK_OFF 2 +# define PR_NETWORK_ALL_FLAGS 3 +# define PR_NETWORK_DN_FLAGS 3 #endif /* _LINUX_PRCTL_H */ diff --git a/kernel/sys.c b/kernel/sys.c index 1fadf10..4c7ef83 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1608,7 +1608,19 @@ long prctl_set_network(unsigned long network_flags) if (current->network & ~network_flags) return -EPERM; - current->network = network_flags; + /* Only the superuser may permit a process to enable disablenetwork. */ + if (!(current->network & PR_NETWORK_ENABLE_DN) && + network_flags & PR_NETWORK_ENABLE_DN && + !capable(CAP_SETPCAP)) + return -EPERM; + + /* Only dn-enabled processes may activate disablenetwork. */ + if (!(current->network & PR_NETWORK_OFF) && + network_flags & PR_NETWORK_OFF && + !(current->network & PR_NETWORK_ENABLE_DN)) + return -EPERM; + + current->network |= network_flags; return 0; } diff --git a/security/disablenetwork.c b/security/disablenetwork.c index 27b88d7..02c0150 100644 --- a/security/disablenetwork.c +++ b/security/disablenetwork.c @@ -19,10 +19,11 @@ #include #include #include +#include -static inline int maybe_allow(void) +static inline int maybe_allow(unsigned long network_flags) { - if (current->network) + if ((network_flags & PR_NETWORK_DN_FLAGS) == PR_NETWORK_DN_FLAGS) return -EPERM; return 0; } @@ -32,7 +33,7 @@ int disablenetwork_security_socket_create(int family, int type, { if (family == AF_UNIX) return 0; - return maybe_allow(); + return maybe_allow(current->network); } int disablenetwork_security_socket_bind(struct socket * sock, @@ -41,7 +42,7 @@ int disablenetwork_security_socket_bind(struct socket * sock, { if (address->sa_family == AF_UNIX) return 0; - return maybe_allow(); + return maybe_allow(current->network); } int disablenetwork_security_socket_connect(struct socket * sock, @@ -50,7 +51,7 @@ int disablenetwork_security_socket_connect(struct socket * sock, { if (address->sa_family == AF_UNIX) return 0; - return maybe_allow(); + return maybe_allow(current->network); } int disablenetwork_security_socket_sendmsg(struct socket * sock, @@ -59,14 +60,14 @@ int disablenetwork_security_socket_sendmsg(struct socket * sock, /* permit sockets which are PF_UNIX or connected; check others. */ if (sock->sk->sk_family == PF_UNIX || msg->msg_name == NULL) return 0; - return maybe_allow(); + return maybe_allow(current->network); } int disablenetwork_security_ptrace_access_check(struct task_struct *child, unsigned int mode) { /* does current have networking restrictions not shared by child? */ - if (current->network & ~child->network) + if (maybe_allow(current->network) && !maybe_allow(child->network)) return -EPERM; return 0; } -- 1.6.6.rc2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/