summaryrefslogtreecommitdiffstats
path: root/fs/posix_acl.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-02-07 18:52:57 -0800
committerEric W. Biederman <ebiederm@xmission.com>2012-09-18 01:01:35 -0700
commit2f6f0654ab61961fd0f7701fe3be89ea111f0cda (patch)
treea96703c892bd374b5ef7b102c52a5ec596970027 /fs/posix_acl.c
parentd20b92ab668cc44fc84bba0001839c5a8013a5cd (diff)
downloadlinux-2f6f0654ab61961fd0f7701fe3be89ea111f0cda.tar.bz2
userns: Convert vfs posix_acl support to use kuids and kgids
- 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>
Diffstat (limited to 'fs/posix_acl.c')
-rw-r--r--fs/posix_acl.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 5e325a42e33d..8bd2135b7f82 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -78,7 +78,8 @@ posix_acl_valid(const struct posix_acl *acl)
{
const struct posix_acl_entry *pa, *pe;
int state = ACL_USER_OBJ;
- unsigned int id = 0; /* keep gcc happy */
+ kuid_t prev_uid = INVALID_UID;
+ kgid_t prev_gid = INVALID_GID;
int needs_mask = 0;
FOREACH_ACL_ENTRY(pa, acl, pe) {
@@ -87,7 +88,6 @@ posix_acl_valid(const struct posix_acl *acl)
switch (pa->e_tag) {
case ACL_USER_OBJ:
if (state == ACL_USER_OBJ) {
- id = 0;
state = ACL_USER;
break;
}
@@ -96,16 +96,17 @@ posix_acl_valid(const struct posix_acl *acl)
case ACL_USER:
if (state != ACL_USER)
return -EINVAL;
- if (pa->e_id == ACL_UNDEFINED_ID ||
- pa->e_id < id)
+ if (!uid_valid(pa->e_uid))
return -EINVAL;
- id = pa->e_id + 1;
+ if (uid_valid(prev_uid) &&
+ uid_lte(pa->e_uid, prev_uid))
+ return -EINVAL;
+ prev_uid = pa->e_uid;
needs_mask = 1;
break;
case ACL_GROUP_OBJ:
if (state == ACL_USER) {
- id = 0;
state = ACL_GROUP;
break;
}
@@ -114,10 +115,12 @@ posix_acl_valid(const struct posix_acl *acl)
case ACL_GROUP:
if (state != ACL_GROUP)
return -EINVAL;
- if (pa->e_id == ACL_UNDEFINED_ID ||
- pa->e_id < id)
+ if (!gid_valid(pa->e_gid))
+ return -EINVAL;
+ if (gid_valid(prev_gid) &&
+ gid_lte(pa->e_gid, prev_gid))
return -EINVAL;
- id = pa->e_id + 1;
+ prev_gid = pa->e_gid;
needs_mask = 1;
break;
@@ -195,15 +198,12 @@ posix_acl_from_mode(umode_t mode, gfp_t flags)
return ERR_PTR(-ENOMEM);
acl->a_entries[0].e_tag = ACL_USER_OBJ;
- acl->a_entries[0].e_id = ACL_UNDEFINED_ID;
acl->a_entries[0].e_perm = (mode & S_IRWXU) >> 6;
acl->a_entries[1].e_tag = ACL_GROUP_OBJ;
- acl->a_entries[1].e_id = ACL_UNDEFINED_ID;
acl->a_entries[1].e_perm = (mode & S_IRWXG) >> 3;
acl->a_entries[2].e_tag = ACL_OTHER;
- acl->a_entries[2].e_id = ACL_UNDEFINED_ID;
acl->a_entries[2].e_perm = (mode & S_IRWXO);
return acl;
}
@@ -224,11 +224,11 @@ posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
switch(pa->e_tag) {
case ACL_USER_OBJ:
/* (May have been checked already) */
- if (inode->i_uid == current_fsuid())
+ if (uid_eq(inode->i_uid, current_fsuid()))
goto check_perm;
break;
case ACL_USER:
- if (pa->e_id == current_fsuid())
+ if (uid_eq(pa->e_uid, current_fsuid()))
goto mask;
break;
case ACL_GROUP_OBJ:
@@ -239,7 +239,7 @@ posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
}
break;
case ACL_GROUP:
- if (in_group_p(pa->e_id)) {
+ if (in_group_p(pa->e_gid)) {
found = 1;
if ((pa->e_perm & want) == want)
goto mask;