diff --git a/kernel.spec b/kernel.spec index 89686d6..e5b1c28 100644 --- a/kernel.spec +++ b/kernel.spec @@ -679,6 +679,10 @@ Patch826: HID-hiddev-validate-num_values-for-HIDIOCGUSAGES-HID.patch #CVE-2016-5728 rhbz 1350811 1350812 Patch827: misc-mic-Fix-for-double-fetch-security-bug-in-mic_co.patch +#CVE-2016-1237 rhbz 1350845 1350847 +Patch830: posix_acl-Add-set_posix_acl.patch +Patch831: nfsd-check-permissions-when-setting-ACLs.patch + # END OF PATCH DEFINITIONS %endif @@ -2197,6 +2201,7 @@ fi # %changelog * Tue Jun 28 2016 Josh Boyer +- CVE-2016-1237 missing check for permissions setting ACL (rhbz 1350845 1350847) - CVE-2016-5728 race condition in mic driver (rhbz 1350811 1350812) * Mon Jun 27 2016 Josh Boyer - 4.5.7-201 diff --git a/nfsd-check-permissions-when-setting-ACLs.patch b/nfsd-check-permissions-when-setting-ACLs.patch new file mode 100644 index 0000000..37ed435 --- /dev/null +++ b/nfsd-check-permissions-when-setting-ACLs.patch @@ -0,0 +1,154 @@ +From 999653786df6954a31044528ac3f7a5dadca08f4 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Wed, 22 Jun 2016 19:43:35 +0100 +Subject: [PATCH] nfsd: check permissions when setting ACLs + +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 +Cc: stable@vger.kernel.org +Signed-off-by: J. Bruce Fields +--- + fs/nfsd/nfs2acl.c | 20 ++++++++++---------- + fs/nfsd/nfs3acl.c | 16 +++++++--------- + fs/nfsd/nfs4acl.c | 16 ++++++++-------- + 3 files changed, 25 insertions(+), 27 deletions(-) + +diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c +index 1580ea6fd64d..d08cd88155c7 100644 +--- a/fs/nfsd/nfs2acl.c ++++ b/fs/nfsd/nfs2acl.c +@@ -104,22 +104,21 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp, + goto out; + + inode = d_inode(fh->fh_dentry); +- 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); +diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c +index 01df4cd7c753..0c890347cde3 100644 +--- a/fs/nfsd/nfs3acl.c ++++ b/fs/nfsd/nfs3acl.c +@@ -95,22 +95,20 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp, + goto out; + + inode = d_inode(fh->fh_dentry); +- 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); +diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c +index 6adabd6049b7..71292a0d6f09 100644 +--- a/fs/nfsd/nfs4acl.c ++++ b/fs/nfsd/nfs4acl.c +@@ -770,9 +770,6 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, + dentry = fhp->fh_dentry; + inode = d_inode(dentry); + +- if (!inode->i_op->set_acl || !IS_POSIXACL(inode)) +- return nfserr_attrnotsupp; +- + if (S_ISDIR(inode->i_mode)) + flags = NFS4_ACL_DIR; + +@@ -782,16 +779,19 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, + 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: +-- +2.5.5 + diff --git a/posix_acl-Add-set_posix_acl.patch b/posix_acl-Add-set_posix_acl.patch new file mode 100644 index 0000000..c067f7b --- /dev/null +++ b/posix_acl-Add-set_posix_acl.patch @@ -0,0 +1,55 @@ +From c463b51e8ea1ae47a7bb8cc2777eb550ad3273e2 Mon Sep 17 00:00:00 2001 +From: Andreas Gruenbacher +Date: Wed, 22 Jun 2016 23:57:25 +0200 +Subject: [PATCH] posix_acl: Add set_posix_acl + +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: stable@vger.kernel.org +Cc: Christoph Hellwig +Cc: Al Viro +Signed-off-by: J. Bruce Fields +--- + fs/posix_acl.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/fs/posix_acl.c b/fs/posix_acl.c +index 711dd5170376..f30caace5b84 100644 +--- a/fs/posix_acl.c ++++ b/fs/posix_acl.c +@@ -786,6 +786,28 @@ posix_acl_xattr_get(const struct xattr_handler *handler, + return error; + } + ++int ++set_posix_acl(struct inode *inode, int type, struct posix_acl *acl) ++{ ++ 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 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(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, +-- +2.5.5 +