From 7d84a7734326f2a5667c2effdb63959d513e6675 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 30 Oct 2022 11:53:10 +0100 Subject: [PATCH] 5.15-stable patches added patches: nfsv4-fix-free-of-uninitialized-nfs4_label-on-referral-lookup.patch --- ...alized-nfs4_label-on-referral-lookup.patch | 190 ++++++++++++++++++ queue-5.15/series | 1 + 2 files changed, 191 insertions(+) create mode 100644 queue-5.15/nfsv4-fix-free-of-uninitialized-nfs4_label-on-referral-lookup.patch diff --git a/queue-5.15/nfsv4-fix-free-of-uninitialized-nfs4_label-on-referral-lookup.patch b/queue-5.15/nfsv4-fix-free-of-uninitialized-nfs4_label-on-referral-lookup.patch new file mode 100644 index 00000000000..a465158906b --- /dev/null +++ b/queue-5.15/nfsv4-fix-free-of-uninitialized-nfs4_label-on-referral-lookup.patch @@ -0,0 +1,190 @@ +From c3ed222745d9ad7b69299b349a64ba533c64a34f Mon Sep 17 00:00:00 2001 +From: Benjamin Coddington +Date: Sat, 14 May 2022 07:05:13 -0400 +Subject: NFSv4: Fix free of uninitialized nfs4_label on referral lookup. + +From: Benjamin Coddington + +commit c3ed222745d9ad7b69299b349a64ba533c64a34f upstream. + +Send along the already-allocated fattr along with nfs4_fs_locations, and +drop the memcpy of fattr. We end up growing two more allocations, but this +fixes up a crash as: + +PID: 790 TASK: ffff88811b43c000 CPU: 0 COMMAND: "ls" + #0 [ffffc90000857920] panic at ffffffff81b9bfde + #1 [ffffc900008579c0] do_trap at ffffffff81023a9b + #2 [ffffc90000857a10] do_error_trap at ffffffff81023b78 + #3 [ffffc90000857a58] exc_stack_segment at ffffffff81be1f45 + #4 [ffffc90000857a80] asm_exc_stack_segment at ffffffff81c009de + #5 [ffffc90000857b08] nfs_lookup at ffffffffa0302322 [nfs] + #6 [ffffc90000857b70] __lookup_slow at ffffffff813a4a5f + #7 [ffffc90000857c60] walk_component at ffffffff813a86c4 + #8 [ffffc90000857cb8] path_lookupat at ffffffff813a9553 + #9 [ffffc90000857cf0] filename_lookup at ffffffff813ab86b + +Suggested-by: Trond Myklebust +Fixes: 9558a007dbc3 ("NFS: Remove the label from the nfs4_lookup_res struct") +Signed-off-by: Benjamin Coddington +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfs/nfs4namespace.c | 9 +++++++-- + fs/nfs/nfs4proc.c | 15 +++++++-------- + fs/nfs/nfs4state.c | 9 ++++++++- + fs/nfs/nfs4xdr.c | 4 ++-- + include/linux/nfs_xdr.h | 2 +- + 5 files changed, 25 insertions(+), 14 deletions(-) + +--- a/fs/nfs/nfs4namespace.c ++++ b/fs/nfs/nfs4namespace.c +@@ -417,6 +417,9 @@ static int nfs_do_refmount(struct fs_con + fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); + if (!fs_locations) + goto out_free; ++ fs_locations->fattr = nfs_alloc_fattr(); ++ if (!fs_locations->fattr) ++ goto out_free_2; + + /* Get locations */ + dentry = ctx->clone_data.dentry; +@@ -427,14 +430,16 @@ static int nfs_do_refmount(struct fs_con + err = nfs4_proc_fs_locations(client, d_inode(parent), &dentry->d_name, fs_locations, page); + dput(parent); + if (err != 0) +- goto out_free_2; ++ goto out_free_3; + + err = -ENOENT; + if (fs_locations->nlocations <= 0 || + fs_locations->fs_path.ncomponents <= 0) +- goto out_free_2; ++ goto out_free_3; + + err = nfs_follow_referral(fc, fs_locations); ++out_free_3: ++ kfree(fs_locations->fattr); + out_free_2: + kfree(fs_locations); + out_free: +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -4213,6 +4213,8 @@ static int nfs4_get_referral(struct rpc_ + if (locations == NULL) + goto out; + ++ locations->fattr = fattr; ++ + status = nfs4_proc_fs_locations(client, dir, name, locations, page); + if (status != 0) + goto out; +@@ -4222,17 +4224,14 @@ static int nfs4_get_referral(struct rpc_ + * referral. Cause us to drop into the exception handler, which + * will kick off migration recovery. + */ +- if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) { ++ if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &fattr->fsid)) { + dprintk("%s: server did not return a different fsid for" + " a referral at %s\n", __func__, name->name); + status = -NFS4ERR_MOVED; + goto out; + } + /* Fixup attributes for the nfs_lookup() call to nfs_fhget() */ +- nfs_fixup_referral_attributes(&locations->fattr); +- +- /* replace the lookup nfs_fattr with the locations nfs_fattr */ +- memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr)); ++ nfs_fixup_referral_attributes(fattr); + memset(fhandle, 0, sizeof(struct nfs_fh)); + out: + if (page) +@@ -7917,7 +7916,7 @@ static int _nfs4_proc_fs_locations(struc + else + bitmask[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; + +- nfs_fattr_init(&fs_locations->fattr); ++ nfs_fattr_init(fs_locations->fattr); + fs_locations->server = server; + fs_locations->nlocations = 0; + status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0); +@@ -7982,7 +7981,7 @@ static int _nfs40_proc_get_locations(str + unsigned long now = jiffies; + int status; + +- nfs_fattr_init(&locations->fattr); ++ nfs_fattr_init(locations->fattr); + locations->server = server; + locations->nlocations = 0; + +@@ -8035,7 +8034,7 @@ static int _nfs41_proc_get_locations(str + }; + int status; + +- nfs_fattr_init(&locations->fattr); ++ nfs_fattr_init(locations->fattr); + locations->server = server; + locations->nlocations = 0; + +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -2096,6 +2096,11 @@ static int nfs4_try_migration(struct nfs + dprintk("<-- %s: no memory\n", __func__); + goto out; + } ++ locations->fattr = nfs_alloc_fattr(); ++ if (locations->fattr == NULL) { ++ dprintk("<-- %s: no memory\n", __func__); ++ goto out; ++ } + + inode = d_inode(server->super->s_root); + result = nfs4_proc_get_locations(server, NFS_FH(inode), locations, +@@ -2110,7 +2115,7 @@ static int nfs4_try_migration(struct nfs + if (!locations->nlocations) + goto out; + +- if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) { ++ if (!(locations->fattr->valid & NFS_ATTR_FATTR_V4_LOCATIONS)) { + dprintk("<-- %s: No fs_locations data, migration skipped\n", + __func__); + goto out; +@@ -2135,6 +2140,8 @@ static int nfs4_try_migration(struct nfs + out: + if (page != NULL) + __free_page(page); ++ if (locations != NULL) ++ kfree(locations->fattr); + kfree(locations); + if (result) { + pr_err("NFS: migration recovery failed (server %s)\n", +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -7028,7 +7028,7 @@ static int nfs4_xdr_dec_fs_locations(str + if (res->migration) { + xdr_enter_page(xdr, PAGE_SIZE); + status = decode_getfattr_generic(xdr, +- &res->fs_locations->fattr, ++ res->fs_locations->fattr, + NULL, res->fs_locations, + NULL, res->fs_locations->server); + if (status) +@@ -7041,7 +7041,7 @@ static int nfs4_xdr_dec_fs_locations(str + goto out; + xdr_enter_page(xdr, PAGE_SIZE); + status = decode_getfattr_generic(xdr, +- &res->fs_locations->fattr, ++ res->fs_locations->fattr, + NULL, res->fs_locations, + NULL, res->fs_locations->server); + } +--- a/include/linux/nfs_xdr.h ++++ b/include/linux/nfs_xdr.h +@@ -1219,7 +1219,7 @@ struct nfs4_fs_location { + + #define NFS4_FS_LOCATIONS_MAXENTRIES 10 + struct nfs4_fs_locations { +- struct nfs_fattr fattr; ++ struct nfs_fattr *fattr; + const struct nfs_server *server; + struct nfs4_pathname fs_path; + int nlocations; diff --git a/queue-5.15/series b/queue-5.15/series index e69de29bb2d..9ba4fe62a36 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -0,0 +1 @@ +nfsv4-fix-free-of-uninitialized-nfs4_label-on-referral-lookup.patch -- 2.47.3