diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 32 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 80 |
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 | ||
2421 | static 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 | |||
2440 | static 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 | ||
642 | static __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 | } | ||
682 | xdr_error: | ||
683 | return nfserr_bad_xdr; | ||
684 | } | ||
685 | |||
686 | static __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; | ||
696 | xdr_error: | ||
697 | return nfserr_bad_xdr; | ||
698 | } | ||
699 | |||
642 | static __be32 | 700 | static __be32 |
643 | nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) | 701 | nfsd4_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 | ||