From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753362Ab0AQC6t (ORCPT ); Sat, 16 Jan 2010 21:58:49 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753250Ab0AQC6s (ORCPT ); Sat, 16 Jan 2010 21:58:48 -0500 Received: from mail-pw0-f42.google.com ([209.85.160.42]:41583 "EHLO mail-pw0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753229Ab0AQC6q convert rfc822-to-8bit (ORCPT ); Sat, 16 Jan 2010 21:58:46 -0500 MIME-Version: 1.0 In-Reply-To: <20100115081308.GA14443@heat> References: <20100115081028.GA14004@heat> <20100115081308.GA14443@heat> Date: Sat, 16 Jan 2010 18:58:41 -0800 X-Google-Sender-Auth: a20fa5b47c2cc449 Message-ID: <551280e51001161858q740bf246n2ed389920de689e7@mail.gmail.com> Subject: Re: disablenetwork (v5): Require CAP_SETPCAP to enable disablenetwork. From: "Andrew G. Morgan" To: Michael Stone Cc: linux-kernel@vger.kernel.org, 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 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Jan 15, 2010 at 12:13 AM, Michael Stone wrote: > 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)) Please use CAP_NET_ADMIN for this feature (and add the corresponding comment in include/linux/capabilities.h). Thanks Andrew > +               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 >