Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-08-21 Thread Paul Moore
On Fri, Jul 24, 2015 at 6:04 AM, Lukasz Pawelczyk
 wrote:
> This commit implements 3 new LSM hooks that provide the means for LSMs
> to embed their own security context within user namespace, effectively
> creating some sort of a user_ns related security namespace.
>
> The first one to take advantage of this mechanism is Smack.
>
> The hooks has been documented in the in the security.h below.
>
> Signed-off-by: Lukasz Pawelczyk 
> Reviewed-by: Casey Schaufler 
> ---
>  include/linux/lsm_hooks.h  | 28 
>  include/linux/security.h   | 23 +++
>  include/linux/user_namespace.h |  4 
>  kernel/user.c  |  3 +++
>  kernel/user_namespace.c| 18 ++
>  security/security.c| 28 
>  6 files changed, 104 insertions(+)

I'm not sure at this point in time we know what we want to do with
SELinux and these hooks, if anything, but they look reasonable to me.

Acked-by: Paul Moore 

> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 9429f05..228558c 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -1261,6 +1261,23 @@
>   * audit_rule_init.
>   * @rule contains the allocated rule
>   *
> + * @userns_create:
> + * Allocates and fills the security part of a new user namespace.
> + * @ns points to a newly created user namespace.
> + * Returns 0 or an error code.
> + *
> + * @userns_free:
> + * Deallocates the security part of a user namespace.
> + * @ns points to a user namespace about to be destroyed.
> + *
> + * @userns_setns:
> + * Run during a setns syscall to add a process to an already existing
> + * user namespace. Returning failure here will block the operation
> + * requested from userspace (setns() with CLONE_NEWUSER).
> + * @nsproxy contains nsproxy to which the user namespace will be 
> assigned.
> + * @ns contains user namespace that is to be incorporated to the nsproxy.
> + * Returns 0 or an error code.
> + *
>   * @inode_notifysecctx:
>   * Notify the security module of what the security context of an inode
>   * should be.  Initializes the incore security context managed by the
> @@ -1613,6 +1630,12 @@ union security_list_options {
> struct audit_context *actx);
> void (*audit_rule_free)(void *lsmrule);
>  #endif /* CONFIG_AUDIT */
> +
> +#ifdef CONFIG_USER_NS
> +   int (*userns_create)(struct user_namespace *ns);
> +   void (*userns_free)(struct user_namespace *ns);
> +   int (*userns_setns)(struct nsproxy *nsproxy, struct user_namespace 
> *ns);
> +#endif /* CONFIG_USER_NS */
>  };
>
>  struct security_hook_heads {
> @@ -1824,6 +1847,11 @@ struct security_hook_heads {
> struct list_head audit_rule_match;
> struct list_head audit_rule_free;
>  #endif /* CONFIG_AUDIT */
> +#ifdef CONFIG_USER_NS
> +   struct list_head userns_create;
> +   struct list_head userns_free;
> +   struct list_head userns_setns;
> +#endif /* CONFIG_USER_NS */
>  };
>
>  /*
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 79d85dd..1b0eccc 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1584,6 +1584,29 @@ static inline void security_audit_rule_free(void 
> *lsmrule)
>  #endif /* CONFIG_SECURITY */
>  #endif /* CONFIG_AUDIT */
>
> +#ifdef CONFIG_USER_NS
> +int security_userns_create(struct user_namespace *ns);
> +void security_userns_free(struct user_namespace *ns);
> +int security_userns_setns(struct nsproxy *nsproxy, struct user_namespace 
> *ns);
> +
> +#else
> +
> +static inline int security_userns_create(struct user_namespace *ns)
> +{
> +   return 0;
> +}
> +
> +static inline void security_userns_free(struct user_namespace *ns)
> +{ }
> +
> +static inline int security_userns_setns(struct nsproxy *nsproxy,
> +   struct user_namespace *ns)
> +{
> +   return 0;
> +}
> +
> +#endif /* CONFIG_USER_NS */
> +
>  #ifdef CONFIG_SECURITYFS
>
>  extern struct dentry *securityfs_create_file(const char *name, umode_t mode,
> diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
> index 8297e5b..a9400cc 100644
> --- a/include/linux/user_namespace.h
> +++ b/include/linux/user_namespace.h
> @@ -39,6 +39,10 @@ struct user_namespace {
> struct key  *persistent_keyring_register;
> struct rw_semaphore persistent_keyring_register_sem;
>  #endif
> +
> +#ifdef CONFIG_SECURITY
> +   void *security;
> +#endif
>  };
>
>  extern struct user_namespace init_user_ns;
> diff --git a/kernel/user.c b/kernel/user.c
> index b069ccb..ce5419e 100644
> --- a/kernel/user.c
> +++ b/kernel/user.c
> @@ -59,6 +59,9 @@ struct user_namespace init_user_ns = {
> .persistent_keyring_register_sem =
> __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
>  #endif
> 

Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-08-21 Thread Paul Moore
On Fri, Jul 24, 2015 at 6:04 AM, Lukasz Pawelczyk
l.pawelc...@samsung.com wrote:
 This commit implements 3 new LSM hooks that provide the means for LSMs
 to embed their own security context within user namespace, effectively
 creating some sort of a user_ns related security namespace.

 The first one to take advantage of this mechanism is Smack.

 The hooks has been documented in the in the security.h below.

 Signed-off-by: Lukasz Pawelczyk l.pawelc...@samsung.com
 Reviewed-by: Casey Schaufler ca...@schaufler-ca.com
 ---
  include/linux/lsm_hooks.h  | 28 
  include/linux/security.h   | 23 +++
  include/linux/user_namespace.h |  4 
  kernel/user.c  |  3 +++
  kernel/user_namespace.c| 18 ++
  security/security.c| 28 
  6 files changed, 104 insertions(+)

I'm not sure at this point in time we know what we want to do with
SELinux and these hooks, if anything, but they look reasonable to me.

Acked-by: Paul Moore p...@paul-moore.com

 diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
 index 9429f05..228558c 100644
 --- a/include/linux/lsm_hooks.h
 +++ b/include/linux/lsm_hooks.h
 @@ -1261,6 +1261,23 @@
   * audit_rule_init.
   * @rule contains the allocated rule
   *
 + * @userns_create:
 + * Allocates and fills the security part of a new user namespace.
 + * @ns points to a newly created user namespace.
 + * Returns 0 or an error code.
 + *
 + * @userns_free:
 + * Deallocates the security part of a user namespace.
 + * @ns points to a user namespace about to be destroyed.
 + *
 + * @userns_setns:
 + * Run during a setns syscall to add a process to an already existing
 + * user namespace. Returning failure here will block the operation
 + * requested from userspace (setns() with CLONE_NEWUSER).
 + * @nsproxy contains nsproxy to which the user namespace will be 
 assigned.
 + * @ns contains user namespace that is to be incorporated to the nsproxy.
 + * Returns 0 or an error code.
 + *
   * @inode_notifysecctx:
   * Notify the security module of what the security context of an inode
   * should be.  Initializes the incore security context managed by the
 @@ -1613,6 +1630,12 @@ union security_list_options {
 struct audit_context *actx);
 void (*audit_rule_free)(void *lsmrule);
  #endif /* CONFIG_AUDIT */
 +
 +#ifdef CONFIG_USER_NS
 +   int (*userns_create)(struct user_namespace *ns);
 +   void (*userns_free)(struct user_namespace *ns);
 +   int (*userns_setns)(struct nsproxy *nsproxy, struct user_namespace 
 *ns);
 +#endif /* CONFIG_USER_NS */
  };

  struct security_hook_heads {
 @@ -1824,6 +1847,11 @@ struct security_hook_heads {
 struct list_head audit_rule_match;
 struct list_head audit_rule_free;
  #endif /* CONFIG_AUDIT */
 +#ifdef CONFIG_USER_NS
 +   struct list_head userns_create;
 +   struct list_head userns_free;
 +   struct list_head userns_setns;
 +#endif /* CONFIG_USER_NS */
  };

  /*
 diff --git a/include/linux/security.h b/include/linux/security.h
 index 79d85dd..1b0eccc 100644
 --- a/include/linux/security.h
 +++ b/include/linux/security.h
 @@ -1584,6 +1584,29 @@ static inline void security_audit_rule_free(void 
 *lsmrule)
  #endif /* CONFIG_SECURITY */
  #endif /* CONFIG_AUDIT */

 +#ifdef CONFIG_USER_NS
 +int security_userns_create(struct user_namespace *ns);
 +void security_userns_free(struct user_namespace *ns);
 +int security_userns_setns(struct nsproxy *nsproxy, struct user_namespace 
 *ns);
 +
 +#else
 +
 +static inline int security_userns_create(struct user_namespace *ns)
 +{
 +   return 0;
 +}
 +
 +static inline void security_userns_free(struct user_namespace *ns)
 +{ }
 +
 +static inline int security_userns_setns(struct nsproxy *nsproxy,
 +   struct user_namespace *ns)
 +{
 +   return 0;
 +}
 +
 +#endif /* CONFIG_USER_NS */
 +
  #ifdef CONFIG_SECURITYFS

  extern struct dentry *securityfs_create_file(const char *name, umode_t mode,
 diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
 index 8297e5b..a9400cc 100644
 --- a/include/linux/user_namespace.h
 +++ b/include/linux/user_namespace.h
 @@ -39,6 +39,10 @@ struct user_namespace {
 struct key  *persistent_keyring_register;
 struct rw_semaphore persistent_keyring_register_sem;
  #endif
 +
 +#ifdef CONFIG_SECURITY
 +   void *security;
 +#endif
  };

  extern struct user_namespace init_user_ns;
 diff --git a/kernel/user.c b/kernel/user.c
 index b069ccb..ce5419e 100644
 --- a/kernel/user.c
 +++ b/kernel/user.c
 @@ -59,6 +59,9 @@ struct user_namespace init_user_ns = {
 .persistent_keyring_register_sem =
 __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
  #endif
 +#ifdef CONFIG_SECURITY
 +   .security = NULL,

Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-08-20 Thread Paul Moore
On Mon, Aug 3, 2015 at 9:38 PM, Kees Cook  wrote:
> On Mon, Aug 3, 2015 at 4:34 AM, Lukasz Pawelczyk
>  wrote:
>> On pią, 2015-07-31 at 22:48 -0500, Serge E. Hallyn wrote:
>>> On Fri, Jul 31, 2015 at 11:28:56AM +0200, Lukasz Pawelczyk wrote:
>>> > On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
>>> > > On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
>>> > > > @@ -969,6 +982,7 @@ static int userns_install(struct nsproxy
>>> > > > *nsproxy, struct ns_common *ns)
>>> > > >  {
>>> > > > struct user_namespace *user_ns = to_user_ns(ns);
>>> > > > struct cred *cred;
>>> > > > +   int err;
>>> > > >
>>> > > > /* Don't allow gaining capabilities by reentering
>>> > > >  * the same user namespace.
>>> > > > @@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy
>>> > > > *nsproxy, struct ns_common *ns)
>>> > > > if (!ns_capable(user_ns, CAP_SYS_ADMIN))
>>> > > > return -EPERM;
>>> > > >
>>> > > > +   err = security_userns_setns(nsproxy, user_ns);
>>> > > > +   if (err)
>>> > > > +   return err;
>>> > >
>>> > > So at this point the LSM thinks current is in the new ns.  If
>>> > > prepare_creds() fails below, should it be informed of that?
>>> > > (Or am I over-thinking this?)
>>> > >
>>> > > > +
>>> > > > cred = prepare_creds();
>>> > > > if (!cred)
>>> > > > return -ENOMEM;
>>> >
>>> > Hmm, the use case for this hook I had in mind was just to allow or
>>> > disallow the operation based on the information passed in
>>> > arguments.
>>> > Not to register the current in any way so LSM can think it is or
>>> > isn't
>>> > in the new namespace.
>>> >
>>> > I think that any other LSM check that would like to know in what
>>> > namespace the current is, would just check that from current's
>>> > creds.
>>> > Not use some stale and duplicated information the above hook could
>>> > have
>>> > registered.
>>> >
>>> > I see no reason for this hook to change the LSM state, only to
>>> > answer
>>> > the question: allowed/disallowed (eventually return an error cause
>>> > it
>>> > is unable to give an answer which falls into the disallow
>>> > category).
>>>
>>> How about renaming it "security_userns_may_setns()" for clarity?
>>
>> I personally have nothing against it. However looking at already
>> existing hooks only one of them has "may" in the name (unix_may_send)
>> while a lot clearly have exactly this purpose (e.g. most of inode_*
>> family, some from file_* and task_*). So it seems the trend is against
>> it.
>>
>> What do you think? Anyone else has an opinion?
>
> Personally, I prefer that hooks be named as closely to their caller,
> or calling context, as possible. In this case, it seems like "may" is
> implied. It's an LSM like all the others, so it can fail, which would
> cause the caller to fail too, so "may" tends to be implicit. I would
> leave it as-is, but I could be convinced otherwise.

I agree with Kees, sticking as close as possible to the general format
of "security_" for LSM hooks makes it easier when
reading/reviewing code.

-- 
paul moore
www.paul-moore.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-08-20 Thread Paul Moore
On Mon, Aug 3, 2015 at 9:38 PM, Kees Cook keesc...@chromium.org wrote:
 On Mon, Aug 3, 2015 at 4:34 AM, Lukasz Pawelczyk
 l.pawelc...@samsung.com wrote:
 On pią, 2015-07-31 at 22:48 -0500, Serge E. Hallyn wrote:
 On Fri, Jul 31, 2015 at 11:28:56AM +0200, Lukasz Pawelczyk wrote:
  On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
   On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
@@ -969,6 +982,7 @@ static int userns_install(struct nsproxy
*nsproxy, struct ns_common *ns)
 {
struct user_namespace *user_ns = to_user_ns(ns);
struct cred *cred;
+   int err;
   
/* Don't allow gaining capabilities by reentering
 * the same user namespace.
@@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy
*nsproxy, struct ns_common *ns)
if (!ns_capable(user_ns, CAP_SYS_ADMIN))
return -EPERM;
   
+   err = security_userns_setns(nsproxy, user_ns);
+   if (err)
+   return err;
  
   So at this point the LSM thinks current is in the new ns.  If
   prepare_creds() fails below, should it be informed of that?
   (Or am I over-thinking this?)
  
+
cred = prepare_creds();
if (!cred)
return -ENOMEM;
 
  Hmm, the use case for this hook I had in mind was just to allow or
  disallow the operation based on the information passed in
  arguments.
  Not to register the current in any way so LSM can think it is or
  isn't
  in the new namespace.
 
  I think that any other LSM check that would like to know in what
  namespace the current is, would just check that from current's
  creds.
  Not use some stale and duplicated information the above hook could
  have
  registered.
 
  I see no reason for this hook to change the LSM state, only to
  answer
  the question: allowed/disallowed (eventually return an error cause
  it
  is unable to give an answer which falls into the disallow
  category).

 How about renaming it security_userns_may_setns() for clarity?

 I personally have nothing against it. However looking at already
 existing hooks only one of them has may in the name (unix_may_send)
 while a lot clearly have exactly this purpose (e.g. most of inode_*
 family, some from file_* and task_*). So it seems the trend is against
 it.

 What do you think? Anyone else has an opinion?

 Personally, I prefer that hooks be named as closely to their caller,
 or calling context, as possible. In this case, it seems like may is
 implied. It's an LSM like all the others, so it can fail, which would
 cause the caller to fail too, so may tends to be implicit. I would
 leave it as-is, but I could be convinced otherwise.

I agree with Kees, sticking as close as possible to the general format
of security_caller for LSM hooks makes it easier when
reading/reviewing code.

-- 
paul moore
www.paul-moore.com
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-08-03 Thread Kees Cook
On Mon, Aug 3, 2015 at 4:34 AM, Lukasz Pawelczyk
 wrote:
> On pią, 2015-07-31 at 22:48 -0500, Serge E. Hallyn wrote:
>> On Fri, Jul 31, 2015 at 11:28:56AM +0200, Lukasz Pawelczyk wrote:
>> > On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
>> > > On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
>> > > > @@ -969,6 +982,7 @@ static int userns_install(struct nsproxy
>> > > > *nsproxy, struct ns_common *ns)
>> > > >  {
>> > > > struct user_namespace *user_ns = to_user_ns(ns);
>> > > > struct cred *cred;
>> > > > +   int err;
>> > > >
>> > > > /* Don't allow gaining capabilities by reentering
>> > > >  * the same user namespace.
>> > > > @@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy
>> > > > *nsproxy, struct ns_common *ns)
>> > > > if (!ns_capable(user_ns, CAP_SYS_ADMIN))
>> > > > return -EPERM;
>> > > >
>> > > > +   err = security_userns_setns(nsproxy, user_ns);
>> > > > +   if (err)
>> > > > +   return err;
>> > >
>> > > So at this point the LSM thinks current is in the new ns.  If
>> > > prepare_creds() fails below, should it be informed of that?
>> > > (Or am I over-thinking this?)
>> > >
>> > > > +
>> > > > cred = prepare_creds();
>> > > > if (!cred)
>> > > > return -ENOMEM;
>> >
>> > Hmm, the use case for this hook I had in mind was just to allow or
>> > disallow the operation based on the information passed in
>> > arguments.
>> > Not to register the current in any way so LSM can think it is or
>> > isn't
>> > in the new namespace.
>> >
>> > I think that any other LSM check that would like to know in what
>> > namespace the current is, would just check that from current's
>> > creds.
>> > Not use some stale and duplicated information the above hook could
>> > have
>> > registered.
>> >
>> > I see no reason for this hook to change the LSM state, only to
>> > answer
>> > the question: allowed/disallowed (eventually return an error cause
>> > it
>> > is unable to give an answer which falls into the disallow
>> > category).
>>
>> How about renaming it "security_userns_may_setns()" for clarity?
>
> I personally have nothing against it. However looking at already
> existing hooks only one of them has "may" in the name (unix_may_send)
> while a lot clearly have exactly this purpose (e.g. most of inode_*
> family, some from file_* and task_*). So it seems the trend is against
> it.
>
> What do you think? Anyone else has an opinion?

Personally, I prefer that hooks be named as closely to their caller,
or calling context, as possible. In this case, it seems like "may" is
implied. It's an LSM like all the others, so it can fail, which would
cause the caller to fail too, so "may" tends to be implicit. I would
leave it as-is, but I could be convinced otherwise.

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-08-03 Thread Lukasz Pawelczyk
On pią, 2015-07-31 at 22:48 -0500, Serge E. Hallyn wrote:
> On Fri, Jul 31, 2015 at 11:28:56AM +0200, Lukasz Pawelczyk wrote:
> > On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
> > > On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
> > > > @@ -969,6 +982,7 @@ static int userns_install(struct nsproxy 
> > > > *nsproxy, struct ns_common *ns)
> > > >  {
> > > > struct user_namespace *user_ns = to_user_ns(ns);
> > > > struct cred *cred;
> > > > +   int err;
> > > >  
> > > > /* Don't allow gaining capabilities by reentering
> > > >  * the same user namespace.
> > > > @@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy 
> > > > *nsproxy, struct ns_common *ns)
> > > > if (!ns_capable(user_ns, CAP_SYS_ADMIN))
> > > > return -EPERM;
> > > >  
> > > > +   err = security_userns_setns(nsproxy, user_ns);
> > > > +   if (err)
> > > > +   return err;
> > > 
> > > So at this point the LSM thinks current is in the new ns.  If
> > > prepare_creds() fails below, should it be informed of that?
> > > (Or am I over-thinking this?)
> > > 
> > > > +
> > > > cred = prepare_creds();
> > > > if (!cred)
> > > > return -ENOMEM;
> > 
> > Hmm, the use case for this hook I had in mind was just to allow or
> > disallow the operation based on the information passed in 
> > arguments.
> > Not to register the current in any way so LSM can think it is or 
> > isn't
> > in the new namespace.
> > 
> > I think that any other LSM check that would like to know in what
> > namespace the current is, would just check that from current's 
> > creds.
> > Not use some stale and duplicated information the above hook could 
> > have
> > registered.
> > 
> > I see no reason for this hook to change the LSM state, only to 
> > answer
> > the question: allowed/disallowed (eventually return an error cause 
> > it
> > is unable to give an answer which falls into the disallow 
> > category).
> 
> How about renaming it "security_userns_may_setns()" for clarity?

I personally have nothing against it. However looking at already
existing hooks only one of them has "may" in the name (unix_may_send)
while a lot clearly have exactly this purpose (e.g. most of inode_*
family, some from file_* and task_*). So it seems the trend is against
it.

What do you think? Anyone else has an opinion?



-- 
Lukasz Pawelczyk
Samsung R Institute Poland
Samsung Electronics



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-08-03 Thread Kees Cook
On Mon, Aug 3, 2015 at 4:34 AM, Lukasz Pawelczyk
l.pawelc...@samsung.com wrote:
 On pią, 2015-07-31 at 22:48 -0500, Serge E. Hallyn wrote:
 On Fri, Jul 31, 2015 at 11:28:56AM +0200, Lukasz Pawelczyk wrote:
  On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
   On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
@@ -969,6 +982,7 @@ static int userns_install(struct nsproxy
*nsproxy, struct ns_common *ns)
 {
struct user_namespace *user_ns = to_user_ns(ns);
struct cred *cred;
+   int err;
   
/* Don't allow gaining capabilities by reentering
 * the same user namespace.
@@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy
*nsproxy, struct ns_common *ns)
if (!ns_capable(user_ns, CAP_SYS_ADMIN))
return -EPERM;
   
+   err = security_userns_setns(nsproxy, user_ns);
+   if (err)
+   return err;
  
   So at this point the LSM thinks current is in the new ns.  If
   prepare_creds() fails below, should it be informed of that?
   (Or am I over-thinking this?)
  
+
cred = prepare_creds();
if (!cred)
return -ENOMEM;
 
  Hmm, the use case for this hook I had in mind was just to allow or
  disallow the operation based on the information passed in
  arguments.
  Not to register the current in any way so LSM can think it is or
  isn't
  in the new namespace.
 
  I think that any other LSM check that would like to know in what
  namespace the current is, would just check that from current's
  creds.
  Not use some stale and duplicated information the above hook could
  have
  registered.
 
  I see no reason for this hook to change the LSM state, only to
  answer
  the question: allowed/disallowed (eventually return an error cause
  it
  is unable to give an answer which falls into the disallow
  category).

 How about renaming it security_userns_may_setns() for clarity?

 I personally have nothing against it. However looking at already
 existing hooks only one of them has may in the name (unix_may_send)
 while a lot clearly have exactly this purpose (e.g. most of inode_*
 family, some from file_* and task_*). So it seems the trend is against
 it.

 What do you think? Anyone else has an opinion?

Personally, I prefer that hooks be named as closely to their caller,
or calling context, as possible. In this case, it seems like may is
implied. It's an LSM like all the others, so it can fail, which would
cause the caller to fail too, so may tends to be implicit. I would
leave it as-is, but I could be convinced otherwise.

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-08-03 Thread Lukasz Pawelczyk
On pią, 2015-07-31 at 22:48 -0500, Serge E. Hallyn wrote:
 On Fri, Jul 31, 2015 at 11:28:56AM +0200, Lukasz Pawelczyk wrote:
  On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
   On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
@@ -969,6 +982,7 @@ static int userns_install(struct nsproxy 
*nsproxy, struct ns_common *ns)
 {
struct user_namespace *user_ns = to_user_ns(ns);
struct cred *cred;
+   int err;
 
/* Don't allow gaining capabilities by reentering
 * the same user namespace.
@@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy 
*nsproxy, struct ns_common *ns)
if (!ns_capable(user_ns, CAP_SYS_ADMIN))
return -EPERM;
 
+   err = security_userns_setns(nsproxy, user_ns);
+   if (err)
+   return err;
   
   So at this point the LSM thinks current is in the new ns.  If
   prepare_creds() fails below, should it be informed of that?
   (Or am I over-thinking this?)
   
+
cred = prepare_creds();
if (!cred)
return -ENOMEM;
  
  Hmm, the use case for this hook I had in mind was just to allow or
  disallow the operation based on the information passed in 
  arguments.
  Not to register the current in any way so LSM can think it is or 
  isn't
  in the new namespace.
  
  I think that any other LSM check that would like to know in what
  namespace the current is, would just check that from current's 
  creds.
  Not use some stale and duplicated information the above hook could 
  have
  registered.
  
  I see no reason for this hook to change the LSM state, only to 
  answer
  the question: allowed/disallowed (eventually return an error cause 
  it
  is unable to give an answer which falls into the disallow 
  category).
 
 How about renaming it security_userns_may_setns() for clarity?

I personally have nothing against it. However looking at already
existing hooks only one of them has may in the name (unix_may_send)
while a lot clearly have exactly this purpose (e.g. most of inode_*
family, some from file_* and task_*). So it seems the trend is against
it.

What do you think? Anyone else has an opinion?



-- 
Lukasz Pawelczyk
Samsung RD Institute Poland
Samsung Electronics



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-07-31 Thread Serge E. Hallyn
On Fri, Jul 31, 2015 at 11:28:56AM +0200, Lukasz Pawelczyk wrote:
> On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
> > On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
> > > @@ -969,6 +982,7 @@ static int userns_install(struct nsproxy 
> > > *nsproxy, struct ns_common *ns)
> > >  {
> > >   struct user_namespace *user_ns = to_user_ns(ns);
> > >   struct cred *cred;
> > > + int err;
> > >  
> > >   /* Don't allow gaining capabilities by reentering
> > >* the same user namespace.
> > > @@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy 
> > > *nsproxy, struct ns_common *ns)
> > >   if (!ns_capable(user_ns, CAP_SYS_ADMIN))
> > >   return -EPERM;
> > >  
> > > + err = security_userns_setns(nsproxy, user_ns);
> > > + if (err)
> > > + return err;
> > 
> > So at this point the LSM thinks current is in the new ns.  If
> > prepare_creds() fails below, should it be informed of that?
> > (Or am I over-thinking this?)
> > 
> > > +
> > >   cred = prepare_creds();
> > >   if (!cred)
> > >   return -ENOMEM;
> 
> Hmm, the use case for this hook I had in mind was just to allow or
> disallow the operation based on the information passed in arguments.
> Not to register the current in any way so LSM can think it is or isn't
> in the new namespace.
> 
> I think that any other LSM check that would like to know in what
> namespace the current is, would just check that from current's creds.
> Not use some stale and duplicated information the above hook could have
> registered.
> 
> I see no reason for this hook to change the LSM state, only to answer
> the question: allowed/disallowed (eventually return an error cause it
> is unable to give an answer which falls into the disallow category).

How about renaming it "security_userns_may_setns()" for clarity?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-07-31 Thread Lukasz Pawelczyk
On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
> On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
> > @@ -969,6 +982,7 @@ static int userns_install(struct nsproxy 
> > *nsproxy, struct ns_common *ns)
> >  {
> > struct user_namespace *user_ns = to_user_ns(ns);
> > struct cred *cred;
> > +   int err;
> >  
> > /* Don't allow gaining capabilities by reentering
> >  * the same user namespace.
> > @@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy 
> > *nsproxy, struct ns_common *ns)
> > if (!ns_capable(user_ns, CAP_SYS_ADMIN))
> > return -EPERM;
> >  
> > +   err = security_userns_setns(nsproxy, user_ns);
> > +   if (err)
> > +   return err;
> 
> So at this point the LSM thinks current is in the new ns.  If
> prepare_creds() fails below, should it be informed of that?
> (Or am I over-thinking this?)
> 
> > +
> > cred = prepare_creds();
> > if (!cred)
> > return -ENOMEM;

Hmm, the use case for this hook I had in mind was just to allow or
disallow the operation based on the information passed in arguments.
Not to register the current in any way so LSM can think it is or isn't
in the new namespace.

I think that any other LSM check that would like to know in what
namespace the current is, would just check that from current's creds.
Not use some stale and duplicated information the above hook could have
registered.

I see no reason for this hook to change the LSM state, only to answer
the question: allowed/disallowed (eventually return an error cause it
is unable to give an answer which falls into the disallow category).


-- 
Lukasz Pawelczyk
Samsung R Institute Poland
Samsung Electronics



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-07-31 Thread Serge E. Hallyn
On Fri, Jul 31, 2015 at 11:28:56AM +0200, Lukasz Pawelczyk wrote:
 On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
  On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
   @@ -969,6 +982,7 @@ static int userns_install(struct nsproxy 
   *nsproxy, struct ns_common *ns)
{
 struct user_namespace *user_ns = to_user_ns(ns);
 struct cred *cred;
   + int err;

 /* Don't allow gaining capabilities by reentering
  * the same user namespace.
   @@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy 
   *nsproxy, struct ns_common *ns)
 if (!ns_capable(user_ns, CAP_SYS_ADMIN))
 return -EPERM;

   + err = security_userns_setns(nsproxy, user_ns);
   + if (err)
   + return err;
  
  So at this point the LSM thinks current is in the new ns.  If
  prepare_creds() fails below, should it be informed of that?
  (Or am I over-thinking this?)
  
   +
 cred = prepare_creds();
 if (!cred)
 return -ENOMEM;
 
 Hmm, the use case for this hook I had in mind was just to allow or
 disallow the operation based on the information passed in arguments.
 Not to register the current in any way so LSM can think it is or isn't
 in the new namespace.
 
 I think that any other LSM check that would like to know in what
 namespace the current is, would just check that from current's creds.
 Not use some stale and duplicated information the above hook could have
 registered.
 
 I see no reason for this hook to change the LSM state, only to answer
 the question: allowed/disallowed (eventually return an error cause it
 is unable to give an answer which falls into the disallow category).

How about renaming it security_userns_may_setns() for clarity?
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-07-31 Thread Lukasz Pawelczyk
On czw, 2015-07-30 at 16:30 -0500, Serge E. Hallyn wrote:
 On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
  @@ -969,6 +982,7 @@ static int userns_install(struct nsproxy 
  *nsproxy, struct ns_common *ns)
   {
  struct user_namespace *user_ns = to_user_ns(ns);
  struct cred *cred;
  +   int err;
   
  /* Don't allow gaining capabilities by reentering
   * the same user namespace.
  @@ -986,6 +1000,10 @@ static int userns_install(struct nsproxy 
  *nsproxy, struct ns_common *ns)
  if (!ns_capable(user_ns, CAP_SYS_ADMIN))
  return -EPERM;
   
  +   err = security_userns_setns(nsproxy, user_ns);
  +   if (err)
  +   return err;
 
 So at this point the LSM thinks current is in the new ns.  If
 prepare_creds() fails below, should it be informed of that?
 (Or am I over-thinking this?)
 
  +
  cred = prepare_creds();
  if (!cred)
  return -ENOMEM;

Hmm, the use case for this hook I had in mind was just to allow or
disallow the operation based on the information passed in arguments.
Not to register the current in any way so LSM can think it is or isn't
in the new namespace.

I think that any other LSM check that would like to know in what
namespace the current is, would just check that from current's creds.
Not use some stale and duplicated information the above hook could have
registered.

I see no reason for this hook to change the LSM state, only to answer
the question: allowed/disallowed (eventually return an error cause it
is unable to give an answer which falls into the disallow category).


-- 
Lukasz Pawelczyk
Samsung RD Institute Poland
Samsung Electronics



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-07-30 Thread Serge E. Hallyn
On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
> This commit implements 3 new LSM hooks that provide the means for LSMs
> to embed their own security context within user namespace, effectively
> creating some sort of a user_ns related security namespace.
> 
> The first one to take advantage of this mechanism is Smack.
> 
> The hooks has been documented in the in the security.h below.
> 
> Signed-off-by: Lukasz Pawelczyk 
> Reviewed-by: Casey Schaufler 
> ---
>  include/linux/lsm_hooks.h  | 28 
>  include/linux/security.h   | 23 +++
>  include/linux/user_namespace.h |  4 
>  kernel/user.c  |  3 +++
>  kernel/user_namespace.c| 18 ++
>  security/security.c| 28 
>  6 files changed, 104 insertions(+)
> 
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 9429f05..228558c 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -1261,6 +1261,23 @@
>   *   audit_rule_init.
>   *   @rule contains the allocated rule
>   *
> + * @userns_create:
> + *   Allocates and fills the security part of a new user namespace.
> + *   @ns points to a newly created user namespace.
> + *   Returns 0 or an error code.
> + *
> + * @userns_free:
> + *   Deallocates the security part of a user namespace.
> + *   @ns points to a user namespace about to be destroyed.
> + *
> + * @userns_setns:
> + *   Run during a setns syscall to add a process to an already existing
> + *   user namespace. Returning failure here will block the operation
> + *   requested from userspace (setns() with CLONE_NEWUSER).
> + *   @nsproxy contains nsproxy to which the user namespace will be assigned.
> + *   @ns contains user namespace that is to be incorporated to the nsproxy.
> + *   Returns 0 or an error code.
> + *
>   * @inode_notifysecctx:
>   *   Notify the security module of what the security context of an inode
>   *   should be.  Initializes the incore security context managed by the
> @@ -1613,6 +1630,12 @@ union security_list_options {
>   struct audit_context *actx);
>   void (*audit_rule_free)(void *lsmrule);
>  #endif /* CONFIG_AUDIT */
> +
> +#ifdef CONFIG_USER_NS
> + int (*userns_create)(struct user_namespace *ns);
> + void (*userns_free)(struct user_namespace *ns);
> + int (*userns_setns)(struct nsproxy *nsproxy, struct user_namespace *ns);
> +#endif /* CONFIG_USER_NS */
>  };
>  
>  struct security_hook_heads {
> @@ -1824,6 +1847,11 @@ struct security_hook_heads {
>   struct list_head audit_rule_match;
>   struct list_head audit_rule_free;
>  #endif /* CONFIG_AUDIT */
> +#ifdef CONFIG_USER_NS
> + struct list_head userns_create;
> + struct list_head userns_free;
> + struct list_head userns_setns;
> +#endif /* CONFIG_USER_NS */
>  };
>  
>  /*
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 79d85dd..1b0eccc 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1584,6 +1584,29 @@ static inline void security_audit_rule_free(void 
> *lsmrule)
>  #endif /* CONFIG_SECURITY */
>  #endif /* CONFIG_AUDIT */
>  
> +#ifdef CONFIG_USER_NS
> +int security_userns_create(struct user_namespace *ns);
> +void security_userns_free(struct user_namespace *ns);
> +int security_userns_setns(struct nsproxy *nsproxy, struct user_namespace 
> *ns);
> +
> +#else
> +
> +static inline int security_userns_create(struct user_namespace *ns)
> +{
> + return 0;
> +}
> +
> +static inline void security_userns_free(struct user_namespace *ns)
> +{ }
> +
> +static inline int security_userns_setns(struct nsproxy *nsproxy,
> + struct user_namespace *ns)
> +{
> + return 0;
> +}
> +
> +#endif /* CONFIG_USER_NS */
> +
>  #ifdef CONFIG_SECURITYFS
>  
>  extern struct dentry *securityfs_create_file(const char *name, umode_t mode,
> diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
> index 8297e5b..a9400cc 100644
> --- a/include/linux/user_namespace.h
> +++ b/include/linux/user_namespace.h
> @@ -39,6 +39,10 @@ struct user_namespace {
>   struct key  *persistent_keyring_register;
>   struct rw_semaphore persistent_keyring_register_sem;
>  #endif
> +
> +#ifdef CONFIG_SECURITY
> + void *security;
> +#endif
>  };
>  
>  extern struct user_namespace init_user_ns;
> diff --git a/kernel/user.c b/kernel/user.c
> index b069ccb..ce5419e 100644
> --- a/kernel/user.c
> +++ b/kernel/user.c
> @@ -59,6 +59,9 @@ struct user_namespace init_user_ns = {
>   .persistent_keyring_register_sem =
>   __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
>  #endif
> +#ifdef CONFIG_SECURITY
> + .security = NULL,
> +#endif
>  };
>  EXPORT_SYMBOL_GPL(init_user_ns);
>  
> diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
> index 4109f83..cadffb6 100644
> --- 

Re: [PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-07-30 Thread Serge E. Hallyn
On Fri, Jul 24, 2015 at 12:04:35PM +0200, Lukasz Pawelczyk wrote:
 This commit implements 3 new LSM hooks that provide the means for LSMs
 to embed their own security context within user namespace, effectively
 creating some sort of a user_ns related security namespace.
 
 The first one to take advantage of this mechanism is Smack.
 
 The hooks has been documented in the in the security.h below.
 
 Signed-off-by: Lukasz Pawelczyk l.pawelc...@samsung.com
 Reviewed-by: Casey Schaufler ca...@schaufler-ca.com
 ---
  include/linux/lsm_hooks.h  | 28 
  include/linux/security.h   | 23 +++
  include/linux/user_namespace.h |  4 
  kernel/user.c  |  3 +++
  kernel/user_namespace.c| 18 ++
  security/security.c| 28 
  6 files changed, 104 insertions(+)
 
 diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
 index 9429f05..228558c 100644
 --- a/include/linux/lsm_hooks.h
 +++ b/include/linux/lsm_hooks.h
 @@ -1261,6 +1261,23 @@
   *   audit_rule_init.
   *   @rule contains the allocated rule
   *
 + * @userns_create:
 + *   Allocates and fills the security part of a new user namespace.
 + *   @ns points to a newly created user namespace.
 + *   Returns 0 or an error code.
 + *
 + * @userns_free:
 + *   Deallocates the security part of a user namespace.
 + *   @ns points to a user namespace about to be destroyed.
 + *
 + * @userns_setns:
 + *   Run during a setns syscall to add a process to an already existing
 + *   user namespace. Returning failure here will block the operation
 + *   requested from userspace (setns() with CLONE_NEWUSER).
 + *   @nsproxy contains nsproxy to which the user namespace will be assigned.
 + *   @ns contains user namespace that is to be incorporated to the nsproxy.
 + *   Returns 0 or an error code.
 + *
   * @inode_notifysecctx:
   *   Notify the security module of what the security context of an inode
   *   should be.  Initializes the incore security context managed by the
 @@ -1613,6 +1630,12 @@ union security_list_options {
   struct audit_context *actx);
   void (*audit_rule_free)(void *lsmrule);
  #endif /* CONFIG_AUDIT */
 +
 +#ifdef CONFIG_USER_NS
 + int (*userns_create)(struct user_namespace *ns);
 + void (*userns_free)(struct user_namespace *ns);
 + int (*userns_setns)(struct nsproxy *nsproxy, struct user_namespace *ns);
 +#endif /* CONFIG_USER_NS */
  };
  
  struct security_hook_heads {
 @@ -1824,6 +1847,11 @@ struct security_hook_heads {
   struct list_head audit_rule_match;
   struct list_head audit_rule_free;
  #endif /* CONFIG_AUDIT */
 +#ifdef CONFIG_USER_NS
 + struct list_head userns_create;
 + struct list_head userns_free;
 + struct list_head userns_setns;
 +#endif /* CONFIG_USER_NS */
  };
  
  /*
 diff --git a/include/linux/security.h b/include/linux/security.h
 index 79d85dd..1b0eccc 100644
 --- a/include/linux/security.h
 +++ b/include/linux/security.h
 @@ -1584,6 +1584,29 @@ static inline void security_audit_rule_free(void 
 *lsmrule)
  #endif /* CONFIG_SECURITY */
  #endif /* CONFIG_AUDIT */
  
 +#ifdef CONFIG_USER_NS
 +int security_userns_create(struct user_namespace *ns);
 +void security_userns_free(struct user_namespace *ns);
 +int security_userns_setns(struct nsproxy *nsproxy, struct user_namespace 
 *ns);
 +
 +#else
 +
 +static inline int security_userns_create(struct user_namespace *ns)
 +{
 + return 0;
 +}
 +
 +static inline void security_userns_free(struct user_namespace *ns)
 +{ }
 +
 +static inline int security_userns_setns(struct nsproxy *nsproxy,
 + struct user_namespace *ns)
 +{
 + return 0;
 +}
 +
 +#endif /* CONFIG_USER_NS */
 +
  #ifdef CONFIG_SECURITYFS
  
  extern struct dentry *securityfs_create_file(const char *name, umode_t mode,
 diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
 index 8297e5b..a9400cc 100644
 --- a/include/linux/user_namespace.h
 +++ b/include/linux/user_namespace.h
 @@ -39,6 +39,10 @@ struct user_namespace {
   struct key  *persistent_keyring_register;
   struct rw_semaphore persistent_keyring_register_sem;
  #endif
 +
 +#ifdef CONFIG_SECURITY
 + void *security;
 +#endif
  };
  
  extern struct user_namespace init_user_ns;
 diff --git a/kernel/user.c b/kernel/user.c
 index b069ccb..ce5419e 100644
 --- a/kernel/user.c
 +++ b/kernel/user.c
 @@ -59,6 +59,9 @@ struct user_namespace init_user_ns = {
   .persistent_keyring_register_sem =
   __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
  #endif
 +#ifdef CONFIG_SECURITY
 + .security = NULL,
 +#endif
  };
  EXPORT_SYMBOL_GPL(init_user_ns);
  
 diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
 index 4109f83..cadffb6 100644
 --- a/kernel/user_namespace.c
 +++ b/kernel/user_namespace.c
 @@ -22,6 +22,7 @@
  #include linux/ctype.h

[PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-07-24 Thread Lukasz Pawelczyk
This commit implements 3 new LSM hooks that provide the means for LSMs
to embed their own security context within user namespace, effectively
creating some sort of a user_ns related security namespace.

The first one to take advantage of this mechanism is Smack.

The hooks has been documented in the in the security.h below.

Signed-off-by: Lukasz Pawelczyk 
Reviewed-by: Casey Schaufler 
---
 include/linux/lsm_hooks.h  | 28 
 include/linux/security.h   | 23 +++
 include/linux/user_namespace.h |  4 
 kernel/user.c  |  3 +++
 kernel/user_namespace.c| 18 ++
 security/security.c| 28 
 6 files changed, 104 insertions(+)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 9429f05..228558c 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1261,6 +1261,23 @@
  * audit_rule_init.
  * @rule contains the allocated rule
  *
+ * @userns_create:
+ * Allocates and fills the security part of a new user namespace.
+ * @ns points to a newly created user namespace.
+ * Returns 0 or an error code.
+ *
+ * @userns_free:
+ * Deallocates the security part of a user namespace.
+ * @ns points to a user namespace about to be destroyed.
+ *
+ * @userns_setns:
+ * Run during a setns syscall to add a process to an already existing
+ * user namespace. Returning failure here will block the operation
+ * requested from userspace (setns() with CLONE_NEWUSER).
+ * @nsproxy contains nsproxy to which the user namespace will be assigned.
+ * @ns contains user namespace that is to be incorporated to the nsproxy.
+ * Returns 0 or an error code.
+ *
  * @inode_notifysecctx:
  * Notify the security module of what the security context of an inode
  * should be.  Initializes the incore security context managed by the
@@ -1613,6 +1630,12 @@ union security_list_options {
struct audit_context *actx);
void (*audit_rule_free)(void *lsmrule);
 #endif /* CONFIG_AUDIT */
+
+#ifdef CONFIG_USER_NS
+   int (*userns_create)(struct user_namespace *ns);
+   void (*userns_free)(struct user_namespace *ns);
+   int (*userns_setns)(struct nsproxy *nsproxy, struct user_namespace *ns);
+#endif /* CONFIG_USER_NS */
 };
 
 struct security_hook_heads {
@@ -1824,6 +1847,11 @@ struct security_hook_heads {
struct list_head audit_rule_match;
struct list_head audit_rule_free;
 #endif /* CONFIG_AUDIT */
+#ifdef CONFIG_USER_NS
+   struct list_head userns_create;
+   struct list_head userns_free;
+   struct list_head userns_setns;
+#endif /* CONFIG_USER_NS */
 };
 
 /*
diff --git a/include/linux/security.h b/include/linux/security.h
index 79d85dd..1b0eccc 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1584,6 +1584,29 @@ static inline void security_audit_rule_free(void 
*lsmrule)
 #endif /* CONFIG_SECURITY */
 #endif /* CONFIG_AUDIT */
 
+#ifdef CONFIG_USER_NS
+int security_userns_create(struct user_namespace *ns);
+void security_userns_free(struct user_namespace *ns);
+int security_userns_setns(struct nsproxy *nsproxy, struct user_namespace *ns);
+
+#else
+
+static inline int security_userns_create(struct user_namespace *ns)
+{
+   return 0;
+}
+
+static inline void security_userns_free(struct user_namespace *ns)
+{ }
+
+static inline int security_userns_setns(struct nsproxy *nsproxy,
+   struct user_namespace *ns)
+{
+   return 0;
+}
+
+#endif /* CONFIG_USER_NS */
+
 #ifdef CONFIG_SECURITYFS
 
 extern struct dentry *securityfs_create_file(const char *name, umode_t mode,
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 8297e5b..a9400cc 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -39,6 +39,10 @@ struct user_namespace {
struct key  *persistent_keyring_register;
struct rw_semaphore persistent_keyring_register_sem;
 #endif
+
+#ifdef CONFIG_SECURITY
+   void *security;
+#endif
 };
 
 extern struct user_namespace init_user_ns;
diff --git a/kernel/user.c b/kernel/user.c
index b069ccb..ce5419e 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -59,6 +59,9 @@ struct user_namespace init_user_ns = {
.persistent_keyring_register_sem =
__RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
 #endif
+#ifdef CONFIG_SECURITY
+   .security = NULL,
+#endif
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
 
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 4109f83..cadffb6 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct kmem_cache *user_ns_cachep __read_mostly;
 static DEFINE_MUTEX(userns_state_mutex);
@@ -108,6 +109,15 @@ int create_user_ns(struct cred *new)
 
  

[PATCH v3 01/11] user_ns: 3 new LSM hooks for user namespace operations

2015-07-24 Thread Lukasz Pawelczyk
This commit implements 3 new LSM hooks that provide the means for LSMs
to embed their own security context within user namespace, effectively
creating some sort of a user_ns related security namespace.

The first one to take advantage of this mechanism is Smack.

The hooks has been documented in the in the security.h below.

Signed-off-by: Lukasz Pawelczyk l.pawelc...@samsung.com
Reviewed-by: Casey Schaufler ca...@schaufler-ca.com
---
 include/linux/lsm_hooks.h  | 28 
 include/linux/security.h   | 23 +++
 include/linux/user_namespace.h |  4 
 kernel/user.c  |  3 +++
 kernel/user_namespace.c| 18 ++
 security/security.c| 28 
 6 files changed, 104 insertions(+)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 9429f05..228558c 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1261,6 +1261,23 @@
  * audit_rule_init.
  * @rule contains the allocated rule
  *
+ * @userns_create:
+ * Allocates and fills the security part of a new user namespace.
+ * @ns points to a newly created user namespace.
+ * Returns 0 or an error code.
+ *
+ * @userns_free:
+ * Deallocates the security part of a user namespace.
+ * @ns points to a user namespace about to be destroyed.
+ *
+ * @userns_setns:
+ * Run during a setns syscall to add a process to an already existing
+ * user namespace. Returning failure here will block the operation
+ * requested from userspace (setns() with CLONE_NEWUSER).
+ * @nsproxy contains nsproxy to which the user namespace will be assigned.
+ * @ns contains user namespace that is to be incorporated to the nsproxy.
+ * Returns 0 or an error code.
+ *
  * @inode_notifysecctx:
  * Notify the security module of what the security context of an inode
  * should be.  Initializes the incore security context managed by the
@@ -1613,6 +1630,12 @@ union security_list_options {
struct audit_context *actx);
void (*audit_rule_free)(void *lsmrule);
 #endif /* CONFIG_AUDIT */
+
+#ifdef CONFIG_USER_NS
+   int (*userns_create)(struct user_namespace *ns);
+   void (*userns_free)(struct user_namespace *ns);
+   int (*userns_setns)(struct nsproxy *nsproxy, struct user_namespace *ns);
+#endif /* CONFIG_USER_NS */
 };
 
 struct security_hook_heads {
@@ -1824,6 +1847,11 @@ struct security_hook_heads {
struct list_head audit_rule_match;
struct list_head audit_rule_free;
 #endif /* CONFIG_AUDIT */
+#ifdef CONFIG_USER_NS
+   struct list_head userns_create;
+   struct list_head userns_free;
+   struct list_head userns_setns;
+#endif /* CONFIG_USER_NS */
 };
 
 /*
diff --git a/include/linux/security.h b/include/linux/security.h
index 79d85dd..1b0eccc 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1584,6 +1584,29 @@ static inline void security_audit_rule_free(void 
*lsmrule)
 #endif /* CONFIG_SECURITY */
 #endif /* CONFIG_AUDIT */
 
+#ifdef CONFIG_USER_NS
+int security_userns_create(struct user_namespace *ns);
+void security_userns_free(struct user_namespace *ns);
+int security_userns_setns(struct nsproxy *nsproxy, struct user_namespace *ns);
+
+#else
+
+static inline int security_userns_create(struct user_namespace *ns)
+{
+   return 0;
+}
+
+static inline void security_userns_free(struct user_namespace *ns)
+{ }
+
+static inline int security_userns_setns(struct nsproxy *nsproxy,
+   struct user_namespace *ns)
+{
+   return 0;
+}
+
+#endif /* CONFIG_USER_NS */
+
 #ifdef CONFIG_SECURITYFS
 
 extern struct dentry *securityfs_create_file(const char *name, umode_t mode,
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 8297e5b..a9400cc 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -39,6 +39,10 @@ struct user_namespace {
struct key  *persistent_keyring_register;
struct rw_semaphore persistent_keyring_register_sem;
 #endif
+
+#ifdef CONFIG_SECURITY
+   void *security;
+#endif
 };
 
 extern struct user_namespace init_user_ns;
diff --git a/kernel/user.c b/kernel/user.c
index b069ccb..ce5419e 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -59,6 +59,9 @@ struct user_namespace init_user_ns = {
.persistent_keyring_register_sem =
__RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
 #endif
+#ifdef CONFIG_SECURITY
+   .security = NULL,
+#endif
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
 
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 4109f83..cadffb6 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -22,6 +22,7 @@
 #include linux/ctype.h
 #include linux/projid.h
 #include linux/fs_struct.h
+#include linux/security.h
 
 static struct kmem_cache *user_ns_cachep __read_mostly;