VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45983

CVE-2026-45983

Description

In the Linux kernel, the following vulnerability has been resolved:

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.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A flaw in the Linux kernel's NFSv4 server allows idmap lookup delays to cause request deferral, leaving session slots permanently in-use and blocking clients.

Vulnerability

In the Linux kernel NFSv4 server (nfsd), during v4 request compound argument decoding, operations such as SETATTR can trigger idmap lookup upcalls. If the upcall response is delayed beyond the allowed time limit, cache_check() marks the request for deferral and causes it to be dropped. This prevents nfs4svc_encode_compoundres from executing, so the NFSD4_SLOT_INUSE flag never gets cleared. The vulnerability exists in NFSv4 servers before the fix commit.

Exploitation

An attacker with network access to the NFSv4 server can send crafted NFSv4 COMPOUND requests that include operations triggering idmap lookups. By causing the idmap upcall to exceed the server's time limit (e.g., by making the idmap daemon slow or unresponsive), the attacker forces request deferral. No authentication is required if the operation is permitted; however, some operations like SETATTR may require appropriate permissions.

Impact

Successful exploitation causes the server to never clear the NFSD4_SLOT_INUSE flag for the affected session slot. Subsequent client requests to that slot fail with NFSERR_JUKEBOX because the SEQUENCE operation detects the slot as still in use. This results in a denial of service (DoS) for NFSv4 clients, preventing them from completing further requests on the same session.

Mitigation

The fix ensures that the RQ_USEDEFERRAL flag is always clear during nfs4svc_decode_compoundargs(), preventing any deferral during idmap lookups. The patch was committed as [1] and [2] in the Linux kernel stable tree. Affected systems should update to a kernel containing these commits. No workarounds have been disclosed. Not listed on CISA's Known Exploited Vulnerabilities (KEV) catalog as of publication.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1
  • Linux/Kernelllm-fuzzy
    Range: <6.14? (several stable backports)

Patches

16
063a6f22478e

nfsd: never defer requests during idmap lookup

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAnthony IliopoulosDec 22, 2025Fixed in 6.12.75via kernel-cna
3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 05efa10ed84b77..2c7a8943cad9c5 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2818,8 +2818,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index fd81db17691a1c..b7bdb9b44440bc 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5876,6 +5876,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
f9c206cdc426

nfsd: never defer requests during idmap lookup

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAnthony IliopoulosDec 22, 2025Fixed in 7.0via kernel-cna
3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 4c708cf028490f..2b805fc51262d2 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -3013,8 +3013,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 51ef97c2545688..5065727204b958 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -6013,6 +6013,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
243f71ed873f

nfsd: never defer requests during idmap lookup

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAnthony IliopoulosDec 22, 2025Fixed in 6.6.128via kernel-cna
3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index a126fae2df5664..5767080362e85a 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2763,8 +2763,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 15189e683e834d..d84eaae7cd0b62 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5492,6 +5492,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
3a72c7dedc99

nfsd: never defer requests during idmap lookup

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAnthony IliopoulosDec 22, 2025Fixed in 5.15.202via kernel-cna
3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 717e400b16b867..21e5b4c990ef36 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 2d6e88f3370bf1..7a85817fa5bfe4 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2717,8 +2717,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 9e25079804732c..46a7fd731ba0ac 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5500,6 +5500,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
d75ec4504a43

nfsd: never defer requests during idmap lookup

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAnthony IliopoulosDec 22, 2025Fixed in 6.18.14via kernel-cna
3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 42a6b914c0fe64..8dada7ef97cb17 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2995,8 +2995,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 4a403ce4fd468c..5f046d5be4a6e2 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -6001,6 +6001,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
b9abb760db20

nfsd: never defer requests during idmap lookup

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAnthony IliopoulosDec 22, 2025Fixed in 5.10.252via kernel-cna
3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 717e400b16b867..21e5b4c990ef36 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index ffd79abd99ea78..a4c7cab1679bdf 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2717,8 +2717,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 4253778a974774..7022ae52b1f20c 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5499,6 +5499,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
99e17b20fdda

nfsd: never defer requests during idmap lookup

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAnthony IliopoulosDec 22, 2025Fixed in 6.1.165via kernel-cna
3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 717e400b16b867..21e5b4c990ef36 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 714e4c471e8637..d29a37f696a445 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2716,8 +2716,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 8ef533b2dc3514..d37c90691b953e 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5499,6 +5499,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
8dff54fe88c0

nfsd: never defer requests during idmap lookup

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAnthony IliopoulosDec 22, 2025Fixed in 6.19.4via kernel-cna
3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 9ec08dd4fe823b..f780024f9a0887 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -3011,8 +3011,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 51ef97c2545688..5065727204b958 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -6013,6 +6013,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
063a6f22478e

nfsd: never defer requests during idmap lookup

3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 05efa10ed84b77..2c7a8943cad9c5 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2818,8 +2818,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index fd81db17691a1c..b7bdb9b44440bc 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5876,6 +5876,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
3a72c7dedc99

nfsd: never defer requests during idmap lookup

3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 717e400b16b867..21e5b4c990ef36 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 2d6e88f3370bf1..7a85817fa5bfe4 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2717,8 +2717,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 9e25079804732c..46a7fd731ba0ac 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5500,6 +5500,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
8dff54fe88c0

nfsd: never defer requests during idmap lookup

3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 9ec08dd4fe823b..f780024f9a0887 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -3011,8 +3011,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 51ef97c2545688..5065727204b958 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -6013,6 +6013,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
99e17b20fdda

nfsd: never defer requests during idmap lookup

3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 717e400b16b867..21e5b4c990ef36 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 714e4c471e8637..d29a37f696a445 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2716,8 +2716,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 8ef533b2dc3514..d37c90691b953e 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5499,6 +5499,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
d75ec4504a43

nfsd: never defer requests during idmap lookup

3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 42a6b914c0fe64..8dada7ef97cb17 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2995,8 +2995,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 4a403ce4fd468c..5f046d5be4a6e2 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -6001,6 +6001,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
243f71ed873f

nfsd: never defer requests during idmap lookup

3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index a126fae2df5664..5767080362e85a 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2763,8 +2763,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 15189e683e834d..d84eaae7cd0b62 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5492,6 +5492,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
b9abb760db20

nfsd: never defer requests during idmap lookup

3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 717e400b16b867..21e5b4c990ef36 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index ffd79abd99ea78..a4c7cab1679bdf 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -2717,8 +2717,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 4253778a974774..7022ae52b1f20c 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -5499,6 +5499,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
f9c206cdc426

nfsd: never defer requests during idmap lookup

3 files changed · +58 9
  • fs/nfsd/nfs4idmap.c+42 6 modified
    diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
    index 8cca1329f3485c..b5b3d45979c9b3 100644
    --- a/fs/nfsd/nfs4idmap.c
    +++ b/fs/nfsd/nfs4idmap.c
    @@ -643,13 +643,31 @@ static __be32 encode_name_from_id(struct xdr_stream *xdr,
     	return idmap_id_to_name(xdr, rqstp, type, id);
     }
     
    -__be32
    -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kuid_t *uid)
    +/**
    + * nfsd_map_name_to_uid - Map user@domain to local UID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @uid: OUT: mapped local UID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kuid_t *uid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    @@ -660,13 +678,31 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
     	return status;
     }
     
    -__be32
    -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
    -		kgid_t *gid)
    +/**
    + * nfsd_map_name_to_gid - Map user@domain to local GID
    + * @rqstp: RPC execution context
    + * @name: user@domain name to be mapped
    + * @namelen: length of name, in bytes
    + * @gid: OUT: mapped local GID value
    + *
    + * Returns nfs_ok on success or an NFSv4 status code on failure.
    + */
    +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name,
    +			    size_t namelen, kgid_t *gid)
     {
     	__be32 status;
     	u32 id = -1;
     
    +	/*
    +	 * The idmap lookup below triggers an upcall that invokes
    +	 * cache_check(). RQ_USEDEFERRAL must be clear to prevent
    +	 * cache_check() from setting RQ_DROPME via svc_defer().
    +	 * NFSv4 servers are not permitted to drop requests. Also
    +	 * RQ_DROPME will force NFSv4.1 session slot processing to
    +	 * be skipped.
    +	 */
    +	WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags));
    +
     	if (name == NULL || namelen == 0)
     		return nfserr_inval;
     
    
  • fs/nfsd/nfs4proc.c+0 2 modified
    diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
    index 4c708cf028490f..2b805fc51262d2 100644
    --- a/fs/nfsd/nfs4proc.c
    +++ b/fs/nfsd/nfs4proc.c
    @@ -3013,8 +3013,6 @@ encode_op:
     	BUG_ON(cstate->replay_owner);
     out:
     	cstate->status = status;
    -	/* Reset deferral mechanism for RPC deferrals */
    -	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
     	return rpc_success;
     }
     
    
  • fs/nfsd/nfs4xdr.c+16 1 modified
    diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
    index 51ef97c2545688..5065727204b958 100644
    --- a/fs/nfsd/nfs4xdr.c
    +++ b/fs/nfsd/nfs4xdr.c
    @@ -6013,6 +6013,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
     	args->ops = args->iops;
     	args->rqstp = rqstp;
     
    +	/*
    +	 * NFSv4 operation decoders can invoke svc cache lookups
    +	 * that trigger svc_defer() when RQ_USEDEFERRAL is set,
    +	 * setting RQ_DROPME. This creates two problems:
    +	 *
    +	 * 1. Non-idempotency: Compounds make it too hard to avoid
    +	 *    problems if a request is deferred and replayed.
    +	 *
    +	 * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set
    +	 *    during decode but SEQUENCE executes successfully, the
    +	 *    session slot will be marked INUSE. The request is then
    +	 *    dropped before encoding, so the slot is never released,
    +	 *    rendering it permanently unusable by the client.
    +	 */
    +	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
    +
     	return nfsd4_decode_compound(args);
     }
     
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"RQ_USEDEFERRAL flag left set during NFSv4 compound argument decoding allows cache_check() to defer and drop the request, which skips session slot cleanup and permanently leaks the slot."

Attack vector

An NFSv4.1+ client sends a compound request (e.g., SETATTR) that triggers an idmap lookup upcall during argument decoding. If the upcall response is delayed beyond the cache timeout, `cache_check()` calls `svc_defer()` which sets `RQ_DROPME` on the request. The request is then dropped before `nfs4svc_encode_compoundres` runs, so the session slot's `NFSD4_SLOT_INUSE` flag is never cleared. The slot becomes permanently unusable, causing all subsequent client requests using that slot to fail with `NFSERR_JUKEBOX` when the SEQUENCE operation checks the slot state [patch_id=2660728].

Affected code

The vulnerability is in the NFSv4 server's compound argument decoder (`nfs4svc_decode_compoundargs` in `fs/nfsd/nfs4xdr.c`) and the idmap lookup functions (`nfsd_map_name_to_uid` and `nfsd_map_name_to_gid` in `fs/nfsd/nfs4idmap.c`). The `RQ_USEDEFERRAL` flag was previously set during compound encoding in `nfs4proc.c`, allowing `cache_check()` to mark the request for deferral during idmap upcalls.

What the fix does

The patch makes three coordinated changes. First, in `nfs4svc_decode_compoundargs()` (`fs/nfsd/nfs4xdr.c`), `clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags)` is added at the start of decoding so that no NFSv4 request can ever be deferred during compound argument parsing. Second, `WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, ...))` guards are added in `nfsd_map_name_to_uid()` and `nfsd_map_name_to_gid()` (`fs/nfsd/nfs4idmap.c`) to catch any future code path that might leave the flag set. Third, the old `set_bit(RQ_USEDEFERRAL, ...)` in `nfs4proc.c` is removed, since the deferral mechanism is no longer used for NFSv4 requests [patch_id=2660728][patch_id=2660723].

Preconditions

  • configNFSv4.1+ session must be in use
  • inputidmap upcall (e.g., via SETATTR with a user/group name) must be triggered during compound decoding
  • inputidmap upcall response must be delayed beyond the cache timeout
  • authAttacker must be an authenticated NFS client able to send NFSv4 compounds

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.