[Devel] [PATCH rh7 04/11] ms/vfs: Verify acls are valid within superblock's s_user_ns.
Konstantin Khorenko
khorenko at virtuozzo.com
Thu Jun 22 17:47:51 MSK 2017
From: "Eric W. Biederman" <ebiederm at 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 at canonical.com>
Signed-off-by: "Eric W. Biederman" <ebiederm at xmission.com>
(cherry picked from commit 0d4d717f25834134bb6f43284f84c8ccee5bbf2a)
https://jira.sw.ru/browse/PSBM-40075
Signed-off-by: Konstantin Khorenko <khorenko at 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(-)
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 *);
--
1.8.3.1
More information about the Devel
mailing list