public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: ebiederm@xmission.com (Eric W. Biederman)
To: Jan Kara <jack@suse.cz>
Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	Serge Hallyn <serge@hallyn.com>,
	Linux Containers <containers@lists.linux-foundation.org>,
	linux-security-module@vger.kernel.org,
	Dave Chinner <david@fromorbit.com>,
	Al Viro <viro@zeniv.linux.org.uk>, Eric Paris <eparis@redhat.com>,
	David Miller <davem@davemloft.net>, Theodore Tso <tytso@mit.edu>,
	Andrew Morton <akpm@linux-foundation.org>,
	Andreas Dilger <adilger.kernel@dilger.ca>
Subject: Re: [PATCH 16/27] userns: Convert vfs posix_acl support to use kuids and kgids
Date: Tue, 09 Oct 2012 14:46:28 -0700	[thread overview]
Message-ID: <878vbf5nez.fsf@xmission.com> (raw)
In-Reply-To: <20121009204433.GB24622@quack.suse.cz> (Jan Kara's message of "Tue, 9 Oct 2012 22:44:33 +0200")

Jan Kara <jack@suse.cz> writes:

> On Wed 19-09-12 18:52:18, Eric W. Biederman wrote:
>> From: "Eric W. Biederman" <ebiederm@xmission.com>
>> 
>> - In setxattr if we are setting a posix acl convert uids and gids from
>>   the current user namespace into the initial user namespace, before
>>   the xattrs are passed to the underlying filesystem.
>> 
>>   Untranslatable uids and gids are represented as -1 which
>>   posix_acl_from_xattr will represent as INVALID_UID or INVALID_GID.
>>   posix_acl_valid will fail if an acl from userspace has any
>>   INVALID_UID or INVALID_GID values.  In net this guarantees that
>>   untranslatable posix acls will not be stored by filesystems.
>> 
>> - In getxattr if we are reading a posix acl convert uids and gids from
>>   the initial user namespace into the current user namespace.
>> 
>>   Uids and gids that can not be tranlsated into the current user namespace
>>   will be represented as -1.
>> 
>> - Replace e_id in struct posix_acl_entry with an anymouns union of
>>   e_uid and e_gid.  For the short term retain the e_id field
>>   until all of the users are converted.
>> 
>> - Don't set struct posix_acl.e_id in the cases where the acl type
>>   does not use e_id.  Greatly reducing the use of ACL_UNDEFINED_ID.
>> 
>> - Rework the ordering checks in posix_acl_valid so that I use kuid_t
>>   and kgid_t types throughout the code, and so that I don't need
>>   arithmetic on uid and gid types.
>> 
>> Cc: Theodore Tso <tytso@mit.edu>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> Cc: Andreas Dilger <adilger.kernel@dilger.ca>
>> Cc: Jan Kara <jack@suse.cz>
>> Cc: Al Viro <viro@zeniv.linux.org.uk>
>> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
>> ---
>   I know this got merged but I got to seriously looking into it only now
> and frankly I think the push was a hurried one...


>> diff --git a/fs/xattr.c b/fs/xattr.c
>> index 4d45b71..c111745 100644
>> --- a/fs/xattr.c
>> +++ b/fs/xattr.c
>> @@ -20,6 +20,7 @@
>>  #include <linux/fsnotify.h>
>>  #include <linux/audit.h>
>>  #include <linux/vmalloc.h>
>> +#include <linux/posix_acl_xattr.h>
>>  
>>  #include <asm/uaccess.h>
>>  
>> @@ -347,6 +348,9 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
>>  			error = -EFAULT;
>>  			goto out;
>>  		}
>> +		if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
>> +		    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
>> +			posix_acl_fix_xattr_from_user(kvalue, size);
>>  	}
>>  
>>  	error = vfs_setxattr(d, kname, kvalue, size, flags);
>> @@ -450,6 +454,9 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
>>  
>>  	error = vfs_getxattr(d, kname, kvalue, size);
>>  	if (error > 0) {
>> +		if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
>> +		    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
>> +			posix_acl_fix_xattr_to_user(kvalue, size);
>>  		if (size && copy_to_user(value, kvalue, error))
>>  			error = -EFAULT;
>>  	} else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
>> diff --git a/fs/xattr_acl.c b/fs/xattr_acl.c
>> index 69d06b0..bf472ca 100644
>> --- a/fs/xattr_acl.c
>> +++ b/fs/xattr_acl.c
>> @@ -9,7 +9,65 @@
>>  #include <linux/fs.h>
>>  #include <linux/posix_acl_xattr.h>
>>  #include <linux/gfp.h>
>> +#include <linux/user_namespace.h>
>>  
>> +/*
>> + * Fix up the uids and gids in posix acl extended attributes in place.
>> + */
>> +static void posix_acl_fix_xattr_userns(
>> +	struct user_namespace *to, struct user_namespace *from,
>> +	void *value, size_t size)
>> +{
>> +	posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
>> +	posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
>> +	int count;
>> +	kuid_t uid;
>> +	kgid_t gid;
>> +
>> +	if (!value)
>> +		return;
>> +	if (size < sizeof(posix_acl_xattr_header))
>> +		return;
>> +	if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
>> +		return;
>> +
>> +	count = posix_acl_xattr_count(size);
>> +	if (count < 0)
>> +		return;
>> +	if (count == 0)
>> +		return;
>> +
>> +	for (end = entry + count; entry != end; entry++) {
>> +		switch(le16_to_cpu(entry->e_tag)) {
>> +		case ACL_USER:
>> +			uid = make_kuid(from, le32_to_cpu(entry->e_id));

  
>   This should have some error checking I guess... The initial checks done
> in posix_acl_from_xattr() are for init_user_ns (why?) and only duplicated
> in posix_acl_valid().

The flow from userspace:
  posix_acl_fix_xattr_from_user
  posix_acl_from_xattr
  posix_acl_valid

The flow to userspace:
  posix_acl_to_xattr
  posix_acl_fix_xattr_to_user

The existence of the posix_acl_fix_xattr_from_user and
posix_fix_xattr_to_user ensure that filesystems only see xattrs encoded
in the initial user namespace. Which is why posix_acl_from_xattr only
takes init_user_ns as a parameter.

How filesystems handle xattrs that deal with acls is spread all across
the map.  Some filesystems do the reasonable thing and translate the
xattr from userspace into an acl and then translate the acl into their
on-disk format.  Other filesystems just stuff the acl onto the disk or
onto the fileserver without looking at it.

As for checks my interpretation was that a filesystem should already
be calling posix_acl_from_xattr and posix_acl_valid, and that
duplicating those checks in posix_acl_fix_xattr_to/from_user would
be redundnant and confusing.

What does happen is that any uid or gid that does not map gets
translated into -1, which should always fail the latter sanity
check.

>> +			entry->e_id = cpu_to_le32(from_kuid(to, uid));
>> +			break;
>> +		case ACL_GROUP:
>> +			gid = make_kgid(from, le32_to_cpu(entry->e_id));
>> +			entry->e_id = cpu_to_le32(from_kuid(to, uid));
>                                              here should be gid ^^^
Ugh.  Yes.  That is a very real bug. :(  The &init_user_ns short circuit
likely protects against regressions but I will fix this.

>> +			break;
>> +		default:
>> +			break;
>> +		}
>> +	}
>> +}
> Also what about the following scenario:
>
> We have namespace A with user U1 and namespace B which does not have a
> valid representation for U1.

> There is a file F which can be seen from both
> namespaces. In namespace A we create acl for user U1 attached to F. Now in
> namespace B we modify the acl via setfacl(1) command. What it does is
> getxattr(2) - returns mangled acl because U1 has no representation in B. We
> add something to xattr and call setxattr(2) - results in removing the
> original acl for U1 and instead adding acl for uid -1. That is a security
> bug I'd say.

What will happen in most reasonable filesystems is that
posix_acl_from_xattr or posix_acl_valid will see the -1 for the unmapped
uid or gid.  Realize that the -1 does not map, and return -EINVAL before
setting the xattr.  So I do not think the failure mode you are worried
about can happen.

Looking back at this I realize I have pretty much repeated my changelog
description.  Hopefully saying the same thing in different words makes
it clearer.

Eric

  reply	other threads:[~2012-10-09 21:46 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-20  1:45 userns subsystem conversions v2 Eric W. Biederman
2012-09-20  1:52 ` [PATCH 01/27] userns: Convert security/keys to the new userns infrastructure Eric W. Biederman
2012-09-20  1:52   ` [PATCH 02/27] userns: net: Call key_alloc with GLOBAL_ROOT_UID, GLOBAL_ROOT_GID instead of 0, 0 Eric W. Biederman
2012-09-20  1:52   ` [PATCH 03/27] audit: Limit audit requests to processes in the initial pid and user namespaces Eric W. Biederman
2012-09-20  1:52   ` [PATCH 04/27] audit: Use current instead of NETLINK_CREDS() in audit_filter Eric W. Biederman
2012-09-20  1:52   ` [PATCH 05/27] audit: kill audit_prepare_user_tty Eric W. Biederman
2012-09-20  1:52   ` [PATCH 06/27] audit: Simply AUDIT_TTY_SET and AUDIT_TTY_GET Eric W. Biederman
2012-09-20  1:52   ` [PATCH 07/27] audit: Properly set the origin port id of audit messages Eric W. Biederman
2012-09-20  1:52   ` [PATCH 08/27] audit: Remove the unused uid parameter from audit_receive_filter Eric W. Biederman
2012-09-20  1:52   ` [PATCH 09/27] audit: Don't pass pid or uid to audit_log_common_recv_msg Eric W. Biederman
2012-09-20  1:52   ` [PATCH 10/27] audit: Add typespecific uid and gid comparators Eric W. Biederman
2012-09-20  1:52   ` [PATCH 11/27] userns: Convert the audit loginuid to be a kuid Eric W. Biederman
2012-09-20  1:52   ` [PATCH 12/27] userns: Convert audit to work with user namespaces enabled Eric W. Biederman
2012-09-20  1:52   ` [PATCH 13/27] userns: Convert taskstats to handle the user and pid namespaces Eric W. Biederman
2012-09-20  1:52   ` [PATCH 15/27] userns: Teach trace to use from_kuid Eric W. Biederman
2012-09-20  1:52   ` [PATCH 16/27] userns: Convert vfs posix_acl support to use kuids and kgids Eric W. Biederman
2012-10-09 20:44     ` Jan Kara
2012-10-09 21:46       ` Eric W. Biederman [this message]
2012-10-10 11:42         ` Jan Kara
2012-10-10 20:06           ` Eric W. Biederman
2012-09-20  1:52   ` [PATCH 18/27] userns: Convert extN to support kuids and kgids in posix acls Eric W. Biederman
2012-09-20  1:52   ` [PATCH 19/27] userns: Convert configfs to use kuid and kgid where appropriate Eric W. Biederman
2012-09-20  1:52   ` [PATCH 20/27] userns: Add kprojid_t and associated infrastructure in projid.h Eric W. Biederman
2012-09-20  1:52   ` [PATCH 21/27] userns: Implement struct kqid Eric W. Biederman
2012-09-20  1:52   ` [PATCH 22/27] userns: Convert qutoactl Eric W. Biederman
2012-09-20  1:52   ` [PATCH 23/27] userns: Modify dqget to take struct kqid Eric W. Biederman
2012-09-20  1:52   ` [PATCH 24/27] userns: Convert quota netlink aka quota_send_warning Eric W. Biederman
2012-09-20  1:52   ` [PATCH 26/27] userns: Convert struct dquot_warn Eric W. Biederman
2012-09-20  1:52   ` [PATCH 27/27] userns: Convert quota 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=878vbf5nez.fsf@xmission.com \
    --to=ebiederm@xmission.com \
    --cc=adilger.kernel@dilger.ca \
    --cc=akpm@linux-foundation.org \
    --cc=containers@lists.linux-foundation.org \
    --cc=davem@davemloft.net \
    --cc=david@fromorbit.com \
    --cc=eparis@redhat.com \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=serge@hallyn.com \
    --cc=tytso@mit.edu \
    --cc=viro@zeniv.linux.org.uk \
    /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