aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4state.c32
-rw-r--r--fs/nfsd/nfs4xdr.c80
2 files changed, 73 insertions, 39 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index a39a542d8be5..6bfa293e1c91 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2418,31 +2418,6 @@ find_file(struct inode *ino)
2418 return NULL; 2418 return NULL;
2419} 2419}
2420 2420
2421static inline int access_valid(u32 x, u32 minorversion)
2422{
2423 if ((x & NFS4_SHARE_ACCESS_MASK) < NFS4_SHARE_ACCESS_READ)
2424 return 0;
2425 if ((x & NFS4_SHARE_ACCESS_MASK) > NFS4_SHARE_ACCESS_BOTH)
2426 return 0;
2427 x &= ~NFS4_SHARE_ACCESS_MASK;
2428 if (minorversion && x) {
2429 if ((x & NFS4_SHARE_WANT_MASK) > NFS4_SHARE_WANT_CANCEL)
2430 return 0;
2431 if ((x & NFS4_SHARE_WHEN_MASK) > NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED)
2432 return 0;
2433 x &= ~(NFS4_SHARE_WANT_MASK | NFS4_SHARE_WHEN_MASK);
2434 }
2435 if (x)
2436 return 0;
2437 return 1;
2438}
2439
2440static inline int deny_valid(u32 x)
2441{
2442 /* Note: unlike access bits, deny bits may be zero. */
2443 return x <= NFS4_SHARE_DENY_BOTH;
2444}
2445
2446/* 2421/*
2447 * Called to check deny when READ with all zero stateid or 2422 * Called to check deny when READ with all zero stateid or
2448 * WRITE with all zero or all one stateid 2423 * WRITE with all zero or all one stateid
@@ -2918,10 +2893,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
2918 struct nfs4_delegation *dp = NULL; 2893 struct nfs4_delegation *dp = NULL;
2919 __be32 status; 2894 __be32 status;
2920 2895
2921 status = nfserr_inval;
2922 if (!access_valid(open->op_share_access, resp->cstate.minorversion)
2923 || !deny_valid(open->op_share_deny))
2924 goto out;
2925 /* 2896 /*
2926 * Lookup file; if found, lookup stateid and check open request, 2897 * Lookup file; if found, lookup stateid and check open request,
2927 * and check for delegations in the process of being recalled. 2898 * and check for delegations in the process of being recalled.
@@ -3571,9 +3542,6 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
3571 (int)cstate->current_fh.fh_dentry->d_name.len, 3542 (int)cstate->current_fh.fh_dentry->d_name.len,
3572 cstate->current_fh.fh_dentry->d_name.name); 3543 cstate->current_fh.fh_dentry->d_name.name);
3573 3544
3574 if (!access_valid(od->od_share_access, cstate->minorversion)
3575 || !deny_valid(od->od_share_deny))
3576 return nfserr_inval;
3577 /* We don't yet support WANT bits: */ 3545 /* We don't yet support WANT bits: */
3578 od->od_share_access &= NFS4_SHARE_ACCESS_MASK; 3546 od->od_share_access &= NFS4_SHARE_ACCESS_MASK;
3579 3547
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 5779acde7e70..94da8bb36c85 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -639,6 +639,64 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup
639 DECODE_TAIL; 639 DECODE_TAIL;
640} 640}
641 641
642static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *x)
643{
644 __be32 *p;
645 u32 w;
646
647 READ_BUF(4);
648 READ32(w);
649 *x = w;
650 switch (w & NFS4_SHARE_ACCESS_MASK) {
651 case NFS4_SHARE_ACCESS_READ:
652 case NFS4_SHARE_ACCESS_WRITE:
653 case NFS4_SHARE_ACCESS_BOTH:
654 break;
655 default:
656 return nfserr_bad_xdr;
657 }
658 w &= !NFS4_SHARE_ACCESS_MASK;
659 if (!w)
660 return nfs_ok;
661 if (!argp->minorversion)
662 return nfserr_bad_xdr;
663 switch (w & NFS4_SHARE_WANT_MASK) {
664 case NFS4_SHARE_WANT_NO_PREFERENCE:
665 case NFS4_SHARE_WANT_READ_DELEG:
666 case NFS4_SHARE_WANT_WRITE_DELEG:
667 case NFS4_SHARE_WANT_ANY_DELEG:
668 case NFS4_SHARE_WANT_NO_DELEG:
669 case NFS4_SHARE_WANT_CANCEL:
670 break;
671 default:
672 return nfserr_bad_xdr;
673 }
674 w &= !NFS4_SHARE_WANT_MASK;
675 if (!w)
676 return nfs_ok;
677 switch (w) {
678 case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL:
679 case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED:
680 return nfs_ok;
681 }
682xdr_error:
683 return nfserr_bad_xdr;
684}
685
686static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x)
687{
688 __be32 *p;
689
690 READ_BUF(4);
691 READ32(*x);
692 /* Note: unlinke access bits, deny bits may be zero. */
693 if (*x & !NFS4_SHARE_DENY_BOTH)
694 return nfserr_bad_xdr;
695 return nfs_ok;
696xdr_error:
697 return nfserr_bad_xdr;
698}
699
642static __be32 700static __be32
643nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) 701nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
644{ 702{
@@ -649,10 +707,15 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
649 open->op_openowner = NULL; 707 open->op_openowner = NULL;
650 708
651 /* seqid, share_access, share_deny, clientid, ownerlen */ 709 /* seqid, share_access, share_deny, clientid, ownerlen */
652 READ_BUF(16 + sizeof(clientid_t)); 710 READ_BUF(4);
653 READ32(open->op_seqid); 711 READ32(open->op_seqid);
654 READ32(open->op_share_access); 712 status = nfsd4_decode_share_access(argp, &open->op_share_access);
655 READ32(open->op_share_deny); 713 if (status)
714 goto xdr_error;
715 status = nfsd4_decode_share_deny(argp, &open->op_share_deny);
716 if (status)
717 goto xdr_error;
718 READ_BUF(sizeof(clientid_t) + 4);
656 COPYMEM(&open->op_clientid, sizeof(clientid_t)); 719 COPYMEM(&open->op_clientid, sizeof(clientid_t));
657 READ32(open->op_owner.len); 720 READ32(open->op_owner.len);
658 721
@@ -753,11 +816,14 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d
753 status = nfsd4_decode_stateid(argp, &open_down->od_stateid); 816 status = nfsd4_decode_stateid(argp, &open_down->od_stateid);
754 if (status) 817 if (status)
755 return status; 818 return status;
756 READ_BUF(12); 819 READ_BUF(4);
757 READ32(open_down->od_seqid); 820 READ32(open_down->od_seqid);
758 READ32(open_down->od_share_access); 821 status = nfsd4_decode_share_access(argp, &open_down->od_share_access);
759 READ32(open_down->od_share_deny); 822 if (status)
760 823 return status;
824 status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny);
825 if (status)
826 return status;
761 DECODE_TAIL; 827 DECODE_TAIL;
762} 828}
763 829