Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nfsd: never defer requests during idmap lookup

During v4 request compound arg decoding, some ops (e.g. SETATTR)
can trigger idmap lookup upcalls. When those upcall responses get
delayed beyond the allowed time limit, cache_check() will mark the
request for deferral and cause it to be dropped.

This prevents nfs4svc_encode_compoundres from being executed, and
thus the session slot flag NFSD4_SLOT_INUSE never gets cleared.
Subsequent client requests will fail with NFSERR_JUKEBOX, given
that the slot will be marked as in-use, making the SEQUENCE op
fail.

Fix this by making sure that the RQ_USEDEFERRAL flag is always
clear during nfs4svc_decode_compoundargs(), since no v4 request
should ever be deferred.

Fixes: 2f425878b6a7 ("nfsd: don't use the deferral service, return NFS4ERR_DELAY")
Signed-off-by: Anthony Iliopoulos <ailiop@suse.com>
Reviewed-by: NeilBrown <neil@brown.name>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by

Anthony Iliopoulos and committed by
Chuck Lever
f9c206cd 9abb3549

+58 -8
+42 -6
fs/nfsd/nfs4idmap.c
··· 643 643 return idmap_id_to_name(xdr, rqstp, type, id); 644 644 } 645 645 646 - __be32 647 - nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, 648 - kuid_t *uid) 646 + /** 647 + * nfsd_map_name_to_uid - Map user@domain to local UID 648 + * @rqstp: RPC execution context 649 + * @name: user@domain name to be mapped 650 + * @namelen: length of name, in bytes 651 + * @uid: OUT: mapped local UID value 652 + * 653 + * Returns nfs_ok on success or an NFSv4 status code on failure. 654 + */ 655 + __be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, 656 + size_t namelen, kuid_t *uid) 649 657 { 650 658 __be32 status; 651 659 u32 id = -1; 660 + 661 + /* 662 + * The idmap lookup below triggers an upcall that invokes 663 + * cache_check(). RQ_USEDEFERRAL must be clear to prevent 664 + * cache_check() from setting RQ_DROPME via svc_defer(). 665 + * NFSv4 servers are not permitted to drop requests. Also 666 + * RQ_DROPME will force NFSv4.1 session slot processing to 667 + * be skipped. 668 + */ 669 + WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags)); 652 670 653 671 if (name == NULL || namelen == 0) 654 672 return nfserr_inval; ··· 678 660 return status; 679 661 } 680 662 681 - __be32 682 - nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, 683 - kgid_t *gid) 663 + /** 664 + * nfsd_map_name_to_gid - Map user@domain to local GID 665 + * @rqstp: RPC execution context 666 + * @name: user@domain name to be mapped 667 + * @namelen: length of name, in bytes 668 + * @gid: OUT: mapped local GID value 669 + * 670 + * Returns nfs_ok on success or an NFSv4 status code on failure. 671 + */ 672 + __be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, 673 + size_t namelen, kgid_t *gid) 684 674 { 685 675 __be32 status; 686 676 u32 id = -1; 677 + 678 + /* 679 + * The idmap lookup below triggers an upcall that invokes 680 + * cache_check(). RQ_USEDEFERRAL must be clear to prevent 681 + * cache_check() from setting RQ_DROPME via svc_defer(). 682 + * NFSv4 servers are not permitted to drop requests. Also 683 + * RQ_DROPME will force NFSv4.1 session slot processing to 684 + * be skipped. 685 + */ 686 + WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags)); 687 687 688 688 if (name == NULL || namelen == 0) 689 689 return nfserr_inval;
-2
fs/nfsd/nfs4proc.c
··· 3013 3013 BUG_ON(cstate->replay_owner); 3014 3014 out: 3015 3015 cstate->status = status; 3016 - /* Reset deferral mechanism for RPC deferrals */ 3017 - set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); 3018 3016 return rpc_success; 3019 3017 } 3020 3018
+16
fs/nfsd/nfs4xdr.c
··· 6013 6013 args->ops = args->iops; 6014 6014 args->rqstp = rqstp; 6015 6015 6016 + /* 6017 + * NFSv4 operation decoders can invoke svc cache lookups 6018 + * that trigger svc_defer() when RQ_USEDEFERRAL is set, 6019 + * setting RQ_DROPME. This creates two problems: 6020 + * 6021 + * 1. Non-idempotency: Compounds make it too hard to avoid 6022 + * problems if a request is deferred and replayed. 6023 + * 6024 + * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set 6025 + * during decode but SEQUENCE executes successfully, the 6026 + * session slot will be marked INUSE. The request is then 6027 + * dropped before encoding, so the slot is never released, 6028 + * rendering it permanently unusable by the client. 6029 + */ 6030 + clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); 6031 + 6016 6032 return nfsd4_decode_compound(args); 6017 6033 } 6018 6034