From: Greg Kroah-Hartman Date: Wed, 13 Jul 2016 00:28:31 +0000 (+0900) Subject: 3.14-stable patches X-Git-Tag: v4.6.5~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=80d08a60926f6a5e637fa71a423c858510854f07;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: nfsd-check-permissions-when-setting-acls.patch posix_acl-add-set_posix_acl.patch --- diff --git a/queue-3.14/nfsd-check-permissions-when-setting-acls.patch b/queue-3.14/nfsd-check-permissions-when-setting-acls.patch new file mode 100644 index 00000000000..aabf126aa20 --- /dev/null +++ b/queue-3.14/nfsd-check-permissions-when-setting-acls.patch @@ -0,0 +1,151 @@ +From 999653786df6954a31044528ac3f7a5dadca08f4 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Wed, 22 Jun 2016 19:43:35 +0100 +Subject: nfsd: check permissions when setting ACLs + +From: Ben Hutchings + +commit 999653786df6954a31044528ac3f7a5dadca08f4 upstream. + +Use set_posix_acl, which includes proper permission checks, instead of +calling ->set_acl directly. Without this anyone may be able to grant +themselves permissions to a file by setting the ACL. + +Lock the inode to make the new checks atomic with respect to set_acl. +(Also, nfsd was the only caller of set_acl not locking the inode, so I +suspect this may fix other races.) + +This also simplifies the code, and ensures our ACLs are checked by +posix_acl_valid. + +The permission checks and the inode locking were lost with commit +4ac7249e, which changed nfsd to use the set_acl inode operation directly +instead of going through xattr handlers. + +Reported-by: David Sinquin +[agreunba@redhat.com: use set_posix_acl] +Fixes: 4ac7249e +Cc: Christoph Hellwig +Cc: Al Viro +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + + +--- + fs/nfsd/nfs2acl.c | 20 ++++++++++---------- + fs/nfsd/nfs3acl.c | 16 +++++++--------- + fs/nfsd/nfs4acl.c | 16 ++++++++-------- + 3 files changed, 25 insertions(+), 27 deletions(-) + +--- a/fs/nfsd/nfs2acl.c ++++ b/fs/nfsd/nfs2acl.c +@@ -104,22 +104,21 @@ static __be32 nfsacld_proc_setacl(struct + goto out; + + inode = fh->fh_dentry->d_inode; +- if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) { +- error = -EOPNOTSUPP; +- goto out_errno; +- } + + error = fh_want_write(fh); + if (error) + goto out_errno; + +- error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS); ++ fh_lock(fh); ++ ++ error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access); + if (error) +- goto out_drop_write; +- error = inode->i_op->set_acl(inode, argp->acl_default, +- ACL_TYPE_DEFAULT); ++ goto out_drop_lock; ++ error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default); + if (error) +- goto out_drop_write; ++ goto out_drop_lock; ++ ++ fh_unlock(fh); + + fh_drop_write(fh); + +@@ -131,7 +130,8 @@ out: + posix_acl_release(argp->acl_access); + posix_acl_release(argp->acl_default); + return nfserr; +-out_drop_write: ++out_drop_lock: ++ fh_unlock(fh); + fh_drop_write(fh); + out_errno: + nfserr = nfserrno(error); +--- a/fs/nfsd/nfs3acl.c ++++ b/fs/nfsd/nfs3acl.c +@@ -95,22 +95,20 @@ static __be32 nfsd3_proc_setacl(struct s + goto out; + + inode = fh->fh_dentry->d_inode; +- if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) { +- error = -EOPNOTSUPP; +- goto out_errno; +- } + + error = fh_want_write(fh); + if (error) + goto out_errno; + +- error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS); ++ fh_lock(fh); ++ ++ error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access); + if (error) +- goto out_drop_write; +- error = inode->i_op->set_acl(inode, argp->acl_default, +- ACL_TYPE_DEFAULT); ++ goto out_drop_lock; ++ error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default); + +-out_drop_write: ++out_drop_lock: ++ fh_unlock(fh); + fh_drop_write(fh); + out_errno: + nfserr = nfserrno(error); +--- a/fs/nfsd/nfs4acl.c ++++ b/fs/nfsd/nfs4acl.c +@@ -818,9 +818,6 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst + dentry = fhp->fh_dentry; + inode = dentry->d_inode; + +- if (!inode->i_op->set_acl || !IS_POSIXACL(inode)) +- return nfserr_attrnotsupp; +- + if (S_ISDIR(inode->i_mode)) + flags = NFS4_ACL_DIR; + +@@ -830,16 +827,19 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst + if (host_error < 0) + goto out_nfserr; + +- host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS); ++ fh_lock(fhp); ++ ++ host_error = set_posix_acl(inode, ACL_TYPE_ACCESS, pacl); + if (host_error < 0) +- goto out_release; ++ goto out_drop_lock; + + if (S_ISDIR(inode->i_mode)) { +- host_error = inode->i_op->set_acl(inode, dpacl, +- ACL_TYPE_DEFAULT); ++ host_error = set_posix_acl(inode, ACL_TYPE_DEFAULT, dpacl); + } + +-out_release: ++out_drop_lock: ++ fh_unlock(fhp); ++ + posix_acl_release(pacl); + posix_acl_release(dpacl); + out_nfserr: diff --git a/queue-3.14/posix_acl-add-set_posix_acl.patch b/queue-3.14/posix_acl-add-set_posix_acl.patch new file mode 100644 index 00000000000..29552adbb9b --- /dev/null +++ b/queue-3.14/posix_acl-add-set_posix_acl.patch @@ -0,0 +1,86 @@ +From 485e71e8fb6356c08c7fc6bcce4bf02c9a9a663f Mon Sep 17 00:00:00 2001 +From: Andreas Gruenbacher +Date: Wed, 22 Jun 2016 23:57:25 +0200 +Subject: posix_acl: Add set_posix_acl + +From: Andreas Gruenbacher + +commit 485e71e8fb6356c08c7fc6bcce4bf02c9a9a663f upstream. + +Factor out part of posix_acl_xattr_set into a common function that takes +a posix_acl, which nfsd can also call. + +The prototype already exists in include/linux/posix_acl.h. + +Signed-off-by: Andreas Gruenbacher +Cc: Christoph Hellwig +Cc: Al Viro +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/posix_acl.c | 38 +++++++++++++++++++++----------------- + 1 file changed, 21 insertions(+), 17 deletions(-) + +--- a/fs/posix_acl.c ++++ b/fs/posix_acl.c +@@ -787,38 +787,42 @@ posix_acl_xattr_get(struct dentry *dentr + return error; + } + +-static int +-posix_acl_xattr_set(struct dentry *dentry, const char *name, +- const void *value, size_t size, int flags, int type) ++int ++set_posix_acl(struct inode *inode, int type, struct posix_acl *acl) + { +- struct inode *inode = dentry->d_inode; +- struct posix_acl *acl = NULL; +- int ret; +- + if (!IS_POSIXACL(inode)) + return -EOPNOTSUPP; + if (!inode->i_op->set_acl) + return -EOPNOTSUPP; + + if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) +- return value ? -EACCES : 0; ++ return acl ? -EACCES : 0; + if (!inode_owner_or_capable(inode)) + return -EPERM; + ++ if (acl) { ++ int ret = posix_acl_valid(acl); ++ if (ret) ++ return ret; ++ } ++ return inode->i_op->set_acl(inode, acl, type); ++} ++EXPORT_SYMBOL(set_posix_acl); ++ ++static int ++posix_acl_xattr_set(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags, int type) ++{ ++ struct inode *inode = dentry->d_inode; ++ struct posix_acl *acl = NULL; ++ int ret; ++ + if (value) { + acl = posix_acl_from_xattr(&init_user_ns, value, size); + if (IS_ERR(acl)) + return PTR_ERR(acl); +- +- if (acl) { +- ret = posix_acl_valid(acl); +- if (ret) +- goto out; +- } + } +- +- ret = inode->i_op->set_acl(inode, acl, type); +-out: ++ ret = set_posix_acl(inode, type, acl); + posix_acl_release(acl); + return ret; + } diff --git a/queue-3.14/series b/queue-3.14/series index 1d041d6d298..6daa9514f2f 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -20,3 +20,5 @@ nfs-fix-another-open_downgrade-bug.patch arm-8578-1-mm-ensure-pmd_present-only-checks-the-valid-bit.patch mm-export-migrate_page_move_mapping-and-migrate_page_copy.patch ubifs-implement-migratepage.patch +posix_acl-add-set_posix_acl.patch +nfsd-check-permissions-when-setting-acls.patch