aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2018-03-21 17:19:02 -0400
committerJ. Bruce Fields <bfields@redhat.com>2018-04-03 16:27:08 -0400
commit880a3a5325489a143269a8e172e7563ebf9897bc (patch)
tree8beb5344209c3ae8ec1f00ebe0da66bc31e64f49
parentf3aefb6a7066e24bfea7fcf1b07907576de69d63 (diff)
nfsd: fix incorrect umasks
We're neglecting to clear the umask after it's set, which can cause a later unrelated rpc to (incorrectly) use the same umask if it happens to be processed by the same thread. There's a more subtle problem here too: An NFSv4 compound request is decoded all in one pass before any operations are executed. Currently we're setting current->fs->umask at the time we decode the compound. In theory a single compound could contain multiple creates each setting a umask. In that case we'd end up using whichever umask was passed in the *last* operation as the umask for all the creates, whether that was correct or not. So, we should just be saving the umask at decode time and waiting to set it until we actually process the corresponding operation. In practice it's unlikely any client would do multiple creates in a single compound. And even if it did they'd likely be from the same process (hence carry the same umask). So this is a little academic, but we should get it right anyway. Fixes: 47057abde515 (nfsd: add support for the umask attribute) Cc: stable@vger.kernel.org Reported-by: Lucash Stach <l.stach@pengutronix.de> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/nfs4proc.c12
-rw-r--r--fs/nfsd/nfs4xdr.c8
-rw-r--r--fs/nfsd/xdr4.h2
3 files changed, 15 insertions, 7 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index c6157ece46b1..5d99e8810b85 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -32,6 +32,7 @@
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35#include <linux/fs_struct.h>
35#include <linux/file.h> 36#include <linux/file.h>
36#include <linux/falloc.h> 37#include <linux/falloc.h>
37#include <linux/slab.h> 38#include <linux/slab.h>
@@ -252,11 +253,13 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
252 * Note: create modes (UNCHECKED,GUARDED...) are the same 253 * Note: create modes (UNCHECKED,GUARDED...) are the same
253 * in NFSv4 as in v3 except EXCLUSIVE4_1. 254 * in NFSv4 as in v3 except EXCLUSIVE4_1.
254 */ 255 */
256 current->fs->umask = open->op_umask;
255 status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, 257 status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
256 open->op_fname.len, &open->op_iattr, 258 open->op_fname.len, &open->op_iattr,
257 *resfh, open->op_createmode, 259 *resfh, open->op_createmode,
258 (u32 *)open->op_verf.data, 260 (u32 *)open->op_verf.data,
259 &open->op_truncate, &open->op_created); 261 &open->op_truncate, &open->op_created);
262 current->fs->umask = 0;
260 263
261 if (!status && open->op_label.len) 264 if (!status && open->op_label.len)
262 nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval); 265 nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval);
@@ -603,6 +606,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
603 if (status) 606 if (status)
604 return status; 607 return status;
605 608
609 current->fs->umask = create->cr_umask;
606 switch (create->cr_type) { 610 switch (create->cr_type) {
607 case NF4LNK: 611 case NF4LNK:
608 status = nfsd_symlink(rqstp, &cstate->current_fh, 612 status = nfsd_symlink(rqstp, &cstate->current_fh,
@@ -611,20 +615,22 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
611 break; 615 break;
612 616
613 case NF4BLK: 617 case NF4BLK:
618 status = nfserr_inval;
614 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2); 619 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
615 if (MAJOR(rdev) != create->cr_specdata1 || 620 if (MAJOR(rdev) != create->cr_specdata1 ||
616 MINOR(rdev) != create->cr_specdata2) 621 MINOR(rdev) != create->cr_specdata2)
617 return nfserr_inval; 622 goto out_umask;
618 status = nfsd_create(rqstp, &cstate->current_fh, 623 status = nfsd_create(rqstp, &cstate->current_fh,
619 create->cr_name, create->cr_namelen, 624 create->cr_name, create->cr_namelen,
620 &create->cr_iattr, S_IFBLK, rdev, &resfh); 625 &create->cr_iattr, S_IFBLK, rdev, &resfh);
621 break; 626 break;
622 627
623 case NF4CHR: 628 case NF4CHR:
629 status = nfserr_inval;
624 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2); 630 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
625 if (MAJOR(rdev) != create->cr_specdata1 || 631 if (MAJOR(rdev) != create->cr_specdata1 ||
626 MINOR(rdev) != create->cr_specdata2) 632 MINOR(rdev) != create->cr_specdata2)
627 return nfserr_inval; 633 goto out_umask;
628 status = nfsd_create(rqstp, &cstate->current_fh, 634 status = nfsd_create(rqstp, &cstate->current_fh,
629 create->cr_name, create->cr_namelen, 635 create->cr_name, create->cr_namelen,
630 &create->cr_iattr,S_IFCHR, rdev, &resfh); 636 &create->cr_iattr,S_IFCHR, rdev, &resfh);
@@ -668,6 +674,8 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
668 fh_dup2(&cstate->current_fh, &resfh); 674 fh_dup2(&cstate->current_fh, &resfh);
669out: 675out:
670 fh_put(&resfh); 676 fh_put(&resfh);
677out_umask:
678 current->fs->umask = 0;
671 return status; 679 return status;
672} 680}
673 681
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index dd72cdf3662e..1d048dd95464 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -33,7 +33,6 @@
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35 35
36#include <linux/fs_struct.h>
37#include <linux/file.h> 36#include <linux/file.h>
38#include <linux/slab.h> 37#include <linux/slab.h>
39#include <linux/namei.h> 38#include <linux/namei.h>
@@ -682,7 +681,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
682 681
683 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, 682 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
684 &create->cr_acl, &create->cr_label, 683 &create->cr_acl, &create->cr_label,
685 &current->fs->umask); 684 &create->cr_umask);
686 if (status) 685 if (status)
687 goto out; 686 goto out;
688 687
@@ -927,7 +926,6 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
927 case NFS4_OPEN_NOCREATE: 926 case NFS4_OPEN_NOCREATE:
928 break; 927 break;
929 case NFS4_OPEN_CREATE: 928 case NFS4_OPEN_CREATE:
930 current->fs->umask = 0;
931 READ_BUF(4); 929 READ_BUF(4);
932 open->op_createmode = be32_to_cpup(p++); 930 open->op_createmode = be32_to_cpup(p++);
933 switch (open->op_createmode) { 931 switch (open->op_createmode) {
@@ -935,7 +933,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
935 case NFS4_CREATE_GUARDED: 933 case NFS4_CREATE_GUARDED:
936 status = nfsd4_decode_fattr(argp, open->op_bmval, 934 status = nfsd4_decode_fattr(argp, open->op_bmval,
937 &open->op_iattr, &open->op_acl, &open->op_label, 935 &open->op_iattr, &open->op_acl, &open->op_label,
938 &current->fs->umask); 936 &open->op_umask);
939 if (status) 937 if (status)
940 goto out; 938 goto out;
941 break; 939 break;
@@ -950,7 +948,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
950 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE); 948 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
951 status = nfsd4_decode_fattr(argp, open->op_bmval, 949 status = nfsd4_decode_fattr(argp, open->op_bmval,
952 &open->op_iattr, &open->op_acl, &open->op_label, 950 &open->op_iattr, &open->op_acl, &open->op_label,
953 &current->fs->umask); 951 &open->op_umask);
954 if (status) 952 if (status)
955 goto out; 953 goto out;
956 break; 954 break;
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 468020fe2a07..17c453a7999c 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -119,6 +119,7 @@ struct nfsd4_create {
119 } u; 119 } u;
120 u32 cr_bmval[3]; /* request */ 120 u32 cr_bmval[3]; /* request */
121 struct iattr cr_iattr; /* request */ 121 struct iattr cr_iattr; /* request */
122 int cr_umask; /* request */
122 struct nfsd4_change_info cr_cinfo; /* response */ 123 struct nfsd4_change_info cr_cinfo; /* response */
123 struct nfs4_acl *cr_acl; 124 struct nfs4_acl *cr_acl;
124 struct xdr_netobj cr_label; 125 struct xdr_netobj cr_label;
@@ -230,6 +231,7 @@ struct nfsd4_open {
230 u32 op_why_no_deleg; /* response - DELEG_NONE_EXT only */ 231 u32 op_why_no_deleg; /* response - DELEG_NONE_EXT only */
231 u32 op_create; /* request */ 232 u32 op_create; /* request */
232 u32 op_createmode; /* request */ 233 u32 op_createmode; /* request */
234 int op_umask; /* request */
233 u32 op_bmval[3]; /* request */ 235 u32 op_bmval[3]; /* request */
234 struct iattr op_iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */ 236 struct iattr op_iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
235 nfs4_verifier op_verf __attribute__((aligned(32))); 237 nfs4_verifier op_verf __attribute__((aligned(32)));