FAILED: patch "[PATCH] nfsd: widen nfsd_genl_rqstp address fields to" failed to apply to 6.18-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x a99d720ed2a5258564e5e9d5f39f3184a030d354
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090358-marital-swizzle-715d@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From a99d720ed2a5258564e5e9d5f39f3184a030d354 Mon Sep 17 00:00:00 2001
From: Jeff Layton <[email protected]>
Date: Tue, 2 Jun 2026 12:23:17 -0400
Subject: [PATCH] nfsd: widen nfsd_genl_rqstp address fields to
sockaddr_storage
struct nfsd_genl_rqstp declares rq_daddr and rq_saddr as plain "struct sockaddr" (16 bytes). When an IPv6 NFS client is connected, nfsd_genl_rpc_status_compose_msg() casts these fields to "struct sockaddr_in6 *" (28 bytes) and reads sin6_addr at offset 8..24, which extends 8 bytes past the end of the 16-byte sockaddr field into the adjacent rq_flags member. The 16-byte nla_put_in6_addr then ships 8 bytes of truncated IPv6 address followed by 8 bytes of rq_flags to userspace via the NFSD_A_RPC_STATUS_SADDR6/DADDR6 netlink attributes.
This is reachable by any unprivileged process in the network namespace because NFSD_CMD_RPC_STATUS_GET uses GENL_CMD_CAP_DUMP without GENL_ADMIN_PERM.
Fix by widening rq_daddr and rq_saddr to struct sockaddr_storage so the IPv6 casts operate within bounds, copying sizeof(struct sockaddr_storage) bytes in the memcpy calls so the full address is captured, and zero-initializing the genl_rqstp stack variable to prevent leaking uninitialized tail bytes through netlink.
fs/nfsd/nfsctl.c +6 -6
@@ -1414,8 +1414,8 @@ static int create_proc_exports_entry(void)unsigned int nfsd_net_id;struct nfsd_genl_rqstp { -struct sockaddr rq_daddr; -struct sockaddr rq_saddr; +struct sockaddr_storage rq_daddr; +struct sockaddr_storage rq_saddr;unsigned long rq_flags;ktime_t rq_stime;__be32 rq_xid;
@@ -1450,7 +1450,7 @@ static int nfsd_genl_rpc_status_compose_msg(struct sk_buff *skb, NFSD_A_RPC_STATUS_PAD))return -ENOBUFS ; -switch (genl_rqstp->rq_saddr.sa_family) { +switch (genl_rqstp->rq_saddr.ss_family) {case AF_INET : {const struct sockaddr_in *s_in, *d_in;
@@ -1527,7 +1527,7 @@ int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb,list_for_each_entry_rcu (rqstp, &nn->nfsd_serv->sv_pools[i].sp_all_threads, rq_all) { -struct nfsd_genl_rqstp genl_rqstp; +struct nfsd_genl_rqstp genl_rqstp = {};unsigned int status_counter;if (rqstp_index++ < cb->args[1 ])/* already consumed */
@@ -1551,9 +1551,9 @@ int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb, genl_rqstp.rq_stime = rqstp->rq_stime; genl_rqstp.rq_opcnt =0 ;memcpy (&genl_rqstp.rq_daddr,svc_daddr (rqstp), -sizeof (struct sockaddr )); +sizeof (struct sockaddr_storage ));memcpy (&genl_rqstp.rq_saddr,svc_addr (rqstp), -sizeof (struct sockaddr )); +sizeof (struct sockaddr_storage ));#ifdef CONFIG_NFSD_V4 if (rqstp->rq_vers == NFS4_VERSION &&
Sasha Levin
maintainerPATCH 1/2 nfsd: move struct nfsd_genl_rqstp to nfsctl.c
From: Jeff Layton <[email protected]>
[ Upstream commit 1ed3df33bdbda5fd639571afe9c7cd282ff82cd9 ]
It's not used outside of that file.
Stable-dep-of: a99d720ed2a5 ("nfsd: widen nfsd_genl_rqstp address fields to sockaddr_storage")
--- fs/nfsd/nfsctl.c | 15 +++++++++++++++ fs/nfsd/nfsd.h | 15 --------------- 2 files changed, 15 insertions(+), 15 deletions(-)
fs/nfsd/nfsctl.c +15 -0
@@ -1411,6 +1411,21 @@ static int create_proc_exports_entry(void)unsigned int nfsd_net_id; +struct nfsd_genl_rqstp { +struct sockaddr rq_daddr; +struct sockaddr rq_saddr; +unsigned long rq_flags; +ktime_t rq_stime; +__be32 rq_xid; +u32 rq_vers; +u32 rq_prog; +u32 rq_proc; + +/* NFSv4 compound */ +u32 rq_opcnt; +u32 rq_opnum[16 ]; +}; +static int nfsd_genl_rpc_status_compose_msg (struct sk_buff *skb,struct netlink_callback *cb,struct nfsd_genl_rqstp *genl_rqstp)
fs/nfsd/nfsd.h +0 -15
@@ -60,21 +60,6 @@ struct readdir_cd {/* Maximum number of operations per session compound */ #define NFSD_MAX_OPS_PER_COMPOUND 200 -struct nfsd_genl_rqstp { -struct sockaddr rq_daddr; -struct sockaddr rq_saddr; -unsigned long rq_flags; -ktime_t rq_stime; -__be32 rq_xid; -u32 rq_vers; -u32 rq_prog; -u32 rq_proc; - -/* NFSv4 compound */ -u32 rq_opcnt; -u32 rq_opnum[16 ]; -}; -extern struct svc_program nfsd_programs[];extern const struct svc_version nfsd_version2, nfsd_version3, nfsd_version4;extern struct mutex nfsd_mutex;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 nfsd: widen nfsd_genl_rqstp address fields to sockaddr_storage
From: Jeff Layton <[email protected]>
[ Upstream commit a99d720ed2a5258564e5e9d5f39f3184a030d354 ]
struct nfsd_genl_rqstp declares rq_daddr and rq_saddr as plain "struct sockaddr" (16 bytes). When an IPv6 NFS client is connected, nfsd_genl_rpc_status_compose_msg() casts these fields to "struct sockaddr_in6 *" (28 bytes) and reads sin6_addr at offset 8..24, which extends 8 bytes past the end of the 16-byte sockaddr field into the adjacent rq_flags member. The 16-byte nla_put_in6_addr then ships 8 bytes of truncated IPv6 address followed by 8 bytes of rq_flags to userspace via the NFSD_A_RPC_STATUS_SADDR6/DADDR6 netlink attributes.
This is reachable by any unprivileged process in the network namespace because NFSD_CMD_RPC_STATUS_GET uses GENL_CMD_CAP_DUMP without GENL_ADMIN_PERM.
Fix by widening rq_daddr and rq_saddr to struct sockaddr_storage so the IPv6 casts operate within bounds, copying sizeof(struct sockaddr_storage) bytes in the memcpy calls so the full address is captured, and zero-initializing the genl_rqstp stack variable to prevent leaking uninitialized tail bytes through netlink.
--- fs/nfsd/nfsctl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
fs/nfsd/nfsctl.c +6 -6
@@ -1412,8 +1412,8 @@ static int create_proc_exports_entry(void)unsigned int nfsd_net_id;struct nfsd_genl_rqstp { -struct sockaddr rq_daddr; -struct sockaddr rq_saddr; +struct sockaddr_storage rq_daddr; +struct sockaddr_storage rq_saddr;unsigned long rq_flags;ktime_t rq_stime;__be32 rq_xid;
@@ -1448,7 +1448,7 @@ static int nfsd_genl_rpc_status_compose_msg(struct sk_buff *skb, NFSD_A_RPC_STATUS_PAD))return -ENOBUFS ; -switch (genl_rqstp->rq_saddr.sa_family) { +switch (genl_rqstp->rq_saddr.ss_family) {case AF_INET : {const struct sockaddr_in *s_in, *d_in;
@@ -1525,7 +1525,7 @@ int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb,list_for_each_entry_rcu (rqstp, &nn->nfsd_serv->sv_pools[i].sp_all_threads, rq_all) { -struct nfsd_genl_rqstp genl_rqstp; +struct nfsd_genl_rqstp genl_rqstp = {};unsigned int status_counter;if (rqstp_index++ < cb->args[1 ])/* already consumed */
@@ -1549,9 +1549,9 @@ int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb, genl_rqstp.rq_stime = rqstp->rq_stime; genl_rqstp.rq_opcnt =0 ;memcpy (&genl_rqstp.rq_daddr,svc_daddr (rqstp), -sizeof (struct sockaddr )); +sizeof (struct sockaddr_storage ));memcpy (&genl_rqstp.rq_saddr,svc_addr (rqstp), -sizeof (struct sockaddr )); +sizeof (struct sockaddr_storage ));#ifdef CONFIG_NFSD_V4 if (rqstp->rq_vers == NFS4_VERSION &&
Signature · 1 line
2.53.0