Linux Container Development
 help / color / mirror / Atom feed
From: ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org (Eric W. Biederman)
To: "Serge E. Hallyn" <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Cc: Linux Containers <containers-qjLDD68F18O7TbgM5vRIOg@public.gmane.org>
Subject: Re: [PATCH 04/10] user namespaces: enforce user namespaces for file permission
Date: Fri, 22 Aug 2008 13:13:36 -0700	[thread overview]
Message-ID: <m1ej4glsen.fsf@frodo.ebiederm.org> (raw)
In-Reply-To: <20080822194609.GD10360-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org> (Serge E. Hallyn's message of "Fri, 22 Aug 2008 14:46:09 -0500")

"Serge E. Hallyn" <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org> writes:

> Add a user_ns to the sb.  It is always set to the user_ns of the task which
> mounted the sb.
>
> Define 3 new super_operations.  convert_uid() and convert_gid() take a uid
> or gid from an inode on the sb's fs, and attempt to convert them into ids
> meaningful in the user namespace passed in, which presumably is current's.
> is_capable() checks whether current has the requested capability with respect
> to the sb's fs, which is dependent upon the relationship between current's
> user_ns and those which the sb knows about.
>
> If the sb isn't user ns aware - which none are right now - then the new
> super_operations won't be defined.  If in that case current and sb have
> different user namespaces, then the userids can't be compared.
>
> If current's and sb's userids can't be compared, then current will get
> 'user other' (we usually say 'nobody') permissions to the inode.
>
> Changelog:
> 	Aug 5: send the whole inode to the super_operations.
>
> Signed-off-by: Serge Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> ---
>  fs/namei.c         |   29 +++++++++++++++++++++++---
>  fs/super.c         |    3 ++
>  include/linux/fs.h |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 83 insertions(+), 4 deletions(-)
>
> diff --git a/fs/namei.c b/fs/namei.c
> index 4ea63ed..6bf5446 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -183,10 +183,27 @@ int generic_permission(struct inode *inode, int mask,
>  		int (*check_acl)(struct inode *inode, int mask))
>  {
>  	umode_t			mode = inode->i_mode;
> +	uid_t			iuid;
> +	gid_t			igid;
> +	int			ret;
> +	int			good_userns = 1;
> +
> +	ret = s_convert_uid_gid(inode, current->user->user_ns,
> +						&iuid, &igid);
> +	if (!ret)
> +		good_userns = 0;
>  
>  	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
>  
> -	if (current->fsuid == inode->i_uid)
> +	/*
> +	 * If we're not in the inode's user namespace, we get
> +	 * user nobody permissions, and we ignore acls
> +	 * (bc serge doesn't know how to handle acls in this case)
> +	 */
> +	if (!good_userns)
> +		goto check;
> +
> +	if (current->fsuid == iuid)
>  		mode >>= 6;
>  	else {
>  		if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
> @@ -197,15 +214,18 @@ int generic_permission(struct inode *inode, int mask,
>  				return error;
>  		}
>  
> -		if (in_group_p(inode->i_gid))
> +		if (in_group_p(igid))
>  			mode >>= 3;
>  	}
>  
> +check:
>  	/*
>  	 * If the DACs are ok we don't need any capability check.
>  	 */
>  	if ((mask & ~mode) == 0)
>  		return 0;
> +	if (!good_userns)
> +		return -EACCES;
>  
>   check_capabilities:
>  	/*
> @@ -214,14 +234,15 @@ int generic_permission(struct inode *inode, int mask,
>  	 */
>  	if (!(mask & MAY_EXEC) ||
>  	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
> -		if (capable(CAP_DAC_OVERRIDE))
> +		if (s_is_capable(inode, current->user->user_ns,
> +						CAP_DAC_OVERRIDE))
>  			return 0;
>  
>  	/*
>  	 * Searching includes executable on directories, else just read.
>  	 */
>  	if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
> -		if (capable(CAP_DAC_READ_SEARCH))
> + if (s_is_capable(inode, current->user->user_ns, CAP_DAC_READ_SEARCH))
>  			return 0;
>  
>  	return -EACCES;
> diff --git a/fs/super.c b/fs/super.c
> index e931ae9..3559637 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -38,6 +38,7 @@
>  #include <linux/kobject.h>
>  #include <linux/mutex.h>
>  #include <linux/file.h>
> +#include <linux/user_namespace.h>
>  #include <asm/uaccess.h>
>  #include "internal.h"
>  
> @@ -93,6 +94,7 @@ static struct super_block *alloc_super(struct file_system_type
> *type)
>  		s->s_qcop = sb_quotactl_ops;
>  		s->s_op = &default_op;
>  		s->s_time_gran = 1000000000;
> +		s->user_ns = get_user_ns(current->user->user_ns);
>  	}
>  out:
>  	return s;
> @@ -109,6 +111,7 @@ static inline void destroy_super(struct super_block *s)
>  	security_sb_free(s);
>  	kfree(s->s_subtype);
>  	kfree(s->s_options);
> +	put_user_ns(s->user_ns);
>  	kfree(s);
>  }
>  
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 580b513..bb58c2e 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1128,6 +1128,11 @@ struct super_block {
>  	 * generic_show_options()
>  	 */
>  	char *s_options;
> +
> +	/*
> +	 * namespace of the user which mounted the sb
> +	 */
> +	struct user_namespace *user_ns;

We should make it clear that this is a default, and not something
a filesystem must use, just something a filesystem may use.
>  };
>  
>  extern struct timespec current_fs_time(struct super_block *sb);
> @@ -1320,6 +1325,9 @@ struct super_operations {
>  	int (*remount_fs) (struct super_block *, int *, char *);
>  	void (*clear_inode) (struct inode *);
>  	void (*umount_begin) (struct super_block *);
> +	int (*is_capable) (struct user_namespace *, struct inode *, int);
> +	uid_t (*convert_uid_gid)(struct user_namespace *, struct inode *,
> +						uid_t *, gid_t *);
>  
I'm not convinced either of those methods makes sense.
>  	int (*show_options)(struct seq_file *, struct vfsmount *);
>  	int (*show_stats)(struct seq_file *, struct vfsmount *);
> @@ -1330,6 +1338,53 @@ struct super_operations {
>  };
>  
>  /*
> + * In the next 3, i'm passing the user_ns in so that I don't need
> + * to know how to dereference struct user her (which would require
> + * #including sched.h).
> + * Note in particular that for instance in s_convert_uid, the uid is the
> + * inode->i_uid, while user_ns is current->user->user_ns.
> + */
> +
> +/*
> + * s_convert_uid: attempt to translate the inode's stored
> + * uid to a uid meaningful in user_ns passed in
> + * If possible, store the result in reuid and return 1
> + * Otherwise, return 0, meaningful the uid cannot be translated
> + */
> +static inline int s_convert_uid_gid(struct inode *ino,
> +		struct user_namespace *user_ns, uid_t *retuid, gid_t *retgid)
> +{
> +	struct super_block *sb = ino->i_sb;
> +
> +	if (sb->user_ns == user_ns) {
> +		*retuid = ino->i_uid;
> +		*retgid = ino->i_gid;
> +		return 1;
> +	}
> +	if (sb->s_op->convert_uid_gid)
> +		return sb->s_op->convert_uid_gid(user_ns, ino, retuid, retgid);

We should be able to just use the existing inode->i_op->getattr.
Especially as that method will have to be updated anyway..

> +	return 0;
> +}
> +
> +/*
> + * s_is_capable: check whether current is capable with respect
> + * to the filesystem represented by sb.
> + *
> + * return 0 if false, 1 if true
> + */
???  Capable should be with respect to a user namespace not with
respect to a filesystem.

  parent reply	other threads:[~2008-08-22 20:13 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-22 19:45 [0/10] User namespaces: introduction Serge E. Hallyn
     [not found] ` <20080822194513.GA10262-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-22 19:45   ` [PATCH 01/10] user namespaces: introduce user_struct->user_namespace relationship Serge E. Hallyn
2008-08-22 19:45   ` [PATCH 02/10] user namespaces: move user_ns from nsproxy into user struct Serge E. Hallyn
2008-08-22 19:45   ` [PATCH 03/10] user namespaces: reset task's credentials on CLONE_NEWUSER Serge E. Hallyn
2008-08-22 19:46   ` [PATCH 04/10] user namespaces: enforce user namespaces for file permission Serge E. Hallyn
     [not found]     ` <20080822194609.GD10360-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-22 20:13       ` Eric W. Biederman [this message]
     [not found]         ` <m1ej4glsen.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-08-23  0:57           ` Serge E. Hallyn
     [not found]             ` <20080823005715.GB21064-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-23  2:16               ` Eric W. Biederman
2008-08-22 21:13       ` Eric W. Biederman
     [not found]         ` <m1bpzkhhy0.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-08-23  0:53           ` [PATCH 04/10] user namespaces: enforce usernamespaces " Serge E. Hallyn
     [not found]             ` <20080823005304.GA21064-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-23  1:56               ` Eric W. Biederman
     [not found]                 ` <m1r68gebop.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-08-23  2:22                   ` Serge E. Hallyn
     [not found]                     ` <20080823022210.GA29618-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-23  3:41                       ` Eric W. Biederman
2008-08-22 19:46   ` [PATCH 05/10] user namespaces: Allow registering new usernamespaces using mount Serge E. Hallyn
2008-08-22 19:46   ` [PATCH 06/10] user namespaces: hook fs/attr.c Serge E. Hallyn
2008-08-22 19:46   ` [PATCH 07/10] user namespaces: bad bad bad but test code Serge E. Hallyn
2008-08-22 19:47   ` [PATCH 08/10] userns: store child userns uids as xattrs in ext3 using lib/fsuserns Serge E. Hallyn
2008-08-22 19:47   ` [PATCH 09/10] userns: have ext3 use fsuserns to read userns xattrs, and add groups to userns Serge E. Hallyn
2008-08-22 19:47   ` [PATCH 10/10] userns: add support for readdir Serge E. Hallyn
2008-08-22 20:41   ` [0/10] User namespaces: introduction Eric W. Biederman
     [not found]     ` <m1d4k0ixzp.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-08-23  1:17       ` Serge E. Hallyn
     [not found]         ` <20080823011731.GA22737-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-23  3:19           ` Eric W. Biederman
     [not found]             ` <m1sksw770k.fsf-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org>
2008-08-25 19:51               ` Serge E. Hallyn
     [not found]                 ` <20080825195124.GA9361-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-08-29  9:40                   ` Eric W. Biederman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m1ej4glsen.fsf@frodo.ebiederm.org \
    --to=ebiederm-as9lmozglivwk0htik3j/w@public.gmane.org \
    --cc=containers-qjLDD68F18O7TbgM5vRIOg@public.gmane.org \
    --cc=serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox