FAILED: patch "[PATCH] lockd: fix NULL dereference on lockowner allocation failure" failed to apply to 6.6-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.6-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.6.y
git checkout FETCH_HEAD
git cherry-pick -x 4c7fc129db061c7daab841c4f3c342d894832362
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090350-anatomy-sublevel-d97c@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 4c7fc129db061c7daab841c4f3c342d894832362 Mon Sep 17 00:00:00 2001
From: Shuangpeng Bai <[email protected]>
Date: Fri, 17 Jul 2026 13:28:09 -0400
Subject: [PATCH] lockd: fix NULL dereference on lockowner allocation failure
nlmclnt_locks_init_private() installs NLM file lock operations even when nlmclnt_find_lockowner() fails to allocate a lockowner. nlmclnt_proc() then returns -ENOMEM, but the VFS still tears down the partially initialized file_lock and calls locks_release_private().
That invokes nlmclnt_locks_release_private(), which dereferences fl->fl_u.nfs_fl.owner and crashes because the owner was never installed.
Clear fl_ops before attempting to initialize the NLM private state, and install the NLM lock operations only after a lockowner has been allocated successfully.
fs/lockd/clntproc.c +3 -0
@@ -487,9 +487,12 @@ static const struct file_lock_operations nlmclnt_lock_ops = {static void nlmclnt_locks_init_private (struct file_lock *fl,struct nlm_host *host) { fl->fl_u.nfs_fl.state =0 ; + fl->fl_ops =NULL ; fl->fl_u.nfs_fl.owner =nlmclnt_find_lockowner (host, fl->c.flc_owner);INIT_LIST_HEAD (&fl->fl_u.nfs_fl.list); +if (!fl->fl_u.nfs_fl.owner) +return ; fl->fl_ops = &nlmclnt_lock_ops; }
Sasha Levin
maintainerPATCH 1/2 filelock: split common fields into struct file_lock_core
From: Jeff Layton <[email protected]>
[ Upstream commit a69ce85ec9af6bdc0b3511959a7dc1a324e5e16a ]
In a future patch, we're going to split file leases into their own structure. Since a lot of the underlying machinery uses the same fields move those into a new file_lock_core, and embed that inside struct file_lock.
For now, add some macros to ensure that we can continue to build while the conversion is in progress.
Backport notes for 6.6:
- Retain the stable tree's unsigned PID type in flc_pid.
- Omit the helper conversions whose functions and iterator are absent here; do not introduce new functions.
- Drop unrelated whitespace cleanups, including the obsolete CIFS writeback hunk, and preserve the stable CIFS implementation.
- Rename conflicting local variables, parameters and filelock trace-entry fields so the compatibility macros do not expand inside declarations. Keep the trace output labels and the existing variable types.
- Convert the owner argument in nlmclnt_locks_init_private() to c.flc_owner and match the upstream wrapping so 4c7fc129db061 applies unchanged.
[ sashal: Reduced backport -- upstream a69ce85ec9af6 touches 24 file(s), this
backport carries 27. Not backported here:
fs/open.c
fs/posix_acl.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: 4c7fc129db06 ("lockd: fix NULL dereference on lockowner allocation failure")
--- fs/9p/vfs_file.c | 7 ++-- fs/afs/flock.c | 6 +-- fs/afs/internal.h | 1 + fs/ceph/locks.c | 1 + fs/dlm/plock.c | 5 ++- fs/fuse/file.c | 1 + fs/gfs2/file.c | 1 + fs/lockd/clntproc.c | 24 ++++++------ fs/locks.c | 9 +++-- fs/nfs/file.c | 1 + fs/nfs/nfs4_fs.h | 1 + fs/nfs/nfs4proc.c | 10 ++--- fs/nfs/nfs4state.c | 14 +++---- fs/nfs/write.c | 1 + fs/nfsd/netns.h | 1 + fs/nfsd/nfs4state.c | 24 ++++++------ fs/ocfs2/locks.c | 1 + fs/ocfs2/stack_user.c | 1 + fs/smb/client/cifsglob.h | 1 + fs/smb/client/cifssmb.c | 1 + fs/smb/client/file.c | 1 + fs/smb/client/smb2file.c | 1 + fs/smb/server/smb2pdu.c | 1 + fs/smb/server/vfs.c | 1 + include/linux/filelock.h | 47 ++++++++++++++++------- include/linux/lockd/xdr.h | 1 + include/trace/events/filelock.h | 66 ++++++++++++++++----------------- 27 files changed, 136 insertions(+), 93 deletions(-)
fs/9p/vfs_file.c +4 -3
@@ -9,6 +9,7 @@#include <linux/module.h> #include <linux/errno.h> #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/sched.h> #include <linux/file.h>
@@ -126,7 +127,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)struct p9_fid *fid;uint8_t status =P9_LOCK_ERROR ;int res =0 ; -unsigned char fl_type; +unsigned char saved_type;struct v9fs_session_info *v9ses; fid = filp->private_data;
@@ -213,11 +214,11 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)* it locally */ if (res <0 && fl->fl_type !=F_UNLCK ) { - fl_type = fl->fl_type; + saved_type = fl->fl_type; fl->fl_type =F_UNLCK ;/* Even if this fails we want to return the remote error */ locks_lock_file_wait (filp, fl); - fl->fl_type = fl_type; + fl->fl_type = saved_type; }if (flock.client_id != fid->clnt->name)kfree (flock.client_id);
fs/afs/flock.c +3 -3
@@ -112,16 +112,16 @@ static void afs_next_locker(struct afs_vnode *vnode, int error) {struct file_lock *p, *_p, *next =NULL ;struct key *key = vnode->lock_key; -unsigned int fl_type =F_RDLCK ; +unsigned int requested_type =F_RDLCK ;_enter ("" );if (vnode->lock_type ==AFS_LOCK_WRITE ) - fl_type =F_WRLCK ; + requested_type =F_WRLCK ;list_for_each_entry_safe (p, _p, &vnode->pending_locks, fl_u.afs.link) {if (error && - p->fl_type == fl_type && + p->fl_type == requested_type &&afs_file_key (p->fl_file) == key) {list_del_init (&p->fl_u.afs.link); p->fl_u.afs.state = error;
fs/afs/internal.h +1 -0
@@ -9,6 +9,7 @@#include <linux/kernel.h> #include <linux/ktime.h> #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/pagemap.h> #include <linux/rxrpc.h>
fs/ceph/locks.c +1 -0
@@ -7,6 +7,7 @@#include "super.h" #include "mds_client.h" +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/ceph/pagelist.h>
fs/dlm/plock.c +3 -2
@@ -4,6 +4,7 @@*/ #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/miscdevice.h> #include <linux/poll.h>
@@ -295,7 +296,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,struct dlm_ls *ls;struct plock_op *op;int rv; -unsigned char fl_flags = fl->fl_flags; +unsigned char saved_flags = fl->fl_flags; ls =dlm_find_lockspace_local (lockspace);if (!ls)
@@ -352,7 +353,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,dlm_release_plock_op (op); out:dlm_put_lockspace (ls); - fl->fl_flags = fl_flags; + fl->fl_flags = saved_flags;return rv; }EXPORT_SYMBOL_GPL (dlm_posix_unlock);
fs/fuse/file.c +1 -0
@@ -18,6 +18,7 @@#include <linux/falloc.h> #include <linux/uio.h> #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> static int fuse_send_open(struct fuse_mount *fm, u64 nodeid,
fs/gfs2/file.c +1 -0
@@ -15,6 +15,7 @@#include <linux/mm.h> #include <linux/mount.h> #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/gfs2_ondisk.h> #include <linux/falloc.h>
fs/lockd/clntproc.c +13 -11
@@ -12,6 +12,7 @@#include <linux/types.h> #include <linux/errno.h> #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/nfs_fs.h> #include <linux/utsname.h>
@@ -485,7 +486,8 @@ static const struct file_lock_operations nlmclnt_lock_ops = {static void nlmclnt_locks_init_private (struct file_lock *fl,struct nlm_host *host) { fl->fl_u.nfs_fl.state =0 ; - fl->fl_u.nfs_fl.owner =nlmclnt_find_lockowner (host, fl->fl_owner); + fl->fl_u.nfs_fl.owner =nlmclnt_find_lockowner (host, + fl->c.flc_owner);INIT_LIST_HEAD (&fl->fl_u.nfs_fl.list); fl->fl_ops = &nlmclnt_lock_ops; }
@@ -522,8 +524,8 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)struct nlm_host *host = req->a_host;struct nlm_res *resp = &req->a_res;struct nlm_wait block; -unsigned char fl_flags = fl->fl_flags; -unsigned char fl_type; +unsigned char saved_flags = fl->fl_flags; +unsigned char saved_type;__be32 b_status;int status = -ENOLCK ;
@@ -533,7 +535,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) fl->fl_flags |=FL_ACCESS ; status =do_vfs_lock (fl); - fl->fl_flags = fl_flags; + fl->fl_flags = saved_flags;if (status <0 ) goto out;
@@ -595,7 +597,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)if (do_vfs_lock (fl) <0 )printk (KERN_WARNING "%s: VFS is out of sync with lock manager!\n" , __func__);up_read (&host->h_rwsem); - fl->fl_flags = fl_flags; + fl->fl_flags = saved_flags; status =0 ; }if (status <0 )
@@ -605,7 +607,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)* cases NLM_LCK_DENIED is returned for a permanent error. So * turn it into an ENOLCK. */ -if (resp->status == nlm_lck_denied && (fl_flags &FL_SLEEP )) +if (resp->status == nlm_lck_denied && (saved_flags &FL_SLEEP )) status = -ENOLCK ;else status =nlm_stat_to_errno (resp->status);
@@ -622,13 +624,13 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) req->a_host->h_addrlen, req->a_res.status);dprintk ("lockd: lock attempt ended in fatal error.\n" " Attempting to unlock.\n" ); - fl_type = fl->fl_type; + saved_type = fl->fl_type; fl->fl_type =F_UNLCK ;down_read (&host->h_rwsem);do_vfs_lock (fl);up_read (&host->h_rwsem); - fl->fl_type = fl_type; - fl->fl_flags = fl_flags; + fl->fl_type = saved_type; + fl->fl_flags = saved_flags;nlmclnt_async_call (cred, req,NLMPROC_UNLOCK , &nlmclnt_unlock_ops);return status; }
@@ -683,7 +685,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)struct nlm_host *host = req->a_host;struct nlm_res *resp = &req->a_res;int status; -unsigned char fl_flags = fl->fl_flags; +unsigned char saved_flags = fl->fl_flags;/* * Note: the server is supposed to either grant us the unlock
@@ -694,7 +696,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)down_read (&host->h_rwsem); status =do_vfs_lock (fl);up_read (&host->h_rwsem); - fl->fl_flags = fl_flags; + fl->fl_flags = saved_flags;if (status == -ENOENT ) { status =0 ; goto out;
fs/locks.c +5 -4
@@ -48,6 +48,7 @@* children. * */ +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/capability.h> #include <linux/file.h>
@@ -2700,11 +2701,11 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, loff_t id, char *pfx, int repeat) { struct inode *inode = NULL; -unsigned int fl_pid; +unsigned int lock_pid;struct pid_namespace *proc_pidns =proc_pid_ns (file_inode (f->file)->i_sb);int type; - fl_pid =locks_translate_pid (fl, proc_pidns); + lock_pid =locks_translate_pid (fl, proc_pidns);/* * If lock owner is dead (and pid is freed) or not visible in current * pidns, zero is shown as a pid value. Check lock info from
@@ -2752,11 +2753,11 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, (type == F_RDLCK) ? "READ" : "UNLCK");if (inode) {/* userspace relies on this representation of dev_t */ -seq_printf (f,"%d %02x:%02x:%lu " , fl_pid, +seq_printf (f,"%d %02x:%02x:%lu " , lock_pid,MAJOR (inode->i_sb->s_dev),MINOR (inode->i_sb->s_dev), inode->i_ino); }else { -seq_printf (f,"%d <none>:0 " , fl_pid); +seq_printf (f,"%d <none>:0 " , lock_pid); }if (IS_POSIX (fl)) {if (fl->fl_end ==OFFSET_MAX )
fs/nfs/file.c +1 -0
@@ -32,6 +32,7 @@#include <linux/compaction.h> #include <linux/uaccess.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include "delegation.h"
fs/nfs/nfs4_fs.h +1 -0
@@ -23,6 +23,7 @@#define NFS4_MAX_LOOP_ON_RECOVER (10)#include <linux/seqlock.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> struct idmap ;
fs/nfs/nfs4proc.c +5 -5
@@ -7074,7 +7074,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *struct rpc_task *task;struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *,gfp_t );int status =0 ; -unsigned char fl_flags = request->fl_flags; +unsigned char saved_flags = request->fl_flags; status =nfs4_set_lock_state (state, request);/* Unlock _before_ we do the RPC call */
@@ -7109,7 +7109,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * status =rpc_wait_for_completion_task (task);rpc_put_task (task); out: - request->fl_flags = fl_flags; + request->fl_flags = saved_flags;trace_nfs4_unlock (request, state,F_SETLK , status);return status; }
@@ -7427,7 +7427,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock {struct nfs_inode *nfsi =NFS_I (state->inode);struct nfs4_state_owner *sp = state->owner; -unsigned char fl_flags = request->fl_flags; +unsigned char saved_flags = request->fl_flags;int status; request->fl_flags |=FL_ACCESS ;
@@ -7439,7 +7439,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lockif (test_bit (NFS_DELEGATED_STATE , &state->flags)) {/* Yes: cache locks! */ /* ...but avoid races with delegation recall... */ - request->fl_flags = fl_flags & ~FL_SLEEP ; + request->fl_flags = saved_flags & ~FL_SLEEP ; status =locks_lock_inode_wait (state->inode, request);up_read (&nfsi->rwsem);mutex_unlock (&sp->so_delegreturn_mutex);
@@ -7449,7 +7449,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lockmutex_unlock (&sp->so_delegreturn_mutex); status =_nfs4_do_setlk (state, cmd, request,NFS_LOCK_NEW ); out: - request->fl_flags = fl_flags; + request->fl_flags = saved_flags;return status; }
fs/nfs/nfs4state.c +7 -7
@@ -847,11 +847,11 @@ void nfs4_close_sync(struct nfs4_state *state, fmode_t fmode)*/ static struct nfs4_lock_state *__nfs4_find_lock_state (struct nfs4_state *state, -fl_owner_t fl_owner,fl_owner_t fl_owner2) +fl_owner_t lock_owner_id,fl_owner_t fl_owner2) {struct nfs4_lock_state *pos, *ret =NULL ;list_for_each_entry (pos, &state->lock_states, ls_locks) { -if (pos->ls_owner == fl_owner) { +if (pos->ls_owner == lock_owner_id) { ret = pos;break ; }
@@ -868,7 +868,7 @@ __nfs4_find_lock_state(struct nfs4_state *state,* exists, return an uninitialized one. * */ -static struct nfs4_lock_state *nfs4_alloc_lock_state (struct nfs4_state *state,fl_owner_t fl_owner) +static struct nfs4_lock_state *nfs4_alloc_lock_state (struct nfs4_state *state,fl_owner_t lock_owner_id) {struct nfs4_lock_state *lsp;struct nfs_server *server = state->owner->so_server;
@@ -879,7 +879,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fnfs4_init_seqid_counter (&lsp->ls_seqid);refcount_set (&lsp->ls_count,1 ); lsp->ls_state = state; - lsp->ls_owner = fl_owner; + lsp->ls_owner = lock_owner_id; lsp->ls_seqid.owner_id =ida_alloc (&server->lockowner_id,GFP_KERNEL_ACCOUNT );if (lsp->ls_seqid.owner_id <0 ) goto out_free;
@@ -993,7 +993,7 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst, const struct nfs_lock_context *l_ctx) {struct nfs4_lock_state *lsp; -fl_owner_t fl_owner, fl_flock_owner; +fl_owner_t lock_owner_id, fl_flock_owner;int ret = -ENOENT ;if (l_ctx ==NULL )
@@ -1002,11 +1002,11 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst,if (test_bit (LK_STATE_IN_USE , &state->flags) ==0 ) goto out; - fl_owner = l_ctx->lockowner; + lock_owner_id = l_ctx->lockowner; fl_flock_owner = l_ctx->open_context->flock_owner;spin_lock (&state->state_lock); - lsp =__nfs4_find_lock_state (state, fl_owner, fl_flock_owner); + lsp =__nfs4_find_lock_state (state, lock_owner_id, fl_flock_owner);if (lsp &&test_bit (NFS_LOCK_LOST , &lsp->ls_flags)) ret = -EIO ;else if (lsp !=NULL &&test_bit (NFS_LOCK_INITIALIZED , &lsp->ls_flags) !=0 ) {
fs/nfs/write.c +1 -0
@@ -25,6 +25,7 @@#include <linux/freezer.h> #include <linux/wait.h> #include <linux/iversion.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/uaccess.h>
fs/nfsd/netns.h +1 -0
@@ -10,6 +10,7 @@#include <net/net_namespace.h> #include <net/netns/generic.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/nfs4.h> #include <linux/percpu_counter.h>
fs/nfsd/nfs4state.c +12 -12
@@ -7580,8 +7580,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,int lkflg;int err;bool new = false; -unsigned char fl_type; -unsigned int fl_flags =FL_POSIX ; +unsigned char lock_type; +unsigned int lock_flags =FL_POSIX ;struct net *net =SVC_NET (rqstp);struct nfsd_net *nn =net_generic (net, nfsd_net_id);
@@ -7643,13 +7643,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out;if (lock->lk_reclaim) - fl_flags |=FL_RECLAIM ; + lock_flags |=FL_RECLAIM ; fp = lock_stp->st_stid.sc_file;switch (lock->lk_type) {case NFS4_READW_LT :if (nfsd4_has_session (cstate)) - fl_flags |=FL_SLEEP ; + lock_flags |=FL_SLEEP ; fallthrough;case NFS4_READ_LT :spin_lock (&fp->fi_lock);
@@ -7657,11 +7657,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,if (nf)get_lock_access (lock_stp,NFS4_SHARE_ACCESS_READ );spin_unlock (&fp->fi_lock); - fl_type =F_RDLCK ; + lock_type =F_RDLCK ;break ;case NFS4_WRITEW_LT :if (nfsd4_has_session (cstate)) - fl_flags |=FL_SLEEP ; + lock_flags |=FL_SLEEP ; fallthrough;case NFS4_WRITE_LT :spin_lock (&fp->fi_lock);
@@ -7669,7 +7669,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,if (nf)get_lock_access (lock_stp,NFS4_SHARE_ACCESS_WRITE );spin_unlock (&fp->fi_lock); - fl_type =F_WRLCK ; + lock_type =F_WRLCK ;break ;default : status = nfserr_inval;
@@ -7689,7 +7689,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,* on those filesystems: */ if (nf->nf_file->f_op->lock) - fl_flags &= ~FL_SLEEP ; + lock_flags &= ~FL_SLEEP ; nbl =find_or_allocate_block (lock_sop, &fp->fi_fhandle, nn);if (!nbl) {
@@ -7699,11 +7699,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, } file_lock = &nbl->nbl_lock; - file_lock->fl_type = fl_type; + file_lock->fl_type = lock_type; file_lock->fl_owner = (fl_owner_t )lockowner (nfs4_get_stateowner (&lock_sop->lo_owner)); file_lock->fl_pid = current->tgid; file_lock->fl_file = nf->nf_file; - file_lock->fl_flags = fl_flags; + file_lock->fl_flags = lock_flags; file_lock->fl_lmops = &nfsd_posix_mng_ops; file_lock->fl_start = lock->lk_offset; file_lock->fl_end =last_byte_offset (lock->lk_offset, lock->lk_length);
@@ -7716,7 +7716,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out; } -if (fl_flags &FL_SLEEP ) { +if (lock_flags &FL_SLEEP ) { nbl->nbl_time =ktime_get_boottime_seconds ();spin_lock (&nn->blocked_locks_lock);list_add_tail (&nbl->nbl_list, &lock_sop->lo_blocked);
@@ -7753,7 +7753,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, out:if (nbl) {/* dequeue it if we queued it before */ -if (fl_flags &FL_SLEEP ) { +if (lock_flags &FL_SLEEP ) {spin_lock (&nn->blocked_locks_lock);if (!list_empty (&nbl->nbl_list) && !list_empty (&nbl->nbl_lru)) {
fs/ocfs2/locks.c +1 -0
@@ -8,6 +8,7 @@*/ #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/fcntl.h>
fs/ocfs2/stack_user.c +1 -0
@@ -9,6 +9,7 @@#include <linux/module.h> #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/miscdevice.h> #include <linux/mutex.h>
fs/smb/client/cifsglob.h +1 -0
@@ -28,6 +28,7 @@#include "../common/cifsglob.h" #include "../common/smb2pdu.h" #include "smb2pdu.h" +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #define SMB_PATH_MAX 260
fs/smb/client/cifssmb.c +1 -0
@@ -15,6 +15,7 @@/* want to reuse a stale file handle and only the caller knows the file info */ #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/kernel.h> #include <linux/vfs.h>
fs/smb/client/file.c +1 -0
@@ -9,6 +9,7 @@* */ #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/backing-dev.h> #include <linux/stat.h>
fs/smb/client/smb2file.c +1 -0
@@ -7,6 +7,7 @@* */ #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/stat.h> #include <linux/slab.h>
fs/smb/server/smb2pdu.c +1 -0
@@ -13,6 +13,7 @@#include <linux/ethtool.h> #include <linux/falloc.h> #include <linux/mount.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include "glob.h"
fs/smb/server/vfs.c +1 -0
@@ -6,6 +6,7 @@#include <linux/kernel.h> #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/uaccess.h> #include <linux/backing-dev.h>
include/linux/filelock.h +34 -13
63 lines not on this page · raw message
include/linux/lockd/xdr.h +1 -0
@@ -11,6 +11,7 @@#define LOCKD_XDR_H #include <linux/fs.h> +#define _NEED_FILE_LOCK_FIELD_MACROS#include <linux/filelock.h> #include <linux/nfs.h> #include <linux/sunrpc/xdr.h>
include/trace/events/filelock.h +33 -33
119 lines not on this page · raw message
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 lockd: fix NULL dereference on lockowner allocation failure
From: Shuangpeng Bai <[email protected]>
[ Upstream commit 4c7fc129db061c7daab841c4f3c342d894832362 ]
nlmclnt_locks_init_private() installs NLM file lock operations even when nlmclnt_find_lockowner() fails to allocate a lockowner. nlmclnt_proc() then returns -ENOMEM, but the VFS still tears down the partially initialized file_lock and calls locks_release_private().
That invokes nlmclnt_locks_release_private(), which dereferences fl->fl_u.nfs_fl.owner and crashes because the owner was never installed.
Clear fl_ops before attempting to initialize the NLM private state, and install the NLM lock operations only after a lockowner has been allocated successfully.
--- fs/lockd/clntproc.c | 3 +++ 1 file changed, 3 insertions(+)
fs/lockd/clntproc.c +3 -0
@@ -486,9 +486,12 @@ static const struct file_lock_operations nlmclnt_lock_ops = {static void nlmclnt_locks_init_private (struct file_lock *fl,struct nlm_host *host) { fl->fl_u.nfs_fl.state =0 ; + fl->fl_ops =NULL ; fl->fl_u.nfs_fl.owner =nlmclnt_find_lockowner (host, fl->c.flc_owner);INIT_LIST_HEAD (&fl->fl_u.nfs_fl.list); +if (!fl->fl_u.nfs_fl.owner) +return ; fl->fl_ops = &nlmclnt_lock_ops; }
Signature · 1 line
2.53.0