[Devel,rh7,04/11] ms/vfs: Verify acls are valid within superblock's s_user_ns.

Submitted by Konstantin Khorenko on June 22, 2017, 2:47 p.m.

Details

Message ID 1498142878-2222-5-git-send-email-khorenko@virtuozzo.com
State New
Series "Revert "ms/cred: Reject inodes with invalid ids in set_create_file_as()""
Headers show

Commit Message

Konstantin Khorenko June 22, 2017, 2:47 p.m.
From: "Eric W. Biederman" <ebiederm@xmission.com>

Update posix_acl_valid to verify that an acl is within a user namespace.

Update the callers of posix_acl_valid to pass in an appropriate
user namespace.  For posix_acl_xattr_set and v9fs_xattr_set_acl pass in
inode->i_sb->s_user_ns to posix_acl_valid.  For md_unpack_acl pass in
&init_user_ns as no inode or superblock is in sight.

Acked-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
(cherry picked from commit 0d4d717f25834134bb6f43284f84c8ccee5bbf2a)

https://jira.sw.ru/browse/PSBM-40075

Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>

Conflicts:
	drivers/staging/lustre/lustre/mdc/mdc_request.c
	fs/posix_acl.c

Note: vz7 code has more places where posix_acl_valid() is used =>
fixed them as well:
       modified:   fs/btrfs/acl.c
       modified:   fs/ceph/acl.c
       modified:   fs/ext4/acl.c
       modified:   fs/gfs2/acl.c
       modified:   fs/nfsd/acl.h
       modified:   fs/nfsd/nfs4acl.c
       modified:   fs/nfsd/vfs.c
       modified:   fs/xfs/xfs_acl.c
---
 fs/9p/acl.c               | 2 +-
 fs/btrfs/acl.c            | 3 ++-
 fs/ceph/acl.c             | 3 ++-
 fs/ext4/acl.c             | 2 +-
 fs/generic_acl.c          | 2 +-
 fs/gfs2/acl.c             | 2 +-
 fs/nfsd/acl.h             | 3 ++-
 fs/nfsd/nfs4acl.c         | 6 +++---
 fs/nfsd/vfs.c             | 2 +-
 fs/posix_acl.c            | 6 +++---
 fs/xfs/xfs_acl.c          | 2 +-
 include/linux/posix_acl.h | 2 +-
 12 files changed, 19 insertions(+), 16 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 9686c1f1..aae9d1a 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -309,7 +309,7 @@  static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 		if (IS_ERR(acl))
 			return PTR_ERR(acl);
 		else if (acl) {
-			retval = posix_acl_valid(acl);
+			retval = posix_acl_valid(inode->i_sb->s_user_ns, acl);
 			if (retval)
 				goto err_out;
 		}
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 9e15ea9..b345b5d 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -167,7 +167,8 @@  static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
 			return PTR_ERR(acl);
 
 		if (acl) {
-			ret = posix_acl_valid(acl);
+			ret = posix_acl_valid(dentry->d_inode->i_sb->s_user_ns,
+					      acl);
 			if (ret)
 				goto out;
 		}
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index 13ef95e2..f9305a1 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -365,7 +365,8 @@  static int ceph_xattr_acl_set(struct dentry *dentry, const char *name,
 		}
 
 		if (acl) {
-			ret = posix_acl_valid(acl);
+			ret = posix_acl_valid(dentry->d_inode->i_sb->s_user_ns,
+					      acl);
 			if (ret)
 				goto out_release;
 		}
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index c844f1b..448042e 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -410,7 +410,7 @@  ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
 		if (IS_ERR(acl))
 			return PTR_ERR(acl);
 		else if (acl) {
-			error = posix_acl_valid(acl);
+			error = posix_acl_valid(inode->i_sb->s_user_ns, acl);
 			if (error)
 				goto release_and_out;
 		}
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index b3f3676..5fa3b77 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -82,7 +82,7 @@  generic_acl_set(struct dentry *dentry, const char *name, const void *value,
 			return PTR_ERR(acl);
 	}
 	if (acl) {
-		error = posix_acl_valid(acl);
+		error = posix_acl_valid(inode->i_sb->s_user_ns, acl);
 		if (error)
 			goto failed;
 		switch (type) {
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 40a5ab9..de808ad 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -262,7 +262,7 @@  static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
 		goto out;
 	}
 
-	error = posix_acl_valid(acl);
+	error = posix_acl_valid(inode->i_sb->s_user_ns, acl);
 	if (error)
 		goto out_release;
 
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
index 051ffcb7..5b15770 100644
--- a/fs/nfsd/acl.h
+++ b/fs/nfsd/acl.h
@@ -54,7 +54,8 @@  __be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who);
 #define NFS4_ACL_OWNER		0x04
 
 struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *,
-				struct posix_acl *, unsigned int flags);
+				struct posix_acl *, unsigned int flags,
+				struct inode *);
 int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *, struct posix_acl **,
 				struct posix_acl **, unsigned int flags);
 
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 7b3ef8d..4e3359e 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -122,18 +122,18 @@  static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
 
 struct nfs4_acl *
 nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
-			unsigned int flags)
+			unsigned int flags, struct inode *inode)
 {
 	struct nfs4_acl *acl;
 	int size = 0;
 
 	if (pacl) {
-		if (posix_acl_valid(pacl) < 0)
+		if (posix_acl_valid(inode->i_sb->s_user_ns, pacl) < 0)
 			return ERR_PTR(-EINVAL);
 		size += 2*pacl->a_count;
 	}
 	if (dpacl) {
-		if (posix_acl_valid(dpacl) < 0)
+		if (posix_acl_valid(inode->i_sb->s_user_ns, dpacl) < 0)
 			return ERR_PTR(-EINVAL);
 		size += 2*dpacl->a_count;
 	}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7176ff7..06f0309 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -591,7 +591,7 @@  nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
 		flags = NFS4_ACL_DIR;
 	}
 
-	*acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags);
+	*acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags, inode);
 	if (IS_ERR(*acl)) {
 		error = PTR_ERR(*acl);
 		*acl = NULL;
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 6777b5d..a5994e9 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -74,7 +74,7 @@  posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
  * Check if an acl is valid. Returns 0 if it is, or -E... otherwise.
  */
 int
-posix_acl_valid(const struct posix_acl *acl)
+posix_acl_valid(struct user_namespace *user_ns, const struct posix_acl *acl)
 {
 	const struct posix_acl_entry *pa, *pe;
 	int state = ACL_USER_OBJ;
@@ -96,7 +96,7 @@  posix_acl_valid(const struct posix_acl *acl)
 			case ACL_USER:
 				if (state != ACL_USER)
 					return -EINVAL;
-				if (!uid_valid(pa->e_uid))
+				if (!kuid_has_mapping(user_ns, pa->e_uid))
 					return -EINVAL;
 				if (uid_valid(prev_uid) &&
 				    uid_lte(pa->e_uid, prev_uid))
@@ -115,7 +115,7 @@  posix_acl_valid(const struct posix_acl *acl)
 			case ACL_GROUP:
 				if (state != ACL_GROUP)
 					return -EINVAL;
-				if (!gid_valid(pa->e_gid))
+				if (!kgid_has_mapping(user_ns, pa->e_gid))
 					return -EINVAL;
 				if (gid_valid(prev_gid) &&
 				    gid_lte(pa->e_gid, prev_gid))
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 271d7c2..4b76d96 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -395,7 +395,7 @@  xfs_xattr_acl_set(struct dentry *dentry, const char *name,
 		goto out;
 	}
 
-	error = posix_acl_valid(acl);
+	error = posix_acl_valid(inode->i_sb->s_user_ns, acl);
 	if (error)
 		goto out_release;
 
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 93985d3..0b45833 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -84,7 +84,7 @@  posix_acl_release(struct posix_acl *acl)
 
 extern void posix_acl_init(struct posix_acl *, int);
 extern struct posix_acl *posix_acl_alloc(int, gfp_t);
-extern int posix_acl_valid(const struct posix_acl *);
+extern int posix_acl_valid(struct user_namespace *, const struct posix_acl *);
 extern int posix_acl_permission(struct inode *, const struct posix_acl *, int);
 extern struct posix_acl *posix_acl_from_mode(umode_t, gfp_t);
 extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *);