FAILED: patch "[PATCH] NFSD: Map flex file layout IDs through the request's user" failed to apply to 6.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.1-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.1.y
git checkout FETCH_HEAD
git cherry-pick -x f913d5d2130a584d1a027ffe3dfd88b6be2e0540
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026110409-never-carnation-defe@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From f913d5d2130a584d1a027ffe3dfd88b6be2e0540 Mon Sep 17 00:00:00 2001
From: Chuck Lever <[email protected]>
Date: Mon, 20 Jul 2026 12:37:24 -0400
Subject: [PATCH] NFSD: Map flex file layout IDs through the request's user
namespace
nfsd4_ff_proc_layoutget() and nfsd4_ff_encode_layoutget() translate the file's owner and group with init_user_ns, but every other identity nfsd places on the wire goes through nfsd_user_namespace(). When the transport carries a credential from a non-initial user namespace, the flex file layout reports host-global IDs. The client copies those IDs into the AUTH_SYS credential it presents to the data server, and svcauth_unix_accept() resolves that credential in the transport's namespace, so data server I/O runs under an identity unrelated to the file's owner.
Switching to the request's namespace introduces a second hazard. from_kuid() returns (uid_t)-1 when the target namespace has no mapping for the owner, and the IOMODE_READ arm adds one to that result to derive an identity for which the data server denies writes. The addition would wrap to zero, handing the client uid 0 instead of an identity distinct from the owner.
Translate both IDs in nfsd4_ff_proc_layoutget(), which has the svc_rqst, and carry the wire values in struct pnfs_ff_layout. from_kuid_munged() substitutes overflowuid for an unmapped owner and thus never returns (uid_t)-1, so the increment cannot wrap to zero.
fs/nfsd/flexfilelayout.c +12 -8
@@ -15,6 +15,7 @@#include "nfserr.h" #include "flexfilelayoutxdr.h" +#include "auth.h" #include "pnfs.h" #include "vfs.h"
@@ -24,10 +25,10 @@ static __be32 nfsd4_ff_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode, const struct svc_fh *fhp, struct nfsd4_layoutget *args) { + struct user_namespace *userns = nfsd_user_namespace(rqstp);struct nfsd4_layout_seg *seg = &args->lg_seg;u32 device_generation =0 ;int error; -uid_t u;struct pnfs_ff_layout *fl;
@@ -50,13 +51,16 @@ nfsd4_ff_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode, fl->flags =FF_FLAGS_NO_LAYOUTCOMMIT |FF_FLAGS_NO_IO_THRU_MDS |FF_FLAGS_NO_READ_IO ; -/* Do not allow a IOMODE_READ segment to have write pemissions */ -if (seg->iomode ==IOMODE_READ ) { - u =from_kuid (&init_user_ns, inode->i_uid) +1 ; - fl->uid =make_kuid (&init_user_ns, u); - }else - fl->uid = inode->i_uid; - fl->gid = inode->i_gid; + fl->uid =from_kuid_munged (userns, inode->i_uid); + fl->gid =from_kgid_munged (userns, inode->i_gid); + +/* +* Do not allow an IOMODE_READ segment to have write permissions. +* The group is left intact so group-readable files stay readable; +* nfsd_setuser() squashes an unmapped uid to the export's anon ID. +*/ +if (seg->iomode ==IOMODE_READ ) + fl->uid++; error =nfsd4_set_deviceid (&fl->deviceid, fhp, device_generation);if (error)
fs/nfsd/flexfilelayoutxdr.c +2 -2
@@ -33,8 +33,8 @@ nfsd4_ff_encode_layoutget(struct xdr_stream *xdr, fh_len =4 +xdr_align_size (fl->fh.size); - uid.len =sprintf (uid.buf,"%u" ,from_kuid (&init_user_ns, fl->uid)); - gid.len =sprintf (gid.buf,"%u" ,from_kgid (&init_user_ns, fl->gid)); + uid.len =sprintf (uid.buf,"%u" , fl->uid); + gid.len =sprintf (gid.buf,"%u" , fl->gid);/* data server entry: deviceid + efficiency + stateid + fh list + * user + group + flags + stats_collect_hint
fs/nfsd/flexfilelayoutxdr.h +3 -2
@@ -35,8 +35,9 @@ struct pnfs_ff_device_addr {struct pnfs_ff_layout {u32 flags;u32 stats_collect_hint; -kuid_t uid; -kgid_t gid; +/* Values to encode; nfsd4_ff_proc_layoutget() has mapped these */ +u32 uid; +u32 gid;struct nfsd4_deviceid deviceid;stateid_t stateid;struct nfs_fh fh;
Sasha Levin
maintainerPATCH 1/1 NFSD: Map flex file layout IDs through the request's user namespace
From: Chuck Lever <[email protected]>
[ Upstream commit f913d5d2130a584d1a027ffe3dfd88b6be2e0540 ]
nfsd4_ff_proc_layoutget() and nfsd4_ff_encode_layoutget() translate the file's owner and group with init_user_ns, but every other identity nfsd places on the wire goes through nfsd_user_namespace(). When the transport carries a credential from a non-initial user namespace, the flex file layout reports host-global IDs. The client copies those IDs into the AUTH_SYS credential it presents to the data server, and svcauth_unix_accept() resolves that credential in the transport's namespace, so data server I/O runs under an identity unrelated to the file's owner.
Switching to the request's namespace introduces a second hazard. from_kuid() returns (uid_t)-1 when the target namespace has no mapping for the owner, and the IOMODE_READ arm adds one to that result to derive an identity for which the data server denies writes. The addition would wrap to zero, handing the client uid 0 instead of an identity distinct from the owner.
Translate both IDs in nfsd4_ff_proc_layoutget(), which has the svc_rqst, and carry the wire values in struct pnfs_ff_layout. from_kuid_munged() substitutes overflowuid for an unmapped owner and thus never returns (uid_t)-1, so the increment cannot wrap to zero.
--- fs/nfsd/blocklayout.c | 4 ++-- fs/nfsd/flexfilelayout.c | 24 ++++++++++++++---------- fs/nfsd/flexfilelayoutxdr.c | 4 ++-- fs/nfsd/flexfilelayoutxdr.h | 5 +++-- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/pnfs.h | 4 ++-- 6 files changed, 24 insertions(+), 19 deletions(-)
fs/nfsd/blocklayout.c +2 -2
@@ -18,8 +18,8 @@static __be32 -nfsd4_block_proc_layoutget (struct inode *inode,const struct svc_fh *fhp, -struct nfsd4_layoutget *args) +nfsd4_block_proc_layoutget (struct svc_rqst *rqstp,struct inode *inode, +const struct svc_fh *fhp,struct nfsd4_layoutget *args) {struct nfsd4_layout_seg *seg = &args->lg_seg;struct super_block *sb = inode->i_sb;
fs/nfsd/flexfilelayout.c +14 -10
@@ -14,19 +14,20 @@#include <linux/sunrpc/addr.h> #include "flexfilelayoutxdr.h" +#include "auth.h" #include "pnfs.h" #include "vfs.h" #define NFSDDBG_FACILITY NFSDDBG_PNFSstatic __be32 -nfsd4_ff_proc_layoutget (struct inode *inode,const struct svc_fh *fhp, -struct nfsd4_layoutget *args) +nfsd4_ff_proc_layoutget (struct svc_rqst *rqstp,struct inode *inode, +const struct svc_fh *fhp,struct nfsd4_layoutget *args) { +struct user_namespace *userns =nfsd_user_namespace (rqstp);struct nfsd4_layout_seg *seg = &args->lg_seg;u32 device_generation =0 ;int error; -uid_t u;struct pnfs_ff_layout *fl;
@@ -49,13 +50,16 @@ nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp, fl->flags =FF_FLAGS_NO_LAYOUTCOMMIT |FF_FLAGS_NO_IO_THRU_MDS |FF_FLAGS_NO_READ_IO ; -/* Do not allow a IOMODE_READ segment to have write pemissions */ -if (seg->iomode ==IOMODE_READ ) { - u =from_kuid (&init_user_ns, inode->i_uid) +1 ; - fl->uid =make_kuid (&init_user_ns, u); - }else - fl->uid = inode->i_uid; - fl->gid = inode->i_gid; + fl->uid =from_kuid_munged (userns, inode->i_uid); + fl->gid =from_kgid_munged (userns, inode->i_gid); + +/* +* Do not allow an IOMODE_READ segment to have write permissions. +* The group is left intact so group-readable files stay readable; +* nfsd_setuser() squashes an unmapped uid to the export's anon ID. +*/ +if (seg->iomode ==IOMODE_READ ) + fl->uid++; error =nfsd4_set_deviceid (&fl->deviceid, fhp, device_generation);if (error)
fs/nfsd/flexfilelayoutxdr.c +2 -2
@@ -32,8 +32,8 @@ nfsd4_ff_encode_layoutget(struct xdr_stream *xdr, fh_len =4 +xdr_align_size (fl->fh.size); - uid.len =sprintf (uid.buf,"%u" ,from_kuid (&init_user_ns, fl->uid)); - gid.len =sprintf (gid.buf,"%u" ,from_kgid (&init_user_ns, fl->gid)); + uid.len =sprintf (uid.buf,"%u" , fl->uid); + gid.len =sprintf (gid.buf,"%u" , fl->gid);/* data server entry: deviceid + efficiency + stateid + fh list + * user + group + flags + stats_collect_hint
fs/nfsd/flexfilelayoutxdr.h +3 -2
@@ -35,8 +35,9 @@ struct pnfs_ff_device_addr {struct pnfs_ff_layout {u32 flags;u32 stats_collect_hint; -kuid_t uid; -kgid_t gid; +/* Values to encode; nfsd4_ff_proc_layoutget() has mapped these */ +u32 uid; +u32 gid;struct nfsd4_deviceid deviceid;stateid_t stateid;struct nfs_fh fh;
fs/nfsd/nfs4proc.c +1 -1
@@ -2260,7 +2260,7 @@ nfsd4_layoutget(struct svc_rqst *rqstp,if (atomic_read (&ls->ls_stid.sc_file->fi_lo_recalls)) goto out_put_stid; - nfserr = ops->proc_layoutget (d_inode (current_fh->fh_dentry), + nfserr = ops->proc_layoutget (rqstp,d_inode (current_fh->fh_dentry), current_fh, lgp);if (nfserr) goto out_put_stid;
fs/nfsd/pnfs.h +2 -2
@@ -29,8 +29,8 @@ struct nfsd4_layout_ops {__be32 (*encode_getdeviceinfo)(struct xdr_stream *xdr,struct nfsd4_getdeviceinfo *gdevp); -__be32 (*proc_layoutget)(struct inode *,const struct svc_fh *fhp, -struct nfsd4_layoutget *lgp); +__be32 (*proc_layoutget)(struct svc_rqst *rqstp,struct inode *inode, +const struct svc_fh *fhp,struct nfsd4_layoutget *lgp);__be32 (*encode_layoutget)(struct xdr_stream *,struct nfsd4_layoutget *lgp);
Signature · 1 line
2.53.0