aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4acl.c
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2016-06-22 14:43:35 -0400
committerJ. Bruce Fields <bfields@redhat.com>2016-06-24 12:11:52 -0400
commit999653786df6954a31044528ac3f7a5dadca08f4 (patch)
tree1591ca7fc7acbd0128b33701516f85276ad8ff06 /fs/nfsd/nfs4acl.c
parent485e71e8fb6356c08c7fc6bcce4bf02c9a9a663f (diff)
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 <david@sinquin.eu> [agreunba@redhat.com: use set_posix_acl] Fixes: 4ac7249e Cc: Christoph Hellwig <hch@infradead.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4acl.c')
-rw-r--r--fs/nfsd/nfs4acl.c16
1 files changed, 8 insertions, 8 deletions
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,
770 dentry = fhp->fh_dentry; 770 dentry = fhp->fh_dentry;
771 inode = d_inode(dentry); 771 inode = d_inode(dentry);
772 772
773 if (!inode->i_op->set_acl || !IS_POSIXACL(inode))
774 return nfserr_attrnotsupp;
775
776 if (S_ISDIR(inode->i_mode)) 773 if (S_ISDIR(inode->i_mode))
777 flags = NFS4_ACL_DIR; 774 flags = NFS4_ACL_DIR;
778 775
@@ -782,16 +779,19 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
782 if (host_error < 0) 779 if (host_error < 0)
783 goto out_nfserr; 780 goto out_nfserr;
784 781
785 host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS); 782 fh_lock(fhp);
783
784 host_error = set_posix_acl(inode, ACL_TYPE_ACCESS, pacl);
786 if (host_error < 0) 785 if (host_error < 0)
787 goto out_release; 786 goto out_drop_lock;
788 787
789 if (S_ISDIR(inode->i_mode)) { 788 if (S_ISDIR(inode->i_mode)) {
790 host_error = inode->i_op->set_acl(inode, dpacl, 789 host_error = set_posix_acl(inode, ACL_TYPE_DEFAULT, dpacl);
791 ACL_TYPE_DEFAULT);
792 } 790 }
793 791
794out_release: 792out_drop_lock:
793 fh_unlock(fhp);
794
795 posix_acl_release(pacl); 795 posix_acl_release(pacl);
796 posix_acl_release(dpacl); 796 posix_acl_release(dpacl);
797out_nfserr: 797out_nfserr: