aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2011-10-10 14:37:13 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-10-11 08:53:12 -0400
commit04f9e664b21c4440daf4d08f31db9b18517e4b8d (patch)
treeea47eaac63adcff1771acc697a76d0635ae4b9a4 /fs/nfsd
parentc30e92df30d7d5fe65262fbce5d1b7de675fe34e (diff)
nfsd4: move access/deny validity checks to xdr code
I'd rather put more of these sorts of checks into standardized xdr decoders for the various types rather than have them cluttering up the core logic in nfs4proc.c and nfs4state.c. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
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