Skip to content

Commit 880a3a5

Browse files
author
J. Bruce Fields
committed
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: 47057ab (nfsd: add support for the umask attribute) Cc: [email protected] Reported-by: Lucash Stach <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent f3aefb6 commit 880a3a5

File tree

3 files changed

+15
-7
lines changed

3 files changed

+15
-7
lines changed

fs/nfsd/nfs4proc.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3333
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3434
*/
35+
#include <linux/fs_struct.h>
3536
#include <linux/file.h>
3637
#include <linux/falloc.h>
3738
#include <linux/slab.h>
@@ -252,11 +253,13 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
252253
* Note: create modes (UNCHECKED,GUARDED...) are the same
253254
* in NFSv4 as in v3 except EXCLUSIVE4_1.
254255
*/
256+
current->fs->umask = open->op_umask;
255257
status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
256258
open->op_fname.len, &open->op_iattr,
257259
*resfh, open->op_createmode,
258260
(u32 *)open->op_verf.data,
259261
&open->op_truncate, &open->op_created);
262+
current->fs->umask = 0;
260263

261264
if (!status && open->op_label.len)
262265
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,
603606
if (status)
604607
return status;
605608

609+
current->fs->umask = create->cr_umask;
606610
switch (create->cr_type) {
607611
case NF4LNK:
608612
status = nfsd_symlink(rqstp, &cstate->current_fh,
@@ -611,20 +615,22 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
611615
break;
612616

613617
case NF4BLK:
618+
status = nfserr_inval;
614619
rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
615620
if (MAJOR(rdev) != create->cr_specdata1 ||
616621
MINOR(rdev) != create->cr_specdata2)
617-
return nfserr_inval;
622+
goto out_umask;
618623
status = nfsd_create(rqstp, &cstate->current_fh,
619624
create->cr_name, create->cr_namelen,
620625
&create->cr_iattr, S_IFBLK, rdev, &resfh);
621626
break;
622627

623628
case NF4CHR:
629+
status = nfserr_inval;
624630
rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
625631
if (MAJOR(rdev) != create->cr_specdata1 ||
626632
MINOR(rdev) != create->cr_specdata2)
627-
return nfserr_inval;
633+
goto out_umask;
628634
status = nfsd_create(rqstp, &cstate->current_fh,
629635
create->cr_name, create->cr_namelen,
630636
&create->cr_iattr,S_IFCHR, rdev, &resfh);
@@ -668,6 +674,8 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
668674
fh_dup2(&cstate->current_fh, &resfh);
669675
out:
670676
fh_put(&resfh);
677+
out_umask:
678+
current->fs->umask = 0;
671679
return status;
672680
}
673681

fs/nfsd/nfs4xdr.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3434
*/
3535

36-
#include <linux/fs_struct.h>
3736
#include <linux/file.h>
3837
#include <linux/slab.h>
3938
#include <linux/namei.h>
@@ -682,7 +681,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
682681

683682
status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
684683
&create->cr_acl, &create->cr_label,
685-
&current->fs->umask);
684+
&create->cr_umask);
686685
if (status)
687686
goto out;
688687

@@ -927,15 +926,14 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
927926
case NFS4_OPEN_NOCREATE:
928927
break;
929928
case NFS4_OPEN_CREATE:
930-
current->fs->umask = 0;
931929
READ_BUF(4);
932930
open->op_createmode = be32_to_cpup(p++);
933931
switch (open->op_createmode) {
934932
case NFS4_CREATE_UNCHECKED:
935933
case NFS4_CREATE_GUARDED:
936934
status = nfsd4_decode_fattr(argp, open->op_bmval,
937935
&open->op_iattr, &open->op_acl, &open->op_label,
938-
&current->fs->umask);
936+
&open->op_umask);
939937
if (status)
940938
goto out;
941939
break;
@@ -950,7 +948,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
950948
COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
951949
status = nfsd4_decode_fattr(argp, open->op_bmval,
952950
&open->op_iattr, &open->op_acl, &open->op_label,
953-
&current->fs->umask);
951+
&open->op_umask);
954952
if (status)
955953
goto out;
956954
break;

fs/nfsd/xdr4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ struct nfsd4_create {
119119
} u;
120120
u32 cr_bmval[3]; /* request */
121121
struct iattr cr_iattr; /* request */
122+
int cr_umask; /* request */
122123
struct nfsd4_change_info cr_cinfo; /* response */
123124
struct nfs4_acl *cr_acl;
124125
struct xdr_netobj cr_label;
@@ -230,6 +231,7 @@ struct nfsd4_open {
230231
u32 op_why_no_deleg; /* response - DELEG_NONE_EXT only */
231232
u32 op_create; /* request */
232233
u32 op_createmode; /* request */
234+
int op_umask; /* request */
233235
u32 op_bmval[3]; /* request */
234236
struct iattr op_iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
235237
nfs4_verifier op_verf __attribute__((aligned(32)));

0 commit comments

Comments
 (0)