diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-06-24 20:22:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-06-24 20:22:27 -0400 |
commit | 9c46a6df3ba770162deb7abc95427fa1ddf28763 (patch) | |
tree | f615a937dd55801ff5a213133eb2c3eb26bc60ed /fs | |
parent | 7f1a00b6fcd0e3c19beba2e92d157dc0c2cf3494 (diff) | |
parent | 999653786df6954a31044528ac3f7a5dadca08f4 (diff) |
Merge tag 'nfsd-4.7-2' of git://linux-nfs.org/~bfields/linux
Pull nfsd bugfixes from Bruce Fields:
"Fix missing server-side permission checks on setting NFS ACLs"
* tag 'nfsd-4.7-2' of git://linux-nfs.org/~bfields/linux:
nfsd: check permissions when setting ACLs
posix_acl: Add set_posix_acl
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/nfs2acl.c | 20 | ||||
-rw-r--r-- | fs/nfsd/nfs3acl.c | 16 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 16 | ||||
-rw-r--r-- | fs/posix_acl.c | 42 |
4 files changed, 48 insertions, 46 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, | |||
104 | goto out; | 104 | goto out; |
105 | 105 | ||
106 | inode = d_inode(fh->fh_dentry); | 106 | inode = d_inode(fh->fh_dentry); |
107 | if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) { | ||
108 | error = -EOPNOTSUPP; | ||
109 | goto out_errno; | ||
110 | } | ||
111 | 107 | ||
112 | error = fh_want_write(fh); | 108 | error = fh_want_write(fh); |
113 | if (error) | 109 | if (error) |
114 | goto out_errno; | 110 | goto out_errno; |
115 | 111 | ||
116 | error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS); | 112 | fh_lock(fh); |
113 | |||
114 | error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access); | ||
117 | if (error) | 115 | if (error) |
118 | goto out_drop_write; | 116 | goto out_drop_lock; |
119 | error = inode->i_op->set_acl(inode, argp->acl_default, | 117 | error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default); |
120 | ACL_TYPE_DEFAULT); | ||
121 | if (error) | 118 | if (error) |
122 | goto out_drop_write; | 119 | goto out_drop_lock; |
120 | |||
121 | fh_unlock(fh); | ||
123 | 122 | ||
124 | fh_drop_write(fh); | 123 | fh_drop_write(fh); |
125 | 124 | ||
@@ -131,7 +130,8 @@ out: | |||
131 | posix_acl_release(argp->acl_access); | 130 | posix_acl_release(argp->acl_access); |
132 | posix_acl_release(argp->acl_default); | 131 | posix_acl_release(argp->acl_default); |
133 | return nfserr; | 132 | return nfserr; |
134 | out_drop_write: | 133 | out_drop_lock: |
134 | fh_unlock(fh); | ||
135 | fh_drop_write(fh); | 135 | fh_drop_write(fh); |
136 | out_errno: | 136 | out_errno: |
137 | nfserr = nfserrno(error); | 137 | 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, | |||
95 | goto out; | 95 | goto out; |
96 | 96 | ||
97 | inode = d_inode(fh->fh_dentry); | 97 | inode = d_inode(fh->fh_dentry); |
98 | if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) { | ||
99 | error = -EOPNOTSUPP; | ||
100 | goto out_errno; | ||
101 | } | ||
102 | 98 | ||
103 | error = fh_want_write(fh); | 99 | error = fh_want_write(fh); |
104 | if (error) | 100 | if (error) |
105 | goto out_errno; | 101 | goto out_errno; |
106 | 102 | ||
107 | error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS); | 103 | fh_lock(fh); |
104 | |||
105 | error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access); | ||
108 | if (error) | 106 | if (error) |
109 | goto out_drop_write; | 107 | goto out_drop_lock; |
110 | error = inode->i_op->set_acl(inode, argp->acl_default, | 108 | error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default); |
111 | ACL_TYPE_DEFAULT); | ||
112 | 109 | ||
113 | out_drop_write: | 110 | out_drop_lock: |
111 | fh_unlock(fh); | ||
114 | fh_drop_write(fh); | 112 | fh_drop_write(fh); |
115 | out_errno: | 113 | out_errno: |
116 | nfserr = nfserrno(error); | 114 | 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, | |||
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 | ||
794 | out_release: | 792 | out_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); |
797 | out_nfserr: | 797 | out_nfserr: |
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 8a4a266beff3..edc452c2a563 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -820,39 +820,43 @@ posix_acl_xattr_get(const struct xattr_handler *handler, | |||
820 | return error; | 820 | return error; |
821 | } | 821 | } |
822 | 822 | ||
823 | static int | 823 | int |
824 | posix_acl_xattr_set(const struct xattr_handler *handler, | 824 | set_posix_acl(struct inode *inode, int type, struct posix_acl *acl) |
825 | struct dentry *unused, struct inode *inode, | ||
826 | const char *name, const void *value, | ||
827 | size_t size, int flags) | ||
828 | { | 825 | { |
829 | struct posix_acl *acl = NULL; | ||
830 | int ret; | ||
831 | |||
832 | if (!IS_POSIXACL(inode)) | 826 | if (!IS_POSIXACL(inode)) |
833 | return -EOPNOTSUPP; | 827 | return -EOPNOTSUPP; |
834 | if (!inode->i_op->set_acl) | 828 | if (!inode->i_op->set_acl) |
835 | return -EOPNOTSUPP; | 829 | return -EOPNOTSUPP; |
836 | 830 | ||
837 | if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) | 831 | if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) |
838 | return value ? -EACCES : 0; | 832 | return acl ? -EACCES : 0; |
839 | if (!inode_owner_or_capable(inode)) | 833 | if (!inode_owner_or_capable(inode)) |
840 | return -EPERM; | 834 | return -EPERM; |
841 | 835 | ||
836 | if (acl) { | ||
837 | int ret = posix_acl_valid(acl); | ||
838 | if (ret) | ||
839 | return ret; | ||
840 | } | ||
841 | return inode->i_op->set_acl(inode, acl, type); | ||
842 | } | ||
843 | EXPORT_SYMBOL(set_posix_acl); | ||
844 | |||
845 | static int | ||
846 | posix_acl_xattr_set(const struct xattr_handler *handler, | ||
847 | struct dentry *unused, struct inode *inode, | ||
848 | const char *name, const void *value, | ||
849 | size_t size, int flags) | ||
850 | { | ||
851 | struct posix_acl *acl = NULL; | ||
852 | int ret; | ||
853 | |||
842 | if (value) { | 854 | if (value) { |
843 | acl = posix_acl_from_xattr(&init_user_ns, value, size); | 855 | acl = posix_acl_from_xattr(&init_user_ns, value, size); |
844 | if (IS_ERR(acl)) | 856 | if (IS_ERR(acl)) |
845 | return PTR_ERR(acl); | 857 | return PTR_ERR(acl); |
846 | |||
847 | if (acl) { | ||
848 | ret = posix_acl_valid(acl); | ||
849 | if (ret) | ||
850 | goto out; | ||
851 | } | ||
852 | } | 858 | } |
853 | 859 | ret = set_posix_acl(inode, handler->flags, acl); | |
854 | ret = inode->i_op->set_acl(inode, acl, handler->flags); | ||
855 | out: | ||
856 | posix_acl_release(acl); | 860 | posix_acl_release(acl); |
857 | return ret; | 861 | return ret; |
858 | } | 862 | } |