* [PATCH 7.0 01/49] io_uring/net: Avoid msghdr on op_connect/op_bind async data
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 02/49] arm64/entry: Fix arm64-specific rseq brokenness Greg Kroah-Hartman
` (51 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Gabriel Krisman Bertazi, Jens Axboe,
Sasha Levin
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <krisman@suse.de>
[ Upstream commit 3979840cd858f30f43ea9f4e7f7f1f56de82d698 ]
This fixes a memory leak due to the lack of the cleanup hook for the
iovec. The stable backport differs from upstream by dropping the
io_connect_bpf_populate hunk, which didn't exist at the time and by
fixing the merge conflict due to the introduction of
io_bind_file_create.
Both IORING_OP_CONNECT and IORING_OP_BIND reuse the msghdr object just
to store the sockaddr. Beyond allocating a much larger object than
needed, msghdr can also wrap an iovec, which will be recycled
unnecessarily. This uses the sockaddr directly.
Cc: stable@vger.kernel.org
Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
Link: https://patch.msgid.link/20260602215327.1885109-2-krisman@suse.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
io_uring/net.c | 36 ++++++++++++++++++------------------
io_uring/opdef.c | 4 ++--
2 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/io_uring/net.c b/io_uring/net.c
index 1329fc9d72fd6f..798bf5dedc2e95 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -1775,7 +1775,7 @@ int io_socket(struct io_kiocb *req, unsigned int issue_flags)
int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
{
struct io_connect *conn = io_kiocb_to_cmd(req, struct io_connect);
- struct io_async_msghdr *io;
+ struct sockaddr_storage *addr;
if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in)
return -EINVAL;
@@ -1784,17 +1784,17 @@ int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
conn->addr_len = READ_ONCE(sqe->addr2);
conn->in_progress = conn->seen_econnaborted = false;
- io = io_msg_alloc_async(req);
- if (unlikely(!io))
+ addr = io_uring_alloc_async_data(NULL, req);
+ if (unlikely(!addr))
return -ENOMEM;
- return move_addr_to_kernel(conn->addr, conn->addr_len, &io->addr);
+ return move_addr_to_kernel(conn->addr, conn->addr_len, addr);
}
int io_connect(struct io_kiocb *req, unsigned int issue_flags)
{
struct io_connect *connect = io_kiocb_to_cmd(req, struct io_connect);
- struct io_async_msghdr *io = req->async_data;
+ struct sockaddr_storage *addr = req->async_data;
unsigned file_flags;
int ret;
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
@@ -1808,8 +1808,7 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
file_flags = force_nonblock ? O_NONBLOCK : 0;
- ret = __sys_connect_file(req->file, &io->addr, connect->addr_len,
- file_flags);
+ ret = __sys_connect_file(req->file, addr, connect->addr_len, file_flags);
if ((ret == -EAGAIN || ret == -EINPROGRESS || ret == -ECONNABORTED)
&& force_nonblock) {
if (ret == -EINPROGRESS) {
@@ -1838,7 +1837,6 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
out:
if (ret < 0)
req_set_fail(req);
- io_req_msg_cleanup(req, issue_flags);
io_req_set_res(req, ret, 0);
return IOU_COMPLETE;
}
@@ -1848,15 +1846,15 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
* which in turn end up in mnt_want_write() which will grab the fs
* percpu start write sem. This can trigger a lockdep warning.
*/
-static int io_bind_file_create(const struct io_async_msghdr *io, int addr_len)
+static int io_bind_file_create(const struct sockaddr_storage *addr, int addr_len)
{
const struct sockaddr_un *sun;
- if (io->addr.ss_family != AF_UNIX)
+ if (addr->ss_family != AF_UNIX)
return 0;
if (addr_len <= offsetof(struct sockaddr_un, sun_path))
return 0;
- sun = (const struct sockaddr_un *) &io->addr;
+ sun = (const struct sockaddr_un *) addr;
return sun->sun_path[0] != '\0';
}
@@ -1864,7 +1862,7 @@ int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
{
struct io_bind *bind = io_kiocb_to_cmd(req, struct io_bind);
struct sockaddr __user *uaddr;
- struct io_async_msghdr *io;
+ struct sockaddr_storage *addr;
int ret;
if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in)
@@ -1873,21 +1871,23 @@ int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
uaddr = u64_to_user_ptr(READ_ONCE(sqe->addr));
bind->addr_len = READ_ONCE(sqe->addr2);
- io = io_msg_alloc_async(req);
- if (unlikely(!io))
+ addr = io_uring_alloc_async_data(NULL, req);
+ if (unlikely(!addr))
return -ENOMEM;
- ret = move_addr_to_kernel(uaddr, bind->addr_len, &io->addr);
+
+ ret = move_addr_to_kernel(uaddr, bind->addr_len, addr);
if (unlikely(ret))
return ret;
- if (io_bind_file_create(io, bind->addr_len))
+ if (io_bind_file_create(addr, bind->addr_len))
req->flags |= REQ_F_FORCE_ASYNC;
return 0;
}
+
int io_bind(struct io_kiocb *req, unsigned int issue_flags)
{
struct io_bind *bind = io_kiocb_to_cmd(req, struct io_bind);
- struct io_async_msghdr *io = req->async_data;
+ struct sockaddr_storage *addr = req->async_data;
struct socket *sock;
int ret;
@@ -1895,7 +1895,7 @@ int io_bind(struct io_kiocb *req, unsigned int issue_flags)
if (unlikely(!sock))
return -ENOTSOCK;
- ret = __sys_bind_socket(sock, &io->addr, bind->addr_len);
+ ret = __sys_bind_socket(sock, addr, bind->addr_len);
if (ret < 0)
req_set_fail(req);
io_req_set_res(req, ret, 0);
diff --git a/io_uring/opdef.c b/io_uring/opdef.c
index 91a23baf415e89..2e1752df8748b4 100644
--- a/io_uring/opdef.c
+++ b/io_uring/opdef.c
@@ -207,7 +207,7 @@ const struct io_issue_def io_issue_defs[] = {
.unbound_nonreg_file = 1,
.pollout = 1,
#if defined(CONFIG_NET)
- .async_size = sizeof(struct io_async_msghdr),
+ .async_size = sizeof(struct sockaddr_storage),
.prep = io_connect_prep,
.issue = io_connect,
#else
@@ -510,7 +510,7 @@ const struct io_issue_def io_issue_defs[] = {
.needs_file = 1,
.prep = io_bind_prep,
.issue = io_bind,
- .async_size = sizeof(struct io_async_msghdr),
+ .async_size = sizeof(struct sockaddr_storage),
#else
.prep = io_eopnotsupp_prep,
#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH 7.0 02/49] arm64/entry: Fix arm64-specific rseq brokenness
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 01/49] io_uring/net: Avoid msghdr on op_connect/op_bind async data Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 03/49] lockd: fix TEST handling when not all permissions are available Greg Kroah-Hartman
` (50 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Mathias Stearn, Mark Rutland,
Peter Zijlstra (Intel), Catalin Marinas, Sasha Levin
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Rutland <mark.rutland@arm.com>
commit 411c1cf430392c905e39f12bc305dd994da0b426 upstream.
Mathias Stearn reports that since v6.19, there are two big issues
affecting rseq:
(1) On arm64 specifically, rseq critical sections aren't aborted when
they should be.
(2) The 'cpu_id_start' field is no longer written by the kernel in all
cases it used to be, including some cases where TCMalloc depends on
the kernel clobbering the field.
This patch fixes issue #1. This patch DOES NOT fix issue #2, which will
need to be addressed by other patches.
The arm64-specific brokenness is a result of commits:
2fc0e4b4126c ("rseq: Record interrupt from user space")
39a167560a61 ("rseq: Optimize event setting")
The first commit failed to add a call to rseq_note_user_irq_entry() on
arm64. Thus arm64 never sets rseq_event::user_irq to record that it may
be necessary to abort an active rseq critical section upon return to
userspace. On its own, this commit had no functional impact as the value
of rseq_event::user_irq was not consumed.
The second commit relied upon rseq_event::user_irq to determine whether
or not to bother to perform rseq work when returning to userspace. As
rseq_event::user_irq wasn't set on arm64, this work would be skipped,
and consequently an active rseq critical section would not be aborted.
Fix this by giving arm64 syscall-specific entry/exit paths, and
performing the relevant logic in syscall and non-syscall paths,
including calling rseq_note_user_irq_entry() for non-syscall entry.
Currently arm64 cannot use syscall_enter_from_user_mode(),
syscall_exit_to_user_mode(), and irqentry_exit_to_user_mode(), due to
ordering constraints with exception masking, and risk of ABI breakage
for syscall tracing/audit/etc. For the moment the entry/exit logic is
left as arm64-specific, directly using enter_from_user_mode() and
exit_to_user_mode(), but mirroring the generic code.
I intend to follow up with refactoring/cleanup, as we did for kernel
mode entry paths in commit:
041aa7a85390 ("entry: Split preemption from irqentry_exit_to_kernel_mode()")
... which will allow arm64 to use the GENERIC_IRQ_ENTRY functions directly.
Fixes: 39a167560a61 ("rseq: Optimize event setting")
Reported-by: Mathias Stearn <mathias@mongodb.com>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/regressions/CAHnCjA25b+nO2n5CeifknSKHssJpPrjnf+dtr7UgzRw4Zgu=oA@mail.gmail.com/
Link: https://patch.msgid.link/20260508142023.3268622-1-mark.rutland@arm.com
[Mark: fix conflicts in entry-common.c & irq-entry-common.h]
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/arm64/kernel/entry-common.c | 29 ++++++++++++++++++++++-------
include/linux/irq-entry-common.h | 8 --------
include/linux/rseq_entry.h | 19 -------------------
3 files changed, 22 insertions(+), 34 deletions(-)
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 3625797e9ee8f9..e3614cedaf23e7 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -58,6 +58,12 @@ static void noinstr exit_to_kernel_mode(struct pt_regs *regs,
irqentry_exit(regs, state);
}
+static __always_inline void arm64_syscall_enter_from_user_mode(struct pt_regs *regs)
+{
+ enter_from_user_mode(regs);
+ mte_disable_tco_entry(current);
+}
+
/*
* Handle IRQ/context state management when entering from user mode.
* Before this function is called it is not safe to call regular kernel code,
@@ -66,19 +72,28 @@ static void noinstr exit_to_kernel_mode(struct pt_regs *regs,
static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs)
{
enter_from_user_mode(regs);
+ rseq_note_user_irq_entry();
mte_disable_tco_entry(current);
}
+static __always_inline void arm64_syscall_exit_to_user_mode(struct pt_regs *regs)
+{
+ local_irq_disable();
+ syscall_exit_to_user_mode_prepare(regs);
+ local_daif_mask();
+ mte_check_tfsr_exit();
+ exit_to_user_mode();
+}
+
/*
* Handle IRQ/context state management when exiting to user mode.
* After this function returns it is not safe to call regular kernel code,
* instrumentable code, or any code which may trigger an exception.
*/
-
static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
{
local_irq_disable();
- exit_to_user_mode_prepare_legacy(regs);
+ irqentry_exit_to_user_mode_prepare(regs);
local_daif_mask();
mte_check_tfsr_exit();
exit_to_user_mode();
@@ -86,7 +101,7 @@ static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs)
{
- arm64_exit_to_user_mode(regs);
+ arm64_syscall_exit_to_user_mode(regs);
}
/*
@@ -717,12 +732,12 @@ static void noinstr el0_brk64(struct pt_regs *regs, unsigned long esr)
static void noinstr el0_svc(struct pt_regs *regs)
{
- arm64_enter_from_user_mode(regs);
+ arm64_syscall_enter_from_user_mode(regs);
cortex_a76_erratum_1463225_svc_handler();
fpsimd_syscall_enter();
local_daif_restore(DAIF_PROCCTX);
do_el0_svc(regs);
- arm64_exit_to_user_mode(regs);
+ arm64_syscall_exit_to_user_mode(regs);
fpsimd_syscall_exit();
}
@@ -869,11 +884,11 @@ static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr)
static void noinstr el0_svc_compat(struct pt_regs *regs)
{
- arm64_enter_from_user_mode(regs);
+ arm64_syscall_enter_from_user_mode(regs);
cortex_a76_erratum_1463225_svc_handler();
local_daif_restore(DAIF_PROCCTX);
do_el0_svc_compat(regs);
- arm64_exit_to_user_mode(regs);
+ arm64_syscall_exit_to_user_mode(regs);
}
static void noinstr el0_bkpt32(struct pt_regs *regs, unsigned long esr)
diff --git a/include/linux/irq-entry-common.h b/include/linux/irq-entry-common.h
index d26d1b1bcbfb97..6519b4a30dc1dd 100644
--- a/include/linux/irq-entry-common.h
+++ b/include/linux/irq-entry-common.h
@@ -236,14 +236,6 @@ static __always_inline void __exit_to_user_mode_validate(void)
lockdep_sys_exit();
}
-/* Temporary workaround to keep ARM64 alive */
-static __always_inline void exit_to_user_mode_prepare_legacy(struct pt_regs *regs)
-{
- __exit_to_user_mode_prepare(regs);
- rseq_exit_to_user_mode_legacy();
- __exit_to_user_mode_validate();
-}
-
/**
* syscall_exit_to_user_mode_prepare - call exit_to_user_mode_loop() if required
* @regs: Pointer to pt_regs on entry stack
diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
index 69bdb93951b904..bbe190269f79aa 100644
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -740,24 +740,6 @@ static __always_inline void rseq_irqentry_exit_to_user_mode(void)
ev->events = 0;
}
-/* Required to keep ARM64 working */
-static __always_inline void rseq_exit_to_user_mode_legacy(void)
-{
- struct rseq_event *ev = ¤t->rseq.event;
-
- rseq_stat_inc(rseq_stats.exit);
-
- if (static_branch_unlikely(&rseq_debug_enabled))
- WARN_ON_ONCE(ev->sched_switch);
-
- /*
- * Ensure that event (especially user_irq) is cleared when the
- * interrupt did not result in a schedule and therefore the
- * rseq processing did not clear it.
- */
- ev->events = 0;
-}
-
void __rseq_debug_syscall_return(struct pt_regs *regs);
static __always_inline void rseq_debug_syscall_return(struct pt_regs *regs)
@@ -773,7 +755,6 @@ static inline bool rseq_exit_to_user_mode_restart(struct pt_regs *regs, unsigned
}
static inline void rseq_syscall_exit_to_user_mode(void) { }
static inline void rseq_irqentry_exit_to_user_mode(void) { }
-static inline void rseq_exit_to_user_mode_legacy(void) { }
static inline void rseq_debug_syscall_return(struct pt_regs *regs) { }
static inline bool rseq_grant_slice_extension(bool work_pending) { return false; }
#endif /* !CONFIG_RSEQ */
--
2.53.0
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH 7.0 03/49] lockd: fix TEST handling when not all permissions are available.
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 01/49] io_uring/net: Avoid msghdr on op_connect/op_bind async data Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 02/49] arm64/entry: Fix arm64-specific rseq brokenness Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 04/49] firmware: exynos-acpm: Count number of commands in acpm_xfer Greg Kroah-Hartman
` (49 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tj, Jeff Layton, NeilBrown,
Chuck Lever, Sasha Levin
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <neil@brown.name>
[ Upstream commit 0b474240327cebeff08ad429e8ed3cfc6c8ee816 ]
The F_GETLK fcntl can work with either read access or write access or
both. It can query F_RDLCK and F_WRLCK locks in either case.
However lockd currently treats F_GETLK similar to F_SETLK in that read
access is required to query an F_RDLCK lock and write access is required
to query a F_WRLCK lock.
This is wrong and can cause problems - e.g. when qemu accesses a
read-only (e.g. iso) filesystem image over NFS (though why it queries
if it can get a write lock - I don't know. But it does, and this works
with local filesystems).
So we need TEST requests to be handled differently. To do this:
- change nlm_do_fopen() to accept O_RDWR as a mode and in that case
succeed if either a O_RDONLY or O_WRONLY file can be opened.
- change nlm_lookup_file() to accept a mode argument from caller,
instead of deducing base on lock time, and pass that on to nlm_do_fopen()
- change nlm4svc_retrieve_args() and nlmsvc_retrieve_args() to detect
TEST requests and pass O_RDWR as a mode to nlm_lookup_file, passing
the same mode as before for other requests. Also set
lock->fl.c.flc_file to whichever file is available for TEST requests.
- change nlmsvc_testlock() to also not calculate the mode, but to use
whatever was stored in lock->fl.c.flc_file.
This behaviour of lockd - requesting O_WRONLY access to TEST for
exclusive locks - has been present at least since git history began.
However it was hidden until recently because knfsd ignored the access
requested by lockd and required only READ access for all locking
requests (unless the underlying filesystem provided an f_op->open
function which checked access permissions).
The commit mentioned in Fixes: below changed nfsd_permission() to NOT
override the access request for LOCK requests and this exposed the bug
that we are now fixing.
Note that there is another issue that this patch does not address.
The flock(.., LOCK_EX) call is permitted on a read-only file descriptor.
Linux NFS maps this to NLM locking as whole-file byte-range locks.
nfsd will see this as though it were fcntl( F_SETLK (F_WRLCK)) and will
now require write access, which it might not be able to get.
It is not clear if this is a problem in practice, or what the best
solution might be. So no attempt is made to address it.
Reported-by: Tj <tj.iam.tj@proton.me>
Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1128861
Fixes: 4cc9b9f2bf4d ("nfsd: refine and rename NFSD_MAY_LOCK")
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: NeilBrown <neil@brown.name>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/lockd/svc4proc.c | 13 ++++++++++---
fs/lockd/svclock.c | 4 +---
fs/lockd/svcproc.c | 15 ++++++++++++---
fs/lockd/svcsubs.c | 35 +++++++++++++++++++++++++----------
include/linux/lockd/lockd.h | 2 +-
5 files changed, 49 insertions(+), 20 deletions(-)
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 4b6f18d977343d..75e020a8bfd072 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -26,6 +26,8 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
struct nlm_host *host = NULL;
struct nlm_file *file = NULL;
struct nlm_lock *lock = &argp->lock;
+ bool is_test = (rqstp->rq_proc == NLMPROC_TEST ||
+ rqstp->rq_proc == NLMPROC_TEST_MSG);
__be32 error = 0;
/* nfsd callbacks must have been installed for this procedure */
@@ -46,15 +48,20 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
if (filp != NULL) {
int mode = lock_to_openmode(&lock->fl);
+ if (is_test)
+ mode = O_RDWR;
+
lock->fl.c.flc_flags = FL_POSIX;
- error = nlm_lookup_file(rqstp, &file, lock);
+ error = nlm_lookup_file(rqstp, &file, lock, mode);
if (error)
goto no_locks;
*filp = file;
-
/* Set up the missing parts of the file_lock structure */
- lock->fl.c.flc_file = file->f_file[mode];
+ if (is_test)
+ lock->fl.c.flc_file = nlmsvc_file_file(file);
+ else
+ lock->fl.c.flc_file = file->f_file[mode];
lock->fl.c.flc_pid = current->tgid;
lock->fl.fl_start = (loff_t)lock->lock_start;
lock->fl.fl_end = lock->lock_len ?
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index abc65dc79f8543..382bf0d93ed1c1 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -619,7 +619,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
struct nlm_lock *conflock)
{
int error;
- int mode;
__be32 ret;
dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
@@ -637,14 +636,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
goto out;
}
- mode = lock_to_openmode(&lock->fl);
locks_init_lock(&conflock->fl);
/* vfs_test_lock only uses start, end, and owner, but tests flc_file */
conflock->fl.c.flc_file = lock->fl.c.flc_file;
conflock->fl.fl_start = lock->fl.fl_start;
conflock->fl.fl_end = lock->fl.fl_end;
conflock->fl.c.flc_owner = lock->fl.c.flc_owner;
- error = vfs_test_lock(file->f_file[mode], &conflock->fl);
+ error = vfs_test_lock(lock->fl.c.flc_file, &conflock->fl);
if (error) {
ret = nlm_lck_denied_nolocks;
goto out;
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 5817ef272332d9..d98e8d684376b7 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -55,6 +55,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
struct nlm_host *host = NULL;
struct nlm_file *file = NULL;
struct nlm_lock *lock = &argp->lock;
+ bool is_test = (rqstp->rq_proc == NLMPROC_TEST ||
+ rqstp->rq_proc == NLMPROC_TEST_MSG);
int mode;
__be32 error = 0;
@@ -70,15 +72,22 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
/* Obtain file pointer. Not used by FREE_ALL call. */
if (filp != NULL) {
- error = cast_status(nlm_lookup_file(rqstp, &file, lock));
+ mode = lock_to_openmode(&lock->fl);
+
+ if (is_test)
+ mode = O_RDWR;
+
+ error = cast_status(nlm_lookup_file(rqstp, &file, lock, mode));
if (error != 0)
goto no_locks;
*filp = file;
/* Set up the missing parts of the file_lock structure */
- mode = lock_to_openmode(&lock->fl);
lock->fl.c.flc_flags = FL_POSIX;
- lock->fl.c.flc_file = file->f_file[mode];
+ if (is_test)
+ lock->fl.c.flc_file = nlmsvc_file_file(file);
+ else
+ lock->fl.c.flc_file = file->f_file[mode];
lock->fl.c.flc_pid = current->tgid;
lock->fl.fl_lmops = &nlmsvc_lock_operations;
nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid);
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index dd0214dcb69503..b83e6ecd5be34f 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -82,18 +82,35 @@ int lock_to_openmode(struct file_lock *lock)
*
* We have to make sure we have the right credential to open
* the file.
+ *
+ * mode can be O_RDONLY(0), O_WRONLY(1) or O_RDWR(2). The latter
+ * means success can be achieved with EITHER O_RDONLY or O_WRONLY.
+ * It does NOT mean both read and write are required.
*/
static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
struct nlm_file *file, int mode)
{
- struct file **fp = &file->f_file[mode];
- __be32 nfserr;
+ __be32 nfserr = nlm_lck_denied_nolocks;
+ __be32 deferred = 0;
+ struct file **fp;
+ int m;
- if (*fp)
- return 0;
- nfserr = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode);
- if (nfserr)
- dprintk("lockd: open failed (error %d)\n", nfserr);
+ for (m = O_RDONLY ; m <= O_WRONLY ; m++) {
+ if (mode != O_RDWR && mode != m)
+ continue;
+
+ fp = &file->f_file[m];
+ if (*fp)
+ return 0;
+ nfserr = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, m);
+ if (!nfserr)
+ return 0;
+ if (nfserr == nlm_drop_reply)
+ deferred = nfserr;
+ }
+ if (deferred)
+ return deferred;
+ dprintk("lockd: open failed (error %d)\n", ntohl(nfserr));
return nfserr;
}
@@ -103,17 +120,15 @@ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
*/
__be32
nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
- struct nlm_lock *lock)
+ struct nlm_lock *lock, int mode)
{
struct nlm_file *file;
unsigned int hash;
__be32 nfserr;
- int mode;
nlm_debug_print_fh("nlm_lookup_file", &lock->fh);
hash = file_hash(&lock->fh);
- mode = lock_to_openmode(&lock->fl);
/* Lock file table */
mutex_lock(&nlm_file_mutex);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 330e38776bb20d..fe5cdd4d66f484 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -294,7 +294,7 @@ void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);
* File handling for the server personality
*/
__be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
- struct nlm_lock *);
+ struct nlm_lock *, int);
void nlm_release_file(struct nlm_file *);
void nlmsvc_put_lockowner(struct nlm_lockowner *);
void nlmsvc_release_lockowner(struct nlm_lock *);
--
2.53.0
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH 7.0 04/49] firmware: exynos-acpm: Count number of commands in acpm_xfer
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (2 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 03/49] lockd: fix TEST handling when not all permissions are available Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 05/49] firmware: exynos-acpm: Count acpm_xfer buffers with __counted_by_ptr Greg Kroah-Hartman
` (48 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Krzysztof Kozlowski, Tudor Ambarus,
Krzysztof Kozlowski, Sasha Levin
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
[ Upstream commit 00808ae2e679a97dccc5cf0ee4474ba1e2e8a21a ]
Struct acpm_xfer holds two buffers with u32 commands - rxd and txd - and
counts their size by rxlen and txlen. "len" suffix is here ambiguous,
so could mean length of the buffer or length of commands, and these are
not the same since each command is u32. Rename these to rxcnt and
txcnt, and change their usage to count the number of commands in each
buffer.
This will have a benefit of allowing to use __counted_by_ptr later.
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Link: https://patch.msgid.link/20260219-firmare-acpm-counted-v2-2-e1f7389237d3@oss.qualcomm.com
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Stable-dep-of: f133bd4b5daf ("firmware: samsung: acpm: Fix cross-thread RX length corruption")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/firmware/samsung/exynos-acpm-dvfs.c | 9 +++++----
drivers/firmware/samsung/exynos-acpm-pmic.c | 14 +++++++-------
drivers/firmware/samsung/exynos-acpm.c | 14 +++++++-------
drivers/firmware/samsung/exynos-acpm.h | 4 ++--
4 files changed, 21 insertions(+), 20 deletions(-)
--- a/drivers/firmware/samsung/exynos-acpm-dvfs.c
+++ b/drivers/firmware/samsung/exynos-acpm-dvfs.c
@@ -5,6 +5,7 @@
* Copyright 2025 Linaro Ltd.
*/
+#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
#include <linux/ktime.h>
@@ -25,11 +26,11 @@ static void acpm_dvfs_set_xfer(struct ac
{
xfer->acpm_chan_id = acpm_chan_id;
xfer->txd = cmd;
- xfer->txlen = cmdlen;
+ xfer->txcnt = cmdlen;
if (response) {
xfer->rxd = cmd;
- xfer->rxlen = cmdlen;
+ xfer->rxcnt = cmdlen;
}
}
@@ -50,7 +51,7 @@ int acpm_dvfs_set_rate(struct acpm_handl
u32 cmd[4];
acpm_dvfs_init_set_rate_cmd(cmd, clk_id, rate);
- acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, false);
+ acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, false);
return acpm_do_xfer(handle, &xfer);
}
@@ -70,7 +71,7 @@ unsigned long acpm_dvfs_get_rate(struct
int ret;
acpm_dvfs_init_get_rate_cmd(cmd, clk_id);
- acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, true);
+ acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, true);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
--- a/drivers/firmware/samsung/exynos-acpm-pmic.c
+++ b/drivers/firmware/samsung/exynos-acpm-pmic.c
@@ -63,8 +63,8 @@ static void acpm_pmic_set_xfer(struct ac
{
xfer->txd = cmd;
xfer->rxd = cmd;
- xfer->txlen = cmdlen;
- xfer->rxlen = cmdlen;
+ xfer->txcnt = cmdlen;
+ xfer->rxcnt = cmdlen;
xfer->acpm_chan_id = acpm_chan_id;
}
@@ -86,7 +86,7 @@ int acpm_pmic_read_reg(struct acpm_handl
int ret;
acpm_pmic_init_read_cmd(cmd, type, reg, chan);
- acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
+ acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -119,7 +119,7 @@ int acpm_pmic_bulk_read(struct acpm_hand
return -EINVAL;
acpm_pmic_init_bulk_read_cmd(cmd, type, reg, chan, count);
- acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
+ acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -159,7 +159,7 @@ int acpm_pmic_write_reg(struct acpm_hand
int ret;
acpm_pmic_init_write_cmd(cmd, type, reg, chan, value);
- acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
+ acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -199,7 +199,7 @@ int acpm_pmic_bulk_write(struct acpm_han
return -EINVAL;
acpm_pmic_init_bulk_write_cmd(cmd, type, reg, chan, count, buf);
- acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
+ acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -229,7 +229,7 @@ int acpm_pmic_update_reg(struct acpm_han
int ret;
acpm_pmic_init_update_cmd(cmd, type, reg, chan, value, mask);
- acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
+ acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -205,7 +205,7 @@ static void acpm_get_saved_rx(struct acp
rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
if (rx_seqnum == tx_seqnum) {
- memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen);
+ memcpy(xfer->rxd, rx_data->cmd, xfer->rxcnt * sizeof(*xfer->rxd));
clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
}
}
@@ -258,8 +258,7 @@ static int acpm_get_rx(struct acpm_chan
if (rx_data->response) {
if (rx_seqnum == tx_seqnum) {
- __ioread32_copy(xfer->rxd, addr,
- xfer->rxlen / 4);
+ __ioread32_copy(xfer->rxd, addr, xfer->rxcnt);
rx_set = true;
clear_bit(seqnum, achan->bitmap_seqnum);
} else {
@@ -269,8 +268,7 @@ static int acpm_get_rx(struct acpm_chan
* clear yet the bitmap. It will be cleared
* after the response is copied to the request.
*/
- __ioread32_copy(rx_data->cmd, addr,
- xfer->rxlen / 4);
+ __ioread32_copy(rx_data->cmd, addr, xfer->rxcnt);
}
} else {
clear_bit(seqnum, achan->bitmap_seqnum);
@@ -425,7 +423,9 @@ int acpm_do_xfer(struct acpm_handle *han
achan = &acpm->chans[xfer->acpm_chan_id];
- if (!xfer->txd || xfer->txlen > achan->mlen || xfer->rxlen > achan->mlen)
+ if (!xfer->txd ||
+ (xfer->txcnt * sizeof(*xfer->txd) > achan->mlen) ||
+ (xfer->rxcnt * sizeof(*xfer->rxd) > achan->mlen))
return -EINVAL;
if (!achan->poll_completion) {
@@ -448,7 +448,7 @@ int acpm_do_xfer(struct acpm_handle *han
/* Write TX command. */
__iowrite32_copy(achan->tx.base + achan->mlen * tx_front,
- xfer->txd, xfer->txlen / 4);
+ xfer->txd, xfer->txcnt);
/* Advance TX front. */
writel(idx, achan->tx.front);
--- a/drivers/firmware/samsung/exynos-acpm.h
+++ b/drivers/firmware/samsung/exynos-acpm.h
@@ -10,8 +10,8 @@
struct acpm_xfer {
const u32 *txd;
u32 *rxd;
- size_t txlen;
- size_t rxlen;
+ size_t txcnt;
+ size_t rxcnt;
unsigned int acpm_chan_id;
};
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 05/49] firmware: exynos-acpm: Count acpm_xfer buffers with __counted_by_ptr
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (3 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 04/49] firmware: exynos-acpm: Count number of commands in acpm_xfer Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 06/49] firmware: samsung: acpm: Fix cross-thread RX length corruption Greg Kroah-Hartman
` (47 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tudor Ambarus, Krzysztof Kozlowski,
Krzysztof Kozlowski, Sasha Levin
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
[ Upstream commit 951b8eee0581bbf39e7b0464d679eee8cb9da3e0 ]
Use __counted_by_ptr() attribute on the acpm_xfer buffers so UBSAN will
validate runtime that we do not pass over the buffer size, thus making
code safer.
Usage of __counted_by_ptr() (or actually __counted_by()) requires that
counter is initialized before counted array.
Tested-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Link: https://patch.msgid.link/20260219-firmare-acpm-counted-v2-3-e1f7389237d3@oss.qualcomm.com
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Stable-dep-of: f133bd4b5daf ("firmware: samsung: acpm: Fix cross-thread RX length corruption")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/firmware/samsung/exynos-acpm-dvfs.c | 4 ++--
drivers/firmware/samsung/exynos-acpm.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/firmware/samsung/exynos-acpm-dvfs.c
+++ b/drivers/firmware/samsung/exynos-acpm-dvfs.c
@@ -25,12 +25,12 @@ static void acpm_dvfs_set_xfer(struct ac
unsigned int acpm_chan_id, bool response)
{
xfer->acpm_chan_id = acpm_chan_id;
- xfer->txd = cmd;
xfer->txcnt = cmdlen;
+ xfer->txd = cmd;
if (response) {
- xfer->rxd = cmd;
xfer->rxcnt = cmdlen;
+ xfer->rxd = cmd;
}
}
--- a/drivers/firmware/samsung/exynos-acpm.h
+++ b/drivers/firmware/samsung/exynos-acpm.h
@@ -8,8 +8,8 @@
#define __EXYNOS_ACPM_H__
struct acpm_xfer {
- const u32 *txd;
- u32 *rxd;
+ const u32 *txd __counted_by_ptr(txcnt);
+ u32 *rxd __counted_by_ptr(rxcnt);
size_t txcnt;
size_t rxcnt;
unsigned int acpm_chan_id;
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 06/49] firmware: samsung: acpm: Fix cross-thread RX length corruption
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (4 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 05/49] firmware: exynos-acpm: Count acpm_xfer buffers with __counted_by_ptr Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 07/49] firmware: samsung: acpm: Fix false timeouts and Use-After-Free in polling Greg Kroah-Hartman
` (46 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Titouan Ameline de Cadeville,
Tudor Ambarus, Krzysztof Kozlowski, Sasha Levin
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tudor Ambarus <tudor.ambarus@linaro.org>
[ Upstream commit f133bd4b5daf71bccdde0ad1a4f47fac76a6bfb1 ]
Sashiko identified a cross-thread RX length corruption bug when
reviewing the thermal addition to ACPM [1].
When multiple threads concurrently send IPC requests, the ACPM polling
mechanism can encounter responses belonging to other threads. To drain
the queue, the driver saves these concurrent responses into an internal
cache (`rx_data->cmd`) to be retrieved later by the owning thread.
Previously, the driver incorrectly used `xfer->rxcnt` (the expected
receive length of the *current* polling thread) when copying data for
*other* threads into this cache. If the threads expected responses of
different lengths, this resulted in buffer underflows (leading to reads
of uninitialized memory) or potential buffer overflows.
Fix this by replacing the boolean `response` flag in
`struct acpm_rx_data` with `rxcnt`, caching the exact expected receive
length for each specific transaction during transfer preparation. Use
this cached length when saving concurrent responses.
Consequently, ensure that `xfer->rxcnt` is explicitly zeroed in driver
helpers (e.g., `acpm_dvfs_set_xfer`) for fire-and-forget messages to
prevent uninitialized stack garbage from being interpreted as a massive
expected receive length.
Cc: stable@vger.kernel.org
Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Closes: https://sashiko.dev/#/patchset/20260420-acpm-tmu-v3-0-3dc8e93f0b26%40linaro.org [1]
Reported-by: Titouan Ameline de Cadeville <titouan.ameline@gmail.com>
Closes: https://lore.kernel.org/r/20260426210255.73674-1-titouan.ameline@gmail.com/
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Link: https://patch.msgid.link/20260505-acpm-fixes-sashiko-reports-v5-1-43b5ee7f1674@linaro.org
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/firmware/samsung/exynos-acpm-dvfs.c | 3 +++
drivers/firmware/samsung/exynos-acpm.c | 15 ++++++++-------
2 files changed, 11 insertions(+), 7 deletions(-)
--- a/drivers/firmware/samsung/exynos-acpm-dvfs.c
+++ b/drivers/firmware/samsung/exynos-acpm-dvfs.c
@@ -31,6 +31,9 @@ static void acpm_dvfs_set_xfer(struct ac
if (response) {
xfer->rxcnt = cmdlen;
xfer->rxd = cmd;
+ } else {
+ xfer->rxcnt = 0;
+ xfer->rxd = NULL;
}
}
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -104,12 +104,12 @@ struct acpm_queue {
*
* @cmd: pointer to where the data shall be saved.
* @n_cmd: number of 32-bit commands.
- * @response: true if the client expects the RX data.
+ * @rxcnt: expected length of the response in 32-bit words.
*/
struct acpm_rx_data {
u32 *cmd;
size_t n_cmd;
- bool response;
+ size_t rxcnt;
};
#define ACPM_SEQNUM_MAX 64
@@ -199,7 +199,7 @@ static void acpm_get_saved_rx(struct acp
const struct acpm_rx_data *rx_data = &achan->rx_data[tx_seqnum - 1];
u32 rx_seqnum;
- if (!rx_data->response)
+ if (!rx_data->rxcnt)
return;
rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
@@ -256,7 +256,7 @@ static int acpm_get_rx(struct acpm_chan
seqnum = rx_seqnum - 1;
rx_data = &achan->rx_data[seqnum];
- if (rx_data->response) {
+ if (rx_data->rxcnt) {
if (rx_seqnum == tx_seqnum) {
__ioread32_copy(xfer->rxd, addr, xfer->rxcnt);
rx_set = true;
@@ -268,7 +268,8 @@ static int acpm_get_rx(struct acpm_chan
* clear yet the bitmap. It will be cleared
* after the response is copied to the request.
*/
- __ioread32_copy(rx_data->cmd, addr, xfer->rxcnt);
+ __ioread32_copy(rx_data->cmd, addr,
+ rx_data->rxcnt);
}
} else {
clear_bit(seqnum, achan->bitmap_seqnum);
@@ -380,8 +381,8 @@ static void acpm_prepare_xfer(struct acp
/* Clear data for upcoming responses */
rx_data = &achan->rx_data[achan->seqnum - 1];
memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd);
- if (xfer->rxd)
- rx_data->response = true;
+ /* zero means no response expected */
+ rx_data->rxcnt = xfer->rxcnt;
/* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
set_bit(achan->seqnum - 1, achan->bitmap_seqnum);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 07/49] firmware: samsung: acpm: Fix false timeouts and Use-After-Free in polling
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (5 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 06/49] firmware: samsung: acpm: Fix cross-thread RX length corruption Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 08/49] firmware: samsung: acpm: Fix missing LKMM barriers in sequence allocator Greg Kroah-Hartman
` (45 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tudor Ambarus, Krzysztof Kozlowski,
Sasha Levin
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tudor Ambarus <tudor.ambarus@linaro.org>
[ Upstream commit c889b146478885344a220dd468e5a08de088cbc5 ]
Sashiko identified severe races in the polling state machine [1].
In the ACPM driver's polling mode, threads waited for responses by
monitoring the globally shared 'bitmap_seqnum'. This caused false
timeouts because if a thread processed its response and freed the
sequence number, a concurrent TX thread could immediately reallocate
it before the polling thread woke up.
Additionally, the driver suffered from a cross-thread Use-After-Free
(UAF) preemption race. Previously, acpm_get_rx() cleared the sequence
number of whichever RX message it drained from the hardware queue. This
meant Thread A could globally free Thread B's sequence slot while
Thread B was asleep. A new Thread C could then steal the slot,
overwrite the buffer, and leave Thread B to wake up to corrupted state
or a timeout.
Fix this by rewriting the polling state machine:
1. Decouple polling from the global allocator by introducing a per-slot
'completed' flag, synchronized via smp_store_release() and
smp_load_acquire().
2. Strip acpm_get_saved_rx() out of acpm_get_rx() to make it a pure
queue-draining function. Introduce a 'native_match' boolean argument
which evaluates to true only if the thread natively processed its
own sequence number during the call. This explicitly informs the
polling loop whether it must retrieve its payload from the
cross-thread cache.
3. Centralize the cache fallback and sequence number free (clear_bit)
inside the polling loop. Crucially, the free operation now strictly
targets the thread's own TX sequence number (xfer->txd[0]), rather
than the drained RX sequence number. This enforces strict ownership:
a thread only ever frees its own allocated sequence slot, and only
at the exact moment it completes its poll, eliminating the UAF
window.
Furthermore, explicitly guard the 'native_match' assignment with an
if (rx_seqnum == tx_seqnum) check, even for zero-length (no payload)
responses. While an unguarded assignment wouldn't crash (because the
cache fallback acpm_get_saved_rx() safely returns early on zero-length
transfers) doing so would "lie" to the state machine. If a thread
drained the queue and found another thread's zero-length message,
setting native_match = true would falsely convince the polling loop
that it natively handled its own response. Maintaining a rigorous state
machine requires that native_match is only set when a thread explicitly
processes its own sequence number.
Cc: stable@vger.kernel.org
Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Closes: https://sashiko.dev/#/patchset/20260429-acpm-fixes-sashiko-reports-v3-0-47cf74ab09ad%40linaro.org [1]
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Link: https://patch.msgid.link/20260505-acpm-fixes-sashiko-reports-v5-5-43b5ee7f1674@linaro.org
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/firmware/samsung/exynos-acpm.c | 68 +++++++++++++++++++++++----------
1 file changed, 48 insertions(+), 20 deletions(-)
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -105,11 +105,14 @@ struct acpm_queue {
* @cmd: pointer to where the data shall be saved.
* @n_cmd: number of 32-bit commands.
* @rxcnt: expected length of the response in 32-bit words.
+ * @completed: flag indicating if the firmware response has been fully
+ * processed.
*/
struct acpm_rx_data {
u32 *cmd;
size_t n_cmd;
size_t rxcnt;
+ bool completed;
};
#define ACPM_SEQNUM_MAX 64
@@ -204,26 +207,28 @@ static void acpm_get_saved_rx(struct acp
rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
- if (rx_seqnum == tx_seqnum) {
+ if (rx_seqnum == tx_seqnum)
memcpy(xfer->rxd, rx_data->cmd, xfer->rxcnt * sizeof(*xfer->rxd));
- clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
- }
}
/**
* acpm_get_rx() - get response from RX queue.
* @achan: ACPM channel info.
* @xfer: reference to the transfer to get response for.
+ * @native_match: pointer to a boolean set to true if the thread natively
+ * processed its own sequence number during this call.
*
* Return: 0 on success, -errno otherwise.
*/
-static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
+static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer,
+ bool *native_match)
{
u32 rx_front, rx_seqnum, tx_seqnum, seqnum;
const void __iomem *base, *addr;
struct acpm_rx_data *rx_data;
u32 i, val, mlen;
- bool rx_set = false;
+
+ *native_match = false;
guard(mutex)(&achan->rx_lock);
@@ -232,10 +237,8 @@ static int acpm_get_rx(struct acpm_chan
tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
- if (i == rx_front) {
- acpm_get_saved_rx(achan, xfer, tx_seqnum);
+ if (i == rx_front)
return 0;
- }
base = achan->rx.base;
mlen = achan->mlen;
@@ -259,8 +262,13 @@ static int acpm_get_rx(struct acpm_chan
if (rx_data->rxcnt) {
if (rx_seqnum == tx_seqnum) {
__ioread32_copy(xfer->rxd, addr, xfer->rxcnt);
- rx_set = true;
- clear_bit(seqnum, achan->bitmap_seqnum);
+ /*
+ * Signal completion to the polling thread.
+ * Pairs with smp_load_acquire() in polling
+ * loop.
+ */
+ smp_store_release(&rx_data->completed, true);
+ *native_match = true;
} else {
/*
* The RX data corresponds to another request.
@@ -270,9 +278,21 @@ static int acpm_get_rx(struct acpm_chan
*/
__ioread32_copy(rx_data->cmd, addr,
rx_data->rxcnt);
+ /*
+ * Signal completion to the polling thread.
+ * Pairs with smp_load_acquire() in polling
+ * loop.
+ */
+ smp_store_release(&rx_data->completed, true);
}
} else {
- clear_bit(seqnum, achan->bitmap_seqnum);
+ /*
+ * Signal completion to the polling thread.
+ * Pairs with smp_load_acquire() in polling loop.
+ */
+ smp_store_release(&rx_data->completed, true);
+ if (rx_seqnum == tx_seqnum)
+ *native_match = true;
}
i = (i + 1) % achan->qlen;
@@ -281,13 +301,6 @@ static int acpm_get_rx(struct acpm_chan
/* We saved all responses, mark RX empty. */
writel(rx_front, achan->rx.rear);
- /*
- * If the response was not in this iteration of the queue, check if the
- * RX data was previously saved.
- */
- if (!rx_set)
- acpm_get_saved_rx(achan, xfer, tx_seqnum);
-
return 0;
}
@@ -302,6 +315,7 @@ static int acpm_dequeue_by_polling(struc
const struct acpm_xfer *xfer)
{
struct device *dev = achan->acpm->dev;
+ bool native_match;
ktime_t timeout;
u32 seqnum;
int ret;
@@ -310,12 +324,25 @@ static int acpm_dequeue_by_polling(struc
timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US);
do {
- ret = acpm_get_rx(achan, xfer);
+ ret = acpm_get_rx(achan, xfer, &native_match);
if (ret)
return ret;
- if (!test_bit(seqnum - 1, achan->bitmap_seqnum))
+ /*
+ * Safely check if our specific transaction has been processed.
+ * smp_load_acquire prevents the CPU from speculatively
+ * executing subsequent instructions before the transaction is
+ * synchronized.
+ */
+ if (smp_load_acquire(&achan->rx_data[seqnum - 1].completed)) {
+ /* Retrieve payload if another thread cached it for us */
+ if (!native_match)
+ acpm_get_saved_rx(achan, xfer, seqnum);
+
+ /* Relinquish ownership of the sequence slot */
+ clear_bit(seqnum - 1, achan->bitmap_seqnum);
return 0;
+ }
/* Determined experimentally. */
udelay(20);
@@ -380,6 +407,7 @@ static void acpm_prepare_xfer(struct acp
/* Clear data for upcoming responses */
rx_data = &achan->rx_data[achan->seqnum - 1];
+ rx_data->completed = false;
memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd);
/* zero means no response expected */
rx_data->rxcnt = xfer->rxcnt;
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 08/49] firmware: samsung: acpm: Fix missing LKMM barriers in sequence allocator
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (6 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 07/49] firmware: samsung: acpm: Fix false timeouts and Use-After-Free in polling Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 09/49] fuse: re-lock request before replacing page cache folio Greg Kroah-Hartman
` (44 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tudor Ambarus, Krzysztof Kozlowski,
Sasha Levin
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tudor Ambarus <tudor.ambarus@linaro.org>
[ Upstream commit bf296f83a3ddab1ab875edc4e8862cb10553064f ]
Sashiko identified memory ordering races in [1].
The ACPM driver uses a globally shared 'bitmap_seqnum' to track
available sequence numbers. Even though threads now strictly free their
own sequence numbers, the allocation and freeing of these bits across
concurrent threads are effectively lockless operations and require
explicit LKMM memory barriers.
Previously, the driver used plain bitwise operators (test_bit, set_bit,
clear_bit), which lack ordering guarantees. This creates two race
conditions on weakly ordered architectures like ARM64:
1. Polling Release Violation: The polling thread copies its payload and
calls clear_bit(). Without a release barrier, the CPU can reorder
the memory operations, making the cleared bit globally visible
before the payload reads have fully completed.
2. TX Acquire Violation: The TX thread loops on test_bit(), calls
set_bit(), and then wipes the payload buffer via memset(). Without
an acquire barrier, the CPU can speculatively execute the memset()
before the bit is safely and formally claimed.
If these reorderings overlap, a new TX thread can claim the sequence
number and overwrite the buffer while the original polling thread is
still actively reading from it.
Fix this by upgrading the bitwise operators. Wrap the TX allocation in
test_and_set_bit_lock() to establish formal LKMM Acquire semantics, and
pair it with clear_bit_unlock() in the polling path to enforce Release
semantics.
Cc: stable@vger.kernel.org
Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Closes: https://sashiko.dev/#/patchset/20260423-acpm-fixes-sashiko-reports-v1-0-2217b790925e%40linaro.org [1]
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Link: https://patch.msgid.link/20260505-acpm-fixes-sashiko-reports-v5-6-43b5ee7f1674@linaro.org
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/firmware/samsung/exynos-acpm.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -7,7 +7,7 @@
#include <linux/bitfield.h>
#include <linux/bitmap.h>
-#include <linux/bits.h>
+#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/container_of.h>
#include <linux/delay.h>
@@ -340,7 +340,7 @@ static int acpm_dequeue_by_polling(struc
acpm_get_saved_rx(achan, xfer, seqnum);
/* Relinquish ownership of the sequence slot */
- clear_bit(seqnum - 1, achan->bitmap_seqnum);
+ clear_bit_unlock(seqnum - 1, achan->bitmap_seqnum);
return 0;
}
@@ -397,11 +397,18 @@ static void acpm_prepare_xfer(struct acp
struct acpm_rx_data *rx_data;
u32 *txd = (u32 *)xfer->txd;
- /* Prevent chan->seqnum from being re-used */
+ /*
+ * Prevent chan->seqnum from being re-used.
+ * test_and_set_bit_lock() provides formal LKMM Acquire semantics.
+ * It pairs with the RX thread's clear_bit_unlock() to ensure the CPU
+ * does not speculatively execute the rx_data buffer wipe (memset)
+ * before the sequence number is safely claimed.
+ */
do {
if (++achan->seqnum == ACPM_SEQNUM_MAX)
achan->seqnum = 1;
- } while (test_bit(achan->seqnum - 1, achan->bitmap_seqnum));
+ /* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
+ } while (test_and_set_bit_lock(achan->seqnum - 1, achan->bitmap_seqnum));
txd[0] |= FIELD_PREP(ACPM_PROTOCOL_SEQNUM, achan->seqnum);
@@ -411,9 +418,6 @@ static void acpm_prepare_xfer(struct acp
memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd);
/* zero means no response expected */
rx_data->rxcnt = xfer->rxcnt;
-
- /* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
- set_bit(achan->seqnum - 1, achan->bitmap_seqnum);
}
/**
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 09/49] fuse: re-lock request before replacing page cache folio
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (7 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 08/49] firmware: samsung: acpm: Fix missing LKMM barriers in sequence allocator Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 10/49] Revert "NFSD: Defer sub-object cleanup in export put callbacks" Greg Kroah-Hartman
` (43 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Lei Lu, Joanne Koong, Miklos Szeredi
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joanne Koong <joannelkoong@gmail.com>
commit a078484921052d0badd827fcc2770b5cfc1d4120 upstream.
fuse_try_move_folio() unlocks the request on entry but does not
re-lock it on the success path. This means fuse_chan_abort() can end the
request and free the fuse_io_args (eg fuse_readpages_end()) while the
subsequent copy chain logic after fuse_try_move_folio() accesses the
fuse_io_args, leading to use-after-free issues.
Fix this by calling lock_request() before replace_page_cache_folio().
This ensures the request is locked on the success path which will
prevent the fuse_io_args from being freed while the later copying logic
runs, and also ensures that the ap->folios[i]->mapping is never null
since ap->folios[i] will always point to the newfolio after
replace_page_cache_folio().
Fixes: ce534fb05292 ("fuse: allow splice to move pages")
Cc: stable@vger.kernel.org
Reported-by: Lei Lu <llfamsec@gmail.com>
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/fuse/dev.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1037,6 +1037,10 @@ static int fuse_try_move_folio(struct fu
if (WARN_ON(folio_test_mlocked(oldfolio)))
goto out_fallback_unlock;
+ err = lock_request(cs->req);
+ if (err)
+ goto out_fallback_unlock;
+
replace_page_cache_folio(oldfolio, newfolio);
folio_get(newfolio);
@@ -1050,20 +1054,7 @@ static int fuse_try_move_folio(struct fu
*/
pipe_buf_release(cs->pipe, buf);
- err = 0;
- spin_lock(&cs->req->waitq.lock);
- if (test_bit(FR_ABORTED, &cs->req->flags))
- err = -ENOENT;
- else
- *foliop = newfolio;
- spin_unlock(&cs->req->waitq.lock);
-
- if (err) {
- folio_unlock(newfolio);
- folio_put(newfolio);
- goto out_put_old;
- }
-
+ *foliop = newfolio;
folio_unlock(oldfolio);
/* Drop ref for ap->pages[] array */
folio_put(oldfolio);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 10/49] Revert "NFSD: Defer sub-object cleanup in export put callbacks"
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (8 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 09/49] fuse: re-lock request before replacing page cache folio Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 11/49] RDMA/bnxt_re: zero shared page before exposing to userspace Greg Kroah-Hartman
` (42 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jeff Layton, Alexandr Alexandrov,
Yang Erkun, Chuck Lever
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Erkun <yangerkun@huawei.com>
commit 516403d4d85607fdef3ca41d4a56b54e5566fa9a upstream.
This reverts commit 48db892356d6cb80f6942885545de4a6dd8d2a29.
Commit 48db892356d6 ("NFSD: Defer sub-object cleanup in export
put callbacks") moved path_put() and auth_domain_put() out of
svc_export_put() and expkey_put() and behind queue_rcu_work() to
close a claimed use-after-free in e_show() and c_show() against
ex_path and ex_client->name. Discussion in [1] shows neither
the diagnosis nor the remedy survives review.
The downstream teardown of both sub-objects is already RCU-deferred.
auth_domain_put() reaches svcauth_unix_domain_release(), which frees
the unix_domain and its ->name through call_rcu(). path_put()
reaches dentry_free(), which frees the dentry through call_rcu(),
and prepend_path() is already structured to tolerate concurrent
dentry teardown. A reader in cache_seq_start_rcu() therefore
observes both sub-objects through the next grace period regardless
of whether svc_export_put() runs synchronously, so the synchronous
form was never unsafe.
The crash signature in the report cited by commit 48db892356d6
("NFSD: Defer sub-object cleanup in export put callbacks") has a
different root cause: a /proc/net/rpc cache file held open across
network-namespace exit lets cache_destroy_net() free cd->hash_table
while a reader is still walking it. The correct fix pins cd->net for
the open fd's lifetime and does not require any deferral inside
svc_export_put().
Meanwhile, deferring path_put() out of svc_export_put() reintroduces
the regression that commit 69d803c40ede ("nfsd: Revert "nfsd:
release svc_expkey/svc_export with rcu_work"") repaired: after
"exportfs -r" drops the last cache reference, the mount reference
held through ex_path lingers in the workqueue, so a subsequent
umount fails with EBUSY.
Restore the synchronous path_put() and auth_domain_put() in
svc_export_put() and expkey_put() and the call_rcu()/kfree_rcu()
free of the containing structures. The unrelated fix for
ex_uuid/ex_stats from commit 2530766492ec ("nfsd: fix UAF when
access ex_uuid or ex_stats") is preserved.
Link: https://lore.kernel.org/all/10019b42-4589-4f9f-8d5b-d8197db1ce3c@huawei.com/ [1]
Fixes: 48db892356d6 ("NFSD: Defer sub-object cleanup in export put callbacks")
Cc: stable@vger.kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Tested-by: Alexandr Alexandrov <alexandr.alexandrov@oracle.com>
Signed-off-by: Yang Erkun <yangerkun@huawei.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/nfsd/export.c | 63 +++++++------------------------------------------------
fs/nfsd/export.h | 7 +-----
fs/nfsd/nfsctl.c | 8 ------
3 files changed, 12 insertions(+), 66 deletions(-)
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -36,30 +36,19 @@
* second map contains a reference to the entry in the first map.
*/
-static struct workqueue_struct *nfsd_export_wq;
-
#define EXPKEY_HASHBITS 8
#define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
-static void expkey_release(struct work_struct *work)
+static void expkey_put(struct kref *ref)
{
- struct svc_expkey *key = container_of(to_rcu_work(work),
- struct svc_expkey, ek_rwork);
+ struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
if (test_bit(CACHE_VALID, &key->h.flags) &&
!test_bit(CACHE_NEGATIVE, &key->h.flags))
path_put(&key->ek_path);
auth_domain_put(key->ek_client);
- kfree(key);
-}
-
-static void expkey_put(struct kref *ref)
-{
- struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
-
- INIT_RCU_WORK(&key->ek_rwork, expkey_release);
- queue_rcu_work(nfsd_export_wq, &key->ek_rwork);
+ kfree_rcu(key, ek_rcu);
}
static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -364,13 +353,11 @@ static void export_stats_destroy(struct
EXP_STATS_COUNTERS_NUM);
}
-static void svc_export_release(struct work_struct *work)
+static void svc_export_release(struct rcu_head *rcu_head)
{
- struct svc_export *exp = container_of(to_rcu_work(work),
- struct svc_export, ex_rwork);
+ struct svc_export *exp = container_of(rcu_head, struct svc_export,
+ ex_rcu);
- path_put(&exp->ex_path);
- auth_domain_put(exp->ex_client);
nfsd4_fslocs_free(&exp->ex_fslocs);
export_stats_destroy(exp->ex_stats);
kfree(exp->ex_stats);
@@ -382,8 +369,9 @@ static void svc_export_put(struct kref *
{
struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
- INIT_RCU_WORK(&exp->ex_rwork, svc_export_release);
- queue_rcu_work(nfsd_export_wq, &exp->ex_rwork);
+ path_put(&exp->ex_path);
+ auth_domain_put(exp->ex_client);
+ call_rcu(&exp->ex_rcu, svc_export_release);
}
static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -1491,36 +1479,6 @@ const struct seq_operations nfs_exports_
.show = e_show,
};
-/**
- * nfsd_export_wq_init - allocate the export release workqueue
- *
- * Called once at module load. The workqueue runs deferred svc_export and
- * svc_expkey release work scheduled by queue_rcu_work() in the cache put
- * callbacks.
- *
- * Return values:
- * %0: workqueue allocated
- * %-ENOMEM: allocation failed
- */
-int nfsd_export_wq_init(void)
-{
- nfsd_export_wq = alloc_workqueue("nfsd_export", WQ_UNBOUND, 0);
- if (!nfsd_export_wq)
- return -ENOMEM;
- return 0;
-}
-
-/**
- * nfsd_export_wq_shutdown - drain and free the export release workqueue
- *
- * Called once at module unload. Per-namespace teardown in
- * nfsd_export_shutdown() has already drained all deferred work.
- */
-void nfsd_export_wq_shutdown(void)
-{
- destroy_workqueue(nfsd_export_wq);
-}
-
/*
* Initialize the exports module.
*/
@@ -1582,9 +1540,6 @@ nfsd_export_shutdown(struct net *net)
cache_unregister_net(nn->svc_expkey_cache, net);
cache_unregister_net(nn->svc_export_cache, net);
- /* Drain deferred export and expkey release work. */
- rcu_barrier();
- flush_workqueue(nfsd_export_wq);
cache_destroy_net(nn->svc_expkey_cache, net);
cache_destroy_net(nn->svc_export_cache, net);
svcauth_unix_purge(net);
--- a/fs/nfsd/export.h
+++ b/fs/nfsd/export.h
@@ -7,7 +7,6 @@
#include <linux/sunrpc/cache.h>
#include <linux/percpu_counter.h>
-#include <linux/workqueue.h>
#include <uapi/linux/nfsd/export.h>
#include <linux/nfs4.h>
@@ -76,7 +75,7 @@ struct svc_export {
u32 ex_layout_types;
struct nfsd4_deviceid_map *ex_devid_map;
struct cache_detail *cd;
- struct rcu_work ex_rwork;
+ struct rcu_head ex_rcu;
unsigned long ex_xprtsec_modes;
struct export_stats *ex_stats;
};
@@ -93,7 +92,7 @@ struct svc_expkey {
u32 ek_fsid[6];
struct path ek_path;
- struct rcu_work ek_rwork;
+ struct rcu_head ek_rcu;
};
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
@@ -111,8 +110,6 @@ __be32 check_nfsd_access(struct svc_expo
/*
* Function declarations
*/
-int nfsd_export_wq_init(void);
-void nfsd_export_wq_shutdown(void);
int nfsd_export_init(struct net *);
void nfsd_export_shutdown(struct net *);
void nfsd_export_flush(struct net *);
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -2269,12 +2269,9 @@ static int __init init_nfsd(void)
if (retval)
goto out_free_pnfs;
nfsd_lockd_init(); /* lockd->nfsd callbacks */
- retval = nfsd_export_wq_init();
- if (retval)
- goto out_free_lockd;
retval = register_pernet_subsys(&nfsd_net_ops);
if (retval < 0)
- goto out_free_export_wq;
+ goto out_free_lockd;
retval = register_cld_notifier();
if (retval)
goto out_free_subsys;
@@ -2303,8 +2300,6 @@ out_free_cld:
unregister_cld_notifier();
out_free_subsys:
unregister_pernet_subsys(&nfsd_net_ops);
-out_free_export_wq:
- nfsd_export_wq_shutdown();
out_free_lockd:
nfsd_lockd_shutdown();
nfsd_drc_slab_free();
@@ -2325,7 +2320,6 @@ static void __exit exit_nfsd(void)
nfsd4_destroy_laundry_wq();
unregister_cld_notifier();
unregister_pernet_subsys(&nfsd_net_ops);
- nfsd_export_wq_shutdown();
nfsd_drc_slab_free();
nfsd_lockd_shutdown();
nfsd4_free_slabs();
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 11/49] RDMA/bnxt_re: zero shared page before exposing to userspace
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (9 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 10/49] Revert "NFSD: Defer sub-object cleanup in export put callbacks" Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 12/49] bpf: Fix NULL pointer dereference in bpf_sk_storage_clone and diag paths Greg Kroah-Hartman
` (41 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lord Ulf Henrik Holmberg,
Leon Romanovsky
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lord Ulf Henrik Holmberg <henrik.holmberg@defensify.se>
commit f6b079629becfa977f9c51fe53ad2e6dcc55ef44 upstream.
bnxt_re_alloc_ucontext() allocates uctx->shpg via
__get_free_page(GFP_KERNEL). The buddy allocator does not zero pages
without __GFP_ZERO, so the page contains stale kernel data from
whatever object most recently freed it.
The page is then mapped into userspace via vm_insert_page() under
BNXT_RE_MMAP_SH_PAGE in bnxt_re_mmap(). The driver only ever writes
4 bytes (a u32 AVID) at offset BNXT_RE_AVID_OFFT (0x10) inside
bnxt_re_create_ah(); the remaining 4092 bytes of the page are exposed
to userspace unsanitised, leaking kernel memory contents.
Any user with access to /dev/infiniband/uverbsX on a host with a
bnxt_re device (typically rdma group membership) can read this data
via a single mmap() at pgoff 0 after IB_USER_VERBS_CMD_GET_CONTEXT.
Other shared pages in the same file already use get_zeroed_page()
correctly:
drivers/infiniband/hw/bnxt_re/ib_verbs.c
srq->uctx_srq_page = (void *)get_zeroed_page(GFP_KERNEL);
cq->uctx_cq_page = (void *)get_zeroed_page(GFP_KERNEL);
uctx->shpg is the only outlier. Bring it in line with the existing
convention by switching to get_zeroed_page().
Fixes: 1ac5a4047975 ("RDMA/bnxt_re: Add bnxt_re RoCE driver")
Signed-off-by: Lord Ulf Henrik Holmberg <henrik.holmberg@defensify.se>
Link: https://patch.msgid.link/20260509084011.11971-1-pomzm67@gmail.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/infiniband/hw/bnxt_re/ib_verbs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -4375,7 +4375,7 @@ int bnxt_re_alloc_ucontext(struct ib_uco
uctx->rdev = rdev;
- uctx->shpg = (void *)__get_free_page(GFP_KERNEL);
+ uctx->shpg = (void *)get_zeroed_page(GFP_KERNEL);
if (!uctx->shpg) {
rc = -ENOMEM;
goto fail;
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 12/49] bpf: Fix NULL pointer dereference in bpf_sk_storage_clone and diag paths
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (10 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 11/49] RDMA/bnxt_re: zero shared page before exposing to userspace Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 13/49] i2c: stub: Reject I2C block transfers with invalid length Greg Kroah-Hartman
` (40 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiang Mei, Amery Hung, Weiming Shi,
Martin KaFai Lau
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <bestswngs@gmail.com>
commit 375e4e33c18dfa05c5dfd5f3dfffeb29343dd4c7 upstream.
bpf_selem_unlink_nofail() sets SDATA(selem)->smap to NULL before
removing the selem from the storage hlist. A concurrent RCU reader in
bpf_sk_storage_clone() can observe the selem still on the list with
smap already NULL, causing a NULL pointer dereference.
general protection fault, probably for non-canonical address 0xdffffc000000000a:
KASAN: null-ptr-deref in range [0x0000000000000050-0x0000000000000057]
RIP: 0010:bpf_sk_storage_clone+0x1cd/0xaa0 net/core/bpf_sk_storage.c:174
Call Trace:
<IRQ>
sk_clone+0xfed/0x1980 net/core/sock.c:2591
inet_csk_clone_lock+0x30/0x760 net/ipv4/inet_connection_sock.c:1222
tcp_create_openreq_child+0x35/0x2680 net/ipv4/tcp_minisocks.c:571
tcp_v4_syn_recv_sock+0x123/0xf90 net/ipv4/tcp_ipv4.c:1729
tcp_check_req+0x8e1/0x2580 include/net/tcp.h:855
tcp_v4_rcv+0x1845/0x3b80 net/ipv4/tcp_ipv4.c:2347
Add a NULL check for smap in bpf_sk_storage_clone().
bpf_sk_storage_diag_put_all() has the same issue. Add a NULL check
and pass the validated smap directly to diag_get(), which is refactored
to take smap as a parameter instead of reading it internally.
bpf_sk_storage_diag_put() uses diag->maps[i] which is always valid
under its refcount, so diag->maps[i] is passed directly to diag_get().
Fixes: 5d800f87d0a5 ("bpf: Support lockless unlink when freeing map or local storage")
Reported-by: Xiang Mei <xmei5@asu.edu>
Acked-by: Amery Hung <ameryhung@gmail.com>
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://patch.msgid.link/20260422065411.1007737-2-bestswngs@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/bpf_sk_storage.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/net/core/bpf_sk_storage.c
+++ b/net/core/bpf_sk_storage.c
@@ -172,7 +172,7 @@ int bpf_sk_storage_clone(const struct so
struct bpf_map *map;
smap = rcu_dereference(SDATA(selem)->smap);
- if (!(smap->map.map_flags & BPF_F_CLONE))
+ if (!smap || !(smap->map.map_flags & BPF_F_CLONE))
continue;
/* Note that for lockless listeners adding new element
@@ -534,10 +534,10 @@ err_free:
}
EXPORT_SYMBOL_GPL(bpf_sk_storage_diag_alloc);
-static int diag_get(struct bpf_local_storage_data *sdata, struct sk_buff *skb)
+static int diag_get(struct bpf_local_storage_map *smap,
+ struct bpf_local_storage_data *sdata, struct sk_buff *skb)
{
struct nlattr *nla_stg, *nla_value;
- struct bpf_local_storage_map *smap;
/* It cannot exceed max nlattr's payload */
BUILD_BUG_ON(U16_MAX - NLA_HDRLEN < BPF_LOCAL_STORAGE_MAX_VALUE_SIZE);
@@ -546,7 +546,6 @@ static int diag_get(struct bpf_local_sto
if (!nla_stg)
return -EMSGSIZE;
- smap = rcu_dereference(sdata->smap);
if (nla_put_u32(skb, SK_DIAG_BPF_STORAGE_MAP_ID, smap->map.id))
goto errout;
@@ -599,9 +598,11 @@ static int bpf_sk_storage_diag_put_all(s
saved_len = skb->len;
hlist_for_each_entry_rcu(selem, &sk_storage->list, snode) {
smap = rcu_dereference(SDATA(selem)->smap);
+ if (!smap)
+ continue;
diag_size += nla_value_size(smap->map.value_size);
- if (nla_stgs && diag_get(SDATA(selem), skb))
+ if (nla_stgs && diag_get(smap, SDATA(selem), skb))
/* Continue to learn diag_size */
err = -EMSGSIZE;
}
@@ -668,7 +669,7 @@ int bpf_sk_storage_diag_put(struct bpf_s
diag_size += nla_value_size(diag->maps[i]->value_size);
- if (nla_stgs && diag_get(sdata, skb))
+ if (nla_stgs && diag_get((struct bpf_local_storage_map *)diag->maps[i], sdata, skb))
/* Continue to learn diag_size */
err = -EMSGSIZE;
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 13/49] i2c: stub: Reject I2C block transfers with invalid length
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (11 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 12/49] bpf: Fix NULL pointer dereference in bpf_sk_storage_clone and diag paths Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 14/49] net: qualcomm: rmnet: fix endpoint use-after-free in rmnet_dellink() Greg Kroah-Hartman
` (39 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiang Mei, Weiming Shi, Jean Delvare,
Wolfram Sang
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <bestswngs@gmail.com>
commit 6036b5067a8199ba7a2dc7b377d4b9dd276d5f9e upstream.
The I2C_SMBUS_I2C_BLOCK_DATA case in stub_xfer() uses data->block[0]
as the transfer length. The existing check only clamps it to avoid
overrunning the chip->words[256] register array, but does not validate
it against I2C_SMBUS_BLOCK_MAX (32), which is the limit of the union
i2c_smbus_data.block buffer (34 bytes total). The driver is a
development/test tool (CONFIG_I2C_STUB=m, not built by default)
that must be loaded with a chip_addr= parameter.
A local user with access to /dev/i2c-* can issue an I2C_SMBUS ioctl
with I2C_SMBUS_I2C_BLOCK_DATA and data->block[0] > 32, causing
stub_xfer() to read or write past the end of the union
i2c_smbus_data.block buffer:
BUG: KASAN: stack-out-of-bounds in stub_xfer (drivers/i2c/i2c-stub.c:223)
Read of size 1 at addr ffff88800abcfd92 by task exploit/81
Call Trace:
<TASK>
stub_xfer (drivers/i2c/i2c-stub.c:223)
__i2c_smbus_xfer (drivers/i2c/i2c-core-smbus.c:593)
i2c_smbus_xfer (drivers/i2c/i2c-core-smbus.c:536)
i2cdev_ioctl_smbus (drivers/i2c/i2c-dev.c:391)
i2cdev_ioctl (drivers/i2c/i2c-dev.c:478)
__x64_sys_ioctl (fs/ioctl.c:583)
do_syscall_64 (arch/x86/entry/syscall_64.c:94)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
</TASK>
The bug exists because i2c-stub implements .smbus_xfer directly,
bypassing the I2C_SMBUS_BLOCK_MAX validation in
i2c_smbus_xfer_emulated(). The I2C_SMBUS_BLOCK_DATA case in the same
function correctly validates against I2C_SMBUS_BLOCK_MAX, but the
I2C_SMBUS_I2C_BLOCK_DATA case does not.
Fix by rejecting transfers with data->block[0] == 0 or
data->block[0] > I2C_SMBUS_BLOCK_MAX with -EINVAL, consistent with
both the I2C_SMBUS_BLOCK_DATA case in the same function and the
I2C_SMBUS_I2C_BLOCK_DATA validation in i2c_smbus_xfer_emulated().
Fixes: 4710317891e4 ("i2c-stub: Implement I2C block support")
Reported-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Reviewed-by: Jean Delvare <jdelvare@suse.de>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/i2c/i2c-stub.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/i2c/i2c-stub.c
+++ b/drivers/i2c/i2c-stub.c
@@ -214,6 +214,11 @@ static s32 stub_xfer(struct i2c_adapter
* We ignore banks here, because banked chips don't use I2C
* block transfers
*/
+ if (data->block[0] == 0 ||
+ data->block[0] > I2C_SMBUS_BLOCK_MAX) {
+ ret = -EINVAL;
+ break;
+ }
if (data->block[0] > 256 - command) /* Avoid overrun */
data->block[0] = 256 - command;
len = data->block[0];
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 14/49] net: qualcomm: rmnet: fix endpoint use-after-free in rmnet_dellink()
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (12 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 13/49] i2c: stub: Reject I2C block transfers with invalid length Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 15/49] agp/amd64: Fix broken error propagation in agp_amd64_probe() Greg Kroah-Hartman
` (38 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Xiang Mei, Weiming Shi,
Jakub Kicinski
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <bestswngs@gmail.com>
commit d00c953a8f69921f484b629801766da68f27f658 upstream.
rmnet_dellink() removes the endpoint from the hash table with
hlist_del_init_rcu() and then immediately frees it with kfree(). However,
RCU readers on the receive path (rmnet_rx_handler ->
__rmnet_map_ingress_handler) may still hold a reference to the endpoint and
dereference ep->egress_dev after the memory has been freed. The endpoint is
a kmalloc-32 object, and the stale read at offset 8 corresponds to the
egress_dev pointer.
BUG: unable to handle page fault for address: ffffffffde942eef
Oops: 0002 [#1] SMP NOPTI
CPU: 1 UID: 0 PID: 137 Comm: poc_write Not tainted 7.0.0+ #4 PREEMPTLAZY
RIP: 0010:rmnet_vnd_rx_fixup (rmnet_vnd.c:27)
Call Trace:
<TASK>
__rmnet_map_ingress_handler (rmnet_handlers.c:48 rmnet_handlers.c:101)
rmnet_rx_handler (rmnet_handlers.c:129 rmnet_handlers.c:235)
__netif_receive_skb_core.constprop.0 (net/core/dev.c:6096)
__netif_receive_skb_one_core (net/core/dev.c:6208)
netif_receive_skb (net/core/dev.c:6467)
tun_get_user (drivers/net/tun.c:1955)
tun_chr_write_iter (drivers/net/tun.c:2003)
vfs_write (fs/read_write.c:688)
ksys_write (fs/read_write.c:740)
</TASK>
Add an rcu_head field to struct rmnet_endpoint and replace kfree() with
kfree_rcu() so the endpoint memory remains valid through the RCU grace
period. Also remove the rmnet_vnd_dellink() call and inline only the
nr_rmnet_devs decrement, since rmnet_vnd_dellink() would set
ep->egress_dev to NULL during the grace period, creating a data race
with lockless readers.
Fixes: ceed73a2cf4a ("drivers: net: ethernet: qualcomm: rmnet: Initial implementation")
Reported-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Link: https://patch.msgid.link/20260514122511.3083479-2-bestswngs@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 8 ++++----
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h | 1 +
2 files changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
@@ -213,8 +213,8 @@ static void rmnet_dellink(struct net_dev
ep = rmnet_get_endpoint(real_port, mux_id);
if (ep) {
hlist_del_init_rcu(&ep->hlnode);
- rmnet_vnd_dellink(mux_id, real_port, ep);
- kfree(ep);
+ real_port->nr_rmnet_devs--;
+ kfree_rcu(ep, rcu);
}
netdev_upper_dev_unlink(real_dev, dev);
@@ -238,9 +238,9 @@ static void rmnet_force_unassociate_devi
hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
unregister_netdevice_queue(ep->egress_dev, &list);
netdev_upper_dev_unlink(real_dev, ep->egress_dev);
- rmnet_vnd_dellink(ep->mux_id, port, ep);
hlist_del_init_rcu(&ep->hlnode);
- kfree(ep);
+ port->nr_rmnet_devs--;
+ kfree_rcu(ep, rcu);
}
rmnet_unregister_real_device(real_dev);
unregister_netdevice_many(&list);
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
@@ -18,6 +18,7 @@ struct rmnet_endpoint {
u8 mux_id;
struct net_device *egress_dev;
struct hlist_node hlnode;
+ struct rcu_head rcu;
};
struct rmnet_egress_agg_params {
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 15/49] agp/amd64: Fix broken error propagation in agp_amd64_probe()
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (13 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 14/49] net: qualcomm: rmnet: fix endpoint use-after-free in rmnet_dellink() Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 16/49] rose: fix dev_put() leak in rose_loopback_timer() Greg Kroah-Hartman
` (37 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mingyu Wang, Lukas Wunner
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
commit b08472db93b1ccff84a7adec5779d47f0e9d3a30 upstream.
A NULL pointer dereference was observed in the AMD64 AGP driver when
running in a virtualized environment (e.g. qemu/kvm) without a physical
AMD northbridge. The crash occurs in amd64_fetch_size() when attempting
to dereference the pointer returned by node_to_amd_nb(0).
The root cause of this crash is broken error propagation in
agp_amd64_probe(): When no AMD northbridges are found, cache_nbs()
correctly returns -ENODEV. However, the probe function erroneously
checks the return value against exactly -1, rather than < 0.
As a result, the hardware absence error is masked, allowing the driver
to improperly proceed with initialization. It eventually calls
agp_add_bridge(), which invokes amd64_fetch_size(). Since the hardware
does not exist, node_to_amd_nb(0) returns NULL, leading to a General
Protection Fault (GPF) when accessing its ->misc member.
Fix the issue by correcting the error check in agp_amd64_probe() to
abort properly when cache_nbs() returns any negative error code. This
prevents the driver from erroneously proceeding without hardware, thereby
avoiding the subsequent NULL pointer dereference at its source.
Fixes: a32073bffc65 ("[PATCH] x86_64: Clean and enhance up K8 northbridge access code")
Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Lukas Wunner <lukas@wunner.de>
Cc: stable@vger.kernel.org # v2.6.18+
Link: https://patch.msgid.link/20260504074823.99377-1-w15303746062@163.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/char/agp/amd64-agp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -546,7 +546,7 @@ static int agp_amd64_probe(struct pci_de
/* Fill in the mode register */
pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode);
- if (cache_nbs(pdev, cap_ptr) == -1) {
+ if (cache_nbs(pdev, cap_ptr) < 0) {
agp_put_bridge(bridge);
return -ENODEV;
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 16/49] rose: fix dev_put() leak in rose_loopback_timer()
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (14 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 15/49] agp/amd64: Fix broken error propagation in agp_amd64_probe() Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 17/49] rose: hold loopback neighbour reference across timer callback Greg Kroah-Hartman
` (36 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit ff91adc54db2b62c7cdf063ff761eceb5adf2215 upstream.
rose_rx_call_request() always consumes or returns the skb but never
releases the device reference obtained from rose_dev_get(). When
rose_rx_call_request() succeeds (returns non-zero) dev_put() was never
called, leaking one reference per loopback CALL_REQUEST.
Move dev_put() outside the conditional so it is called unconditionally
after rose_rx_call_request() in all cases.
Also remove the dead check (!rose_loopback_neigh->dev &&
!rose_loopback_neigh->loopback) that immediately precedes it: the
loopback neighbour always has loopback=1 so this condition can never
be true.
Fixes: 0453c6824595 ("net/rose: fix unbound loop in rose_loopback_timer()")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/rose_loopback.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
--- a/net/rose/rose_loopback.c
+++ b/net/rose/rose_loopback.c
@@ -96,22 +96,15 @@ static void rose_loopback_timer(struct t
}
if (frametype == ROSE_CALL_REQUEST) {
- if (!rose_loopback_neigh->dev &&
- !rose_loopback_neigh->loopback) {
- kfree_skb(skb);
- continue;
- }
-
dev = rose_dev_get(dest);
if (!dev) {
kfree_skb(skb);
continue;
}
- if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) {
- dev_put(dev);
+ if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0)
kfree_skb(skb);
- }
+ dev_put(dev);
} else {
kfree_skb(skb);
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 17/49] rose: hold loopback neighbour reference across timer callback
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (15 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 16/49] rose: fix dev_put() leak in rose_loopback_timer() Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 18/49] rose: fix race between loopback timer and module removal Greg Kroah-Hartman
` (35 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit d270a7a5793af84555c40dd1eb80f1d497fdf53c upstream.
rose_loopback_timer() dereferences rose_loopback_neigh throughout its
body but holds no reference on it. A concurrent rose_loopback_clear()
followed by rose_add_loopback_neigh() could free and reallocate the
neighbour while the timer body is running, causing a use-after-free.
Take a reference with rose_neigh_hold() at the start of the callback
(bailing out if the pointer is already NULL) and release it with
rose_neigh_put() at the single exit point. The neigh cannot be freed
while the callback holds a reference.
Fixes: d860d1faa6b2 ("net: rose: convert 'use' field to refcount_t")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/rose_loopback.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
--- a/net/rose/rose_loopback.c
+++ b/net/rose/rose_loopback.c
@@ -66,10 +66,15 @@ static void rose_loopback_timer(struct t
unsigned int lci_i, lci_o;
int count;
+ if (rose_loopback_neigh)
+ rose_neigh_hold(rose_loopback_neigh);
+ else
+ return;
+
for (count = 0; count < ROSE_LOOPBACK_LIMIT; count++) {
skb = skb_dequeue(&loopback_queue);
if (!skb)
- return;
+ goto out;
if (skb->len < ROSE_MIN_LEN) {
kfree_skb(skb);
continue;
@@ -109,6 +114,10 @@ static void rose_loopback_timer(struct t
kfree_skb(skb);
}
}
+
+out:
+ rose_neigh_put(rose_loopback_neigh);
+
if (!skb_queue_empty(&loopback_queue))
mod_timer(&loopback_timer, jiffies + 1);
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 18/49] rose: fix race between loopback timer and module removal
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (16 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 17/49] rose: hold loopback neighbour reference across timer callback Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 19/49] rose: clear neighbour pointer after rose_neigh_put() in state machines Greg Kroah-Hartman
` (34 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit 47dd6ec1a77d77895afb00aa2e68373a48289108 upstream.
rose_loopback_clear() called timer_delete() which returns immediately
without waiting for any running callback to complete. If the timer
fired concurrently with module removal, rose_loopback_timer() could
re-arm the timer after timer_delete() returned and then access
rose_loopback_neigh after it was freed.
Two complementary changes close the race:
1. Add a loopback_stopping atomic flag. rose_loopback_timer() checks
it at entry (before acquiring a reference) and again inside the
loop; when set it drains the queue and exits without re-arming the
timer.
2. Switch rose_loopback_clear() to timer_delete_sync() so it blocks
until any in-flight callback has returned before freeing resources.
The smp_mb() between setting the flag and calling timer_delete_sync()
ensures the flag is visible to any callback that is about to run.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/rose_loopback.c | 31 ++++++++++++++++++++++++-------
1 file changed, 24 insertions(+), 7 deletions(-)
--- a/net/rose/rose_loopback.c
+++ b/net/rose/rose_loopback.c
@@ -12,13 +12,15 @@
#include <net/rose.h>
#include <linux/init.h>
-static struct sk_buff_head loopback_queue;
#define ROSE_LOOPBACK_LIMIT 1000
-static struct timer_list loopback_timer;
+static struct timer_list loopback_timer;
+static struct sk_buff_head loopback_queue;
static void rose_set_loopback_timer(void);
static void rose_loopback_timer(struct timer_list *unused);
+static atomic_t loopback_stopping = ATOMIC_INIT(0);
+
void rose_loopback_init(void)
{
skb_queue_head_init(&loopback_queue);
@@ -66,6 +68,9 @@ static void rose_loopback_timer(struct t
unsigned int lci_i, lci_o;
int count;
+ if (atomic_read(&loopback_stopping))
+ return;
+
if (rose_loopback_neigh)
rose_neigh_hold(rose_loopback_neigh);
else
@@ -75,6 +80,13 @@ static void rose_loopback_timer(struct t
skb = skb_dequeue(&loopback_queue);
if (!skb)
goto out;
+
+ if (atomic_read(&loopback_stopping)) {
+ kfree_skb(skb);
+ skb_queue_purge(&loopback_queue);
+ goto out;
+ }
+
if (skb->len < ROSE_MIN_LEN) {
kfree_skb(skb);
continue;
@@ -118,7 +130,7 @@ static void rose_loopback_timer(struct t
out:
rose_neigh_put(rose_loopback_neigh);
- if (!skb_queue_empty(&loopback_queue))
+ if (!atomic_read(&loopback_stopping) && !skb_queue_empty(&loopback_queue))
mod_timer(&loopback_timer, jiffies + 1);
}
@@ -126,10 +138,15 @@ void __exit rose_loopback_clear(void)
{
struct sk_buff *skb;
- timer_delete(&loopback_timer);
+ atomic_set(&loopback_stopping, 1);
+ /* Pairs with atomic_read() in rose_loopback_timer(): ensure the
+ * stopping flag is visible before we cancel, so a concurrent
+ * callback aborts its loop early rather than re-arming the timer.
+ */
+ smp_mb();
+
+ timer_delete_sync(&loopback_timer);
- while ((skb = skb_dequeue(&loopback_queue)) != NULL) {
- skb->sk = NULL;
+ while ((skb = skb_dequeue(&loopback_queue)) != NULL)
kfree_skb(skb);
- }
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 19/49] rose: clear neighbour pointer after rose_neigh_put() in state machines
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (17 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 18/49] rose: fix race between loopback timer and module removal Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 20/49] rose: guard rose_neigh_put() against NULL in timer expiry Greg Kroah-Hartman
` (33 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit e8eb0c6faa8849ba7769516c1a8c84d9f612acf6 upstream.
After calling rose_neigh_put() in rose_state1_machine() through
rose_state5_machine(), rose->neighbour was left pointing at the
potentially freed neighbour structure. A subsequent timer expiry or
concurrent teardown path could dereference the stale pointer, causing
a use-after-free.
Set rose->neighbour to NULL immediately after each rose_neigh_put()
call in the state machine functions.
Fixes: d860d1faa6b2 ("net: rose: convert 'use' field to refcount_t")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/rose_in.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -57,6 +57,7 @@ static int rose_state1_machine(struct so
rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
break;
default:
@@ -80,11 +81,13 @@ static int rose_state2_machine(struct so
rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
rose_disconnect(sk, 0, skb->data[3], skb->data[4]);
rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
break;
case ROSE_CLEAR_CONFIRMATION:
rose_disconnect(sk, 0, -1, -1);
rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
break;
default:
@@ -122,6 +125,7 @@ static int rose_state3_machine(struct so
rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
rose_disconnect(sk, 0, skb->data[3], skb->data[4]);
rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
break;
case ROSE_RR:
@@ -235,6 +239,7 @@ static int rose_state4_machine(struct so
rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
rose_disconnect(sk, 0, skb->data[3], skb->data[4]);
rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
break;
default:
@@ -255,6 +260,7 @@ static int rose_state5_machine(struct so
rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
rose_disconnect(sk, 0, skb->data[3], skb->data[4]);
rose_neigh_put(rose_sk(sk)->neighbour);
+ rose_sk(sk)->neighbour = NULL;
}
return 0;
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 20/49] rose: guard rose_neigh_put() against NULL in timer expiry
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (18 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 19/49] rose: clear neighbour pointer after rose_neigh_put() in state machines Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 21/49] rose: fix netdev double-hold in rose_rx_call_request() Greg Kroah-Hartman
` (32 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit 2b67342c6ff899a0b83359517146a5b7b243af97 upstream.
In rose_timer_expiry(), the ROSE_STATE_2 branch calls
rose_neigh_put(rose->neighbour) without first checking whether the
pointer is NULL. After commit 5de7665e0a07 ("net: rose: fix timer
races against user threads") the timer is re-armed when the socket is
owned by a user thread; between the re-arm and the next firing, a
device-down event or concurrent teardown via rose_kill_by_device() can
set rose->neighbour to NULL, leading to a NULL-pointer dereference
inside rose_neigh_put().
Add a NULL check before the put and clear the pointer afterwards.
Fixes: 5de7665e0a07 ("net: rose: fix timer races against user threads")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/rose_timer.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -180,7 +180,10 @@ static void rose_timer_expiry(struct tim
break;
case ROSE_STATE_2: /* T3 */
- rose_neigh_put(rose->neighbour);
+ if (rose->neighbour) {
+ rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
+ }
rose_disconnect(sk, ETIMEDOUT, -1, -1);
break;
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 21/49] rose: fix netdev double-hold in rose_rx_call_request()
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (19 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 20/49] rose: guard rose_neigh_put() against NULL in timer expiry Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 22/49] rose: fix notifier unregistered too early in rose_exit() Greg Kroah-Hartman
` (31 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit c675277c3ba0d2310e0825577d58308c39931e14 upstream.
rose_rx_call_request() used netdev_tracker_alloc() after assigning
make_rose->device, intending to take ownership of the reference passed
by the caller. But every caller -- rose_route_frame() and
rose_loopback_timer() -- already calls dev_put() for its own hold after
the function returns, so the socket ended up with a tracker entry
pointing at a reference that had already been released.
The result was spurious refcount_t warnings ("saturated", "decrement
hit 0") on every incoming CALL_REQUEST, leading to refcount corruption
and eventual silent freeze.
Replace netdev_tracker_alloc() with netdev_hold() so that
rose_rx_call_request() acquires its own independent reference. Each
caller retains its own hold from rose_dev_get() and releases it via
dev_put() as before; socket cleanup releases the socket's separate hold
via netdev_put().
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/af_rose.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1079,9 +1079,11 @@ int rose_rx_call_request(struct sk_buff
make_rose->source_digis[n] = facilities.source_digis[n];
make_rose->neighbour = neigh;
make_rose->device = dev;
- /* Caller got a reference for us. */
- netdev_tracker_alloc(make_rose->device, &make_rose->dev_tracker,
- GFP_ATOMIC);
+ /* Take an independent reference for this socket; callers keep their
+ * own reference (from rose_dev_get / dev_hold) and will release it
+ * themselves via dev_put().
+ */
+ netdev_hold(make_rose->device, &make_rose->dev_tracker, GFP_ATOMIC);
make_rose->facilities = facilities;
rose_neigh_hold(make_rose->neighbour);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 22/49] rose: fix notifier unregistered too early in rose_exit()
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (20 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 21/49] rose: fix netdev double-hold in rose_rx_call_request() Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 23/49] rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup Greg Kroah-Hartman
` (30 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit f71a8a1edc14dba746edde38adddd654ba202b4d upstream.
rose_exit() called unregister_netdevice_notifier() before the loop that
calls unregister_netdev() on each ROSE virtual device. As a result,
the NETDEV_DOWN event fired by unregister_netdev() was never delivered
to rose_device_event(), so rose_kill_by_device() never ran.
Every socket whose rose->device pointed at a ROSE device therefore kept
its netdev_tracker entry live until free_netdev() destroyed the
ref_tracker_dir, at which point the kernel reported all of them as
leaked references (165 entries in a typical FPAC setup). Worse, those
sockets retained stale device pointers and live timers that could fire
into freed module text after module unload, causing a silent system
freeze with no kernel panic logged.
Fix by moving unregister_netdevice_notifier() to after the device-
unregistration loop. unregister_netdev() then delivers NETDEV_DOWN
while the notifier is still registered, rose_kill_by_device() runs for
each device, releases all netdev references held by open sockets, and
calls rose_disconnect() which stops the per-socket timers.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/af_rose.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1669,19 +1669,28 @@ static void __exit rose_exit(void)
#ifdef CONFIG_SYSCTL
rose_unregister_sysctl();
#endif
- unregister_netdevice_notifier(&rose_dev_notifier);
-
sock_unregister(PF_ROSE);
for (i = 0; i < rose_ndevs; i++) {
struct net_device *dev = dev_rose[i];
if (dev) {
+ /* unregister_netdev() fires NETDEV_DOWN, which -- while the
+ * notifier is still registered below -- invokes
+ * rose_kill_by_device(dev). That releases every socket's
+ * netdev reference and disconnects all active circuits.
+ * Unregistering the notifier before this loop was the
+ * original bug: NETDEV_DOWN was never delivered, leaving
+ * 165 netdev_tracker entries leaked and stale timers live.
+ */
unregister_netdev(dev);
free_netdev(dev);
}
}
+ /* Now safe to remove the notifier -- all ROSE devices are gone. */
+ unregister_netdevice_notifier(&rose_dev_notifier);
+
kfree(dev_rose);
proto_unregister(&rose_proto);
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 23/49] rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (21 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 22/49] rose: fix notifier unregistered too early in rose_exit() Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 24/49] rose: disconnect orphaned STATE_2 sockets when device is gone Greg Kroah-Hartman
` (29 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit 741a4863ad570889c75f7a8e404567d8f3e46335 upstream.
When rose_kill_by_device() is called (via NETDEV_DOWN on module exit
or interface removal), it calls rose_disconnect() which transitions
sockets to ROSE_STATE_0 and sets SOCK_DEAD. However,
rose_heartbeat_expiry() only calls rose_destroy_socket() at
ROSE_STATE_0 if SOCK_DESTROY is set -- the SOCK_DEAD path is reserved
for TCP_LISTEN sockets. Without SOCK_DESTROY, orphaned sockets in
ROSE_STATE_2 (clearing) loop indefinitely in the heartbeat without
ever being freed, keeping the module use-count elevated and blocking
modprobe -r rose until the T1 timer (up to 200 s) expires.
Set SOCK_DESTROY immediately after rose_disconnect() so the heartbeat
destroys the socket at its next tick (within 5 s), allowing clean
module unload.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/af_rose.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -211,6 +211,11 @@ start:
spin_lock_bh(&rose_list_lock);
if (rose->device == dev) {
rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
+ /* Mark for destruction so rose_heartbeat_expiry()
+ * cleans up the socket at its next tick rather than
+ * looping forever in ROSE_STATE_0 with no owner.
+ */
+ sock_set_flag(sk, SOCK_DESTROY);
if (rose->neighbour)
rose_neigh_put(rose->neighbour);
netdev_put(rose->device, &rose->dev_tracker);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 24/49] rose: disconnect orphaned STATE_2 sockets when device is gone
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (22 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 23/49] rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 25/49] rose: fix netdev double-hold in rose_make_new() Greg Kroah-Hartman
` (28 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit d4f4cf9f09a3f5fafa8f09110a7c1b5d10f2f261 upstream.
When ax25stop brings down ROSE interfaces, sockets in ROSE_STATE_2
(awaiting CLEAR CONFIRM) whose device pointer is already NULL are not
reached by rose_kill_by_device() and wait for T3 (up to 180s) before
self-cleaning via rose_timer_expiry(). This keeps the rose module
usecount at 1, blocking rmmod for the full T3 duration.
In rose_heartbeat_expiry(), detect ROSE_STATE_2 sockets with no device,
cancel T3, release the neighbour reference, and call rose_disconnect()
+ sock_set_flag(SOCK_DESTROY). The next heartbeat tick (<=5s) then
destroys the socket via the existing ROSE_STATE_0/SOCK_DESTROY path,
allowing clean module unload within 10s instead of up to 180s.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/rose_timer.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -139,6 +139,20 @@ static void rose_heartbeat_expiry(struct
}
break;
+ case ROSE_STATE_2:
+ /* Device gone before CLEAR CONFIRM arrived: stop waiting for T3
+ * and disconnect now instead of blocking rmmod for up to 180s. */
+ if (!rose->device) {
+ rose_stop_timer(sk);
+ if (rose->neighbour) {
+ rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
+ }
+ rose_disconnect(sk, ENETDOWN, -1, -1);
+ sock_set_flag(sk, SOCK_DESTROY);
+ }
+ break;
+
case ROSE_STATE_3:
/*
* Check for the state of the receive buffer.
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 25/49] rose: fix netdev double-hold in rose_make_new()
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (23 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 24/49] rose: disconnect orphaned STATE_2 sockets when device is gone Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 26/49] rose: release netdev ref and destroy orphaned incoming sockets Greg Kroah-Hartman
` (27 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit b9fb21ceb4f0d043767a1eba60786ec84809033b upstream.
rose_make_new() copies orose->device from the listener socket and calls
netdev_hold(), storing the tracker in rose->dev_tracker. The only
caller, rose_rx_call_request(), then overwrites both make_rose->device
and make_rose->dev_tracker with a fresh netdev_hold() for the actual
incoming-call device.
This orphans the tracker allocated by rose_make_new(): it remains in
the device's refcount_tracker list but no pointer exists to free it
via netdev_put(). The result is one spurious outstanding reference per
accepted CALL_REQUEST, visible at rmmod time as:
ref_tracker: netdev@X has 2/2 users at
rose_rx_call_request+0xba3/0x1d50 [rose]
rose_loopback_timer+0x3eb/0x670 [rose]
The second entry is the orphaned tracker from rose_make_new(); the
first is the correctly-managed socket reference from rose_rx_call_request().
Fix: initialise rose->device to NULL in rose_make_new() and let
rose_rx_call_request() -- the sole caller -- assign the correct device
and take the sole netdev_hold() as it already does.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/af_rose.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -631,9 +631,7 @@ static struct sock *rose_make_new(struct
rose->hb = orose->hb;
rose->idle = orose->idle;
rose->defer = orose->defer;
- rose->device = orose->device;
- if (rose->device)
- netdev_hold(rose->device, &rose->dev_tracker, GFP_ATOMIC);
+ rose->device = NULL; /* rose_rx_call_request() sets this */
rose->qbitincl = orose->qbitincl;
return sk;
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 26/49] rose: release netdev ref and destroy orphaned incoming sockets
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (24 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 25/49] rose: fix netdev double-hold in rose_make_new() Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 27/49] rose: drop CALL_REQUEST in loopback timer when device is not running Greg Kroah-Hartman
` (26 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit df12be096302d2c947388acc25764456c7f18cc1 upstream.
Two related cleanup gaps left the module unremovable after a loopback
session:
1. rose_destroy_socket() did not release the device reference. When
an unaccepted incoming socket (created by rose_rx_call_request()) is
destroyed via rose_heartbeat_expiry(), it is removed from rose_list
before rose_kill_by_device() can find it, so the netdev_hold() taken
in rose_rx_call_request() was never matched by netdev_put(). Add the
release at the top of rose_destroy_socket() guarded by a NULL check
so that rose_release() and rose_kill_by_device(), which already call
netdev_put() and set device = NULL, are not affected.
2. rose_heartbeat_expiry() STATE_0 cleanup required TCP_LISTEN in
addition to SOCK_DEAD. Unaccepted incoming sockets are
TCP_ESTABLISHED, so the condition was never true and those sockets
lingered forever, holding the module use count above zero and
blocking rmmod. Drop the TCP_LISTEN restriction: any STATE_0 +
SOCK_DEAD socket is orphaned and should be destroyed.
Together with the earlier rose_make_new() double-hold fix these three
patches allow clean rmmod after loopback sessions.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/af_rose.c | 9 +++++++++
net/rose/rose_timer.c | 9 +++++----
2 files changed, 14 insertions(+), 4 deletions(-)
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -363,6 +363,7 @@ static void rose_destroy_timer(struct ti
*/
void rose_destroy_socket(struct sock *sk)
{
+ struct rose_sock *rose = rose_sk(sk);
struct sk_buff *skb;
rose_remove_socket(sk);
@@ -370,6 +371,14 @@ void rose_destroy_socket(struct sock *sk
rose_stop_idletimer(sk);
rose_stop_timer(sk);
+ /* Drop any device reference not already released by rose_kill_by_device()
+ * or rose_release() -- e.g. incoming sockets that were never accepted.
+ */
+ if (rose->device) {
+ netdev_put(rose->device, &rose->dev_tracker);
+ rose->device = NULL;
+ }
+
rose_clear_queues(sk); /* Flush the queues */
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -128,10 +128,11 @@ static void rose_heartbeat_expiry(struct
}
switch (rose->state) {
case ROSE_STATE_0:
- /* Magic here: If we listen() and a new link dies before it
- is accepted() it isn't 'dead' so doesn't get removed. */
- if (sock_flag(sk, SOCK_DESTROY) ||
- (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
+ /* Destroy any orphaned STATE_0 socket: either explicitly
+ * flagged SOCK_DESTROY, or SOCK_DEAD (covers both unaccepted
+ * incoming connections and listening sockets whose link died).
+ */
+ if (sock_flag(sk, SOCK_DESTROY) || sock_flag(sk, SOCK_DEAD)) {
bh_unlock_sock(sk);
rose_destroy_socket(sk);
sock_put(sk);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 27/49] rose: drop CALL_REQUEST in loopback timer when device is not running
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (25 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 26/49] rose: release netdev ref and destroy orphaned incoming sockets Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 28/49] rose: cancel neighbour timers in rose_neigh_put() before freeing Greg Kroah-Hartman
` (25 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit cf5567a2652e44866eae8987dff4c1ea507680df upstream.
When ax25stop brings down rose0 while the loopback timer has pending
CALL_REQUEST frames, rose_loopback_timer() calls rose_dev_get() and
finds the device still registered (unregister_netdevice waits for
refs to drop), then calls rose_rx_call_request() which takes a
netdev_hold() for the new socket.
But NETDEV_DOWN fires only once: rose_kill_by_device() already ran
before this timer tick, so the new socket is never cleaned up. The
stuck reference prevents unregister_netdevice from completing, and the
orphan socket's timers eventually fire on freed memory (KASAN
slab-use-after-free in __run_timers).
The kernel clears IFF_UP via dev_close() before sending NETDEV_DOWN,
so checking netif_running() after rose_dev_get() is sufficient: if the
device is no longer running, the CALL_REQUEST is silently dropped and
no socket is created. This closes the race without touching the
module-exit path (which already stops the timer via loopback_stopping).
Tested: unregister_netdevice completes immediately after ax25stop with
active loopback connections; no ref_tracker warnings, no KASAN.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/rose_loopback.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/net/rose/rose_loopback.c
+++ b/net/rose/rose_loopback.c
@@ -118,6 +118,16 @@ static void rose_loopback_timer(struct t
kfree_skb(skb);
continue;
}
+ /* rose_kill_by_device() runs on NETDEV_DOWN (IFF_UP cleared)
+ * before the device is unregistered. If we create a new
+ * socket here after that cleanup, the ref never gets released
+ * because NETDEV_DOWN fires only once. Drop the call instead.
+ */
+ if (!netif_running(dev)) {
+ dev_put(dev);
+ kfree_skb(skb);
+ continue;
+ }
if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0)
kfree_skb(skb);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 28/49] rose: cancel neighbour timers in rose_neigh_put() before freeing
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (26 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 27/49] rose: drop CALL_REQUEST in loopback timer when device is not running Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 29/49] rose: clear neighbour pointer in rose_kill_by_device() Greg Kroah-Hartman
` (24 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit 9b222cb1d23ff210975e9df5ebab7b011acb6fad upstream.
rose_neigh_put() kfree()s the neighbour but never cancels its ftimer and
t0timer. Until now every caller that dropped the final reference first
called rose_remove_neigh(), which deletes those timers. The socket
heartbeat reaping path drops the last reference directly, so a neighbour
could be freed with t0timer still armed -- it re-arms itself in
rose_t0timer_expiry() -- leading to a use-after-free write in
enqueue_timer().
Cancel both timers with timer_delete_sync() (the synchronous variant, to
wait out a concurrently running, self-rearming handler) in the
refcount-zero branch of rose_neigh_put().
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/rose.h | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -160,6 +160,18 @@ static inline void rose_neigh_hold(struc
static inline void rose_neigh_put(struct rose_neigh *rose_neigh)
{
if (refcount_dec_and_test(&rose_neigh->use)) {
+ /* We are dropping the last reference, so we are about to free the
+ * neighbour. Its timers may still be armed -- t0timer in particular
+ * re-arms itself in rose_t0timer_expiry(). rose_remove_neigh()
+ * cancels them before its own put, but callers that drop the final
+ * reference without first calling rose_remove_neigh() (the socket
+ * heartbeat reaping path) would otherwise kfree() a neighbour with a
+ * live timer -> use-after-free. timer_delete_sync() (not the async
+ * variant) is required: it waits out a concurrently running handler
+ * and loops until the self-rearming timer stays stopped.
+ */
+ timer_delete_sync(&rose_neigh->ftimer);
+ timer_delete_sync(&rose_neigh->t0timer);
if (rose_neigh->ax25)
ax25_cb_put(rose_neigh->ax25);
kfree(rose_neigh->digipeat);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 29/49] rose: clear neighbour pointer in rose_kill_by_device()
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (27 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 28/49] rose: cancel neighbour timers in rose_neigh_put() before freeing Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 30/49] rose: dont free fd-owned sockets when reaping in the heartbeat Greg Kroah-Hartman
` (23 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit 606e42d195b467480d4d405f8814c48d1651a76a upstream.
rose_kill_by_device() drops the neighbour reference but leaves
rose->neighbour pointing at it, unlike every other rose_neigh_put() site
(see "rose: clear neighbour pointer after rose_neigh_put() in state
machines"). The heartbeat STATE_0 reaping path then puts the same
neighbour a second time, causing a rose_neigh refcount underflow and a
use-after-free.
Set rose->neighbour = NULL after the put, restoring the invariant.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/af_rose.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -216,8 +216,16 @@ start:
* looping forever in ROSE_STATE_0 with no owner.
*/
sock_set_flag(sk, SOCK_DESTROY);
- if (rose->neighbour)
+ if (rose->neighbour) {
rose_neigh_put(rose->neighbour);
+ /* Clear the pointer after dropping the reference, as
+ * every other rose_neigh_put() site does. Otherwise
+ * rose_heartbeat_expiry() (STATE_0 reaping) sees a stale
+ * rose->neighbour and puts it a second time -> rose_neigh
+ * refcount underflow / use-after-free.
+ */
+ rose->neighbour = NULL;
+ }
netdev_put(rose->device, &rose->dev_tracker);
rose->device = NULL;
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 30/49] rose: dont free fd-owned sockets when reaping in the heartbeat
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (28 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 29/49] rose: clear neighbour pointer in rose_kill_by_device() Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 31/49] net: export netif_open for self_test usage Greg Kroah-Hartman
` (22 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bernard Pidoux <bernard.f6bvp@gmail.com>
commit 56576518920edd7b6c3479477d8d490fe2ebdaaa upstream.
The heartbeat reaps orphaned ROSE sockets after their bound device goes
down. A socket still attached to a struct socket (sk->sk_socket != NULL --
e.g. an incoming connection an fpad client has accepted and kept open) is
owned by that userspace fd: rose_release() frees it on close(). Freeing it
from the heartbeat left the fd dangling, so the eventual close() touched
freed memory -- slab-use-after-free in rose_release().
Reap only sockets with sk->sk_socket == NULL (unaccepted incoming
connections and post-close orphans). For an fd-owned socket whose device
went down, disconnect it and fall through to the switch so close() does
the teardown. Also release the neighbour reference held by orphaned
incoming sockets before tearing them down.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rose/rose_timer.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -126,13 +126,68 @@ static void rose_heartbeat_expiry(struct
sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ/20);
goto out;
}
+
+ /* The bound device went down while we still hold a reference on it.
+ * This catches the narrow race where rose_loopback_timer() created a
+ * socket in the window after rose_kill_by_device()'s NETDEV_DOWN sweep
+ * but before rose_insert_socket() -- leaving a STATE_3 socket that no
+ * other branch reaps. A down device means the link is dead, so tear
+ * the socket down regardless of state. rose_destroy_socket() releases
+ * the held netdev reference (rose->device still set).
+ */
+ if (rose->device && !netif_running(rose->device)) {
+ if (rose->neighbour) {
+ rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
+ }
+ rose_disconnect(sk, ENETDOWN, -1, -1);
+
+ /* Only reap the socket if userspace no longer holds it. A socket
+ * still attached to a struct socket (sk->sk_socket != NULL -- e.g.
+ * a connection an fpad client has accepted and kept open) is owned
+ * by that fd: rose_release() will destroy it on close(). Dropping
+ * the last reference here leaves the open fd dangling, so the
+ * eventual close() touches freed memory -> slab-use-after-free in
+ * rose_release(). Unaccepted incoming sockets and post-close
+ * orphans have sk->sk_socket == NULL and stay safe to reap here.
+ */
+ if (!sk->sk_socket) {
+ sock_set_flag(sk, SOCK_DESTROY);
+ bh_unlock_sock(sk);
+ rose_destroy_socket(sk);
+ sock_put(sk);
+ return;
+ }
+
+ /* Owned by userspace: the link is down and the socket is now
+ * disconnected (rose_disconnect() moved it to STATE_0). Fall
+ * through to the switch, which re-arms the heartbeat; the close()
+ * will tear the socket down. */
+ }
+
switch (rose->state) {
case ROSE_STATE_0:
/* Destroy any orphaned STATE_0 socket: either explicitly
* flagged SOCK_DESTROY, or SOCK_DEAD (covers both unaccepted
* incoming connections and listening sockets whose link died).
*/
- if (sock_flag(sk, SOCK_DESTROY) || sock_flag(sk, SOCK_DEAD)) {
+ if ((sock_flag(sk, SOCK_DESTROY) || sock_flag(sk, SOCK_DEAD)) &&
+ !sk->sk_socket) {
+ /* Reap only orphaned sockets (sk->sk_socket == NULL). A
+ * socket still owned by a userspace fd reaches here via the
+ * STATE_2 device-gone branch, which sets SOCK_DESTROY without
+ * knowing about the fd; freeing it would race rose_release()
+ * at close() -> use-after-free. Leave it for close().
+ *
+ * Orphaned incoming sockets (rose_rx_call_request) hold a
+ * neighbour reference; release it before teardown, as the
+ * STATE_2 and device-down branches do. rose_destroy_socket()
+ * does not drop it.
+ */
+ if (rose->neighbour) {
+ rose_neigh_put(rose->neighbour);
+ rose->neighbour = NULL;
+ }
bh_unlock_sock(sk);
rose_destroy_socket(sk);
sock_put(sk);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 31/49] net: export netif_open for self_test usage
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (29 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 30/49] rose: dont free fd-owned sockets when reaping in the heartbeat Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 32/49] net: net_failover: Fix the deadlock in slave register Greg Kroah-Hartman
` (21 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mike Marciniszyn (Meta), Paolo Abeni
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Marciniszyn (Meta) <mike.marciniszyn@gmail.com>
commit 3fdd33697c2be9184668c89ba4f24a5ecbc8ec51 upstream.
dev_open() already is exported, but drivers which use the netdev
instance lock need to use netif_open() instead. netif_close() is
also already exported [1] so this completes the pairing.
This export is required for the following fbnic self tests to
avoid calling ndo_stop() and ndo_open() in favor of the
more appropriate netif_open() and netif_close() that notifies
any listeners that the interface went down to test and is now
coming back up.
Link: https://patch.msgid.link/20250309215851.2003708-1-sdf@fomichev.me [1]
Signed-off-by: Mike Marciniszyn (Meta) <mike.marciniszyn@gmail.com>
Link: https://patch.msgid.link/20260307105847.1438-2-mike.marciniszyn@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/dev.c | 1 +
1 file changed, 1 insertion(+)
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1731,6 +1731,7 @@ int netif_open(struct net_device *dev, s
return ret;
}
+EXPORT_SYMBOL(netif_open);
static void __dev_close_many(struct list_head *head)
{
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 32/49] net: net_failover: Fix the deadlock in slave register
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (30 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 31/49] net: export netif_open for self_test usage Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 33/49] iio: light: veml6075: add bounds check to veml6075_it_ms index Greg Kroah-Hartman
` (20 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Faicker Mo, Jakub Kicinski
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Faicker Mo <faicker.mo@gmail.com>
commit b84c5632c7b31f8910167075a8128cfb9e50fcfe upstream.
There is netdev_lock_ops() before the NETDEV_REGISTER notifier
in register_netdevice(), so use the non-locking functions
in net_failover_slave_register().
failover_slave_register() in failover_existing_slave_register() adds lock
and unlock ops too.
Call Trace:
<TASK>
__schedule+0x30d/0x7a0
schedule+0x27/0x90
schedule_preempt_disabled+0x15/0x30
__mutex_lock.constprop.0+0x538/0x9e0
__mutex_lock_slowpath+0x13/0x20
mutex_lock+0x3b/0x50
dev_set_mtu+0x40/0xe0
net_failover_slave_register+0x24/0x280
failover_slave_register+0x103/0x1b0
failover_event+0x15e/0x210
? dropmon_net_event+0xac/0xe0
notifier_call_chain+0x5e/0xe0
raw_notifier_call_chain+0x16/0x30
call_netdevice_notifiers_info+0x52/0xa0
register_netdevice+0x5f4/0x7c0
register_netdev+0x1e/0x40
_mlx5e_probe+0xe2/0x370 [mlx5_core]
mlx5e_probe+0x59/0x70 [mlx5_core]
? __pfx_mlx5e_probe+0x10/0x10 [mlx5_core]
Fixes: 4c975fd70002 ("net: hold instance lock during NETDEV_REGISTER/UP")
Signed-off-by: Faicker Mo <faicker.mo@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/net_failover.c | 12 ++++++------
net/core/failover.c | 6 +++++-
2 files changed, 11 insertions(+), 7 deletions(-)
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -502,7 +502,7 @@ static int net_failover_slave_register(s
/* Align MTU of slave with failover dev */
orig_mtu = slave_dev->mtu;
- err = dev_set_mtu(slave_dev, failover_dev->mtu);
+ err = netif_set_mtu(slave_dev, failover_dev->mtu);
if (err) {
netdev_err(failover_dev, "unable to change mtu of %s to %u register failed\n",
slave_dev->name, failover_dev->mtu);
@@ -512,11 +512,11 @@ static int net_failover_slave_register(s
dev_hold(slave_dev);
if (netif_running(failover_dev)) {
- err = dev_open(slave_dev, NULL);
+ err = netif_open(slave_dev, NULL);
if (err && (err != -EBUSY)) {
netdev_err(failover_dev, "Opening slave %s failed err:%d\n",
slave_dev->name, err);
- goto err_dev_open;
+ goto err_netif_open;
}
}
@@ -562,10 +562,10 @@ static int net_failover_slave_register(s
err_vlan_add:
dev_uc_unsync(slave_dev, failover_dev);
dev_mc_unsync(slave_dev, failover_dev);
- dev_close(slave_dev);
-err_dev_open:
+ netif_close(slave_dev);
+err_netif_open:
dev_put(slave_dev);
- dev_set_mtu(slave_dev, orig_mtu);
+ netif_set_mtu(slave_dev, orig_mtu);
done:
return err;
}
--- a/net/core/failover.c
+++ b/net/core/failover.c
@@ -12,6 +12,7 @@
#include <uapi/linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <linux/if_vlan.h>
+#include <net/netdev_lock.h>
#include <net/failover.h>
static LIST_HEAD(failover_list);
@@ -221,8 +222,11 @@ failover_existing_slave_register(struct
for_each_netdev(net, dev) {
if (netif_is_failover(dev))
continue;
- if (ether_addr_equal(failover_dev->perm_addr, dev->perm_addr))
+ if (ether_addr_equal(failover_dev->perm_addr, dev->perm_addr)) {
+ netdev_lock_ops(dev);
failover_slave_register(dev);
+ netdev_unlock_ops(dev);
+ }
}
rtnl_unlock();
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 33/49] iio: light: veml6075: add bounds check to veml6075_it_ms index
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (31 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 32/49] net: net_failover: Fix the deadlock in slave register Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 34/49] iio: adc: ti-ads1298: add bounds check to pga_settings index Greg Kroah-Hartman
` (19 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Sam Daly, Javier Carrasco,
Jonathan Cameron
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sam Daly <sam@samdaly.ie>
commit 307dc4240bd41852d9e0912921e298160db1c109 upstream.
veml6075_it_ms has 5 elements but VEML6075_CONF_IT can yield values 0-7.
If it returns a value >= 5, this causes an out-of-bounds array access.
Add a bounds check and return -EINVAL if the index is out of range.
The problem values are reserved so should never be read from the
register. Hence this is hardening against fault device, missprogramming
or bus corruption.
Assisted-by: gkh_clanker_2000
Cc: stable <stable@kernel.org>
Signed-off-by: Sam Daly <sam@samdaly.ie>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Javier Carrasco <javier.carrasco.cruz@gmail.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/iio/light/veml6075.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/iio/light/veml6075.c
+++ b/drivers/iio/light/veml6075.c
@@ -100,7 +100,7 @@ static const struct iio_chan_spec veml60
static int veml6075_request_measurement(struct veml6075_data *data)
{
- int ret, conf, int_time;
+ int ret, conf, int_time, int_index;
ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf);
if (ret < 0)
@@ -117,7 +117,11 @@ static int veml6075_request_measurement(
* time for all possible configurations. Using a 1.50 factor simplifies
* operations and ensures reliability under all circumstances.
*/
- int_time = veml6075_it_ms[FIELD_GET(VEML6075_CONF_IT, conf)];
+ int_index = FIELD_GET(VEML6075_CONF_IT, conf);
+ if (int_index >= ARRAY_SIZE(veml6075_it_ms))
+ return -EINVAL;
+
+ int_time = veml6075_it_ms[int_index];
msleep(int_time + (int_time / 2));
/* shutdown again, data registers are still accessible */
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 34/49] iio: adc: ti-ads1298: add bounds check to pga_settings index
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (32 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 33/49] iio: light: veml6075: add bounds check to veml6075_it_ms index Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 35/49] Input: rmi4 - fix register descriptor address calculation Greg Kroah-Hartman
` (18 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Jonathan Cameron,
David Lechner, Nuno Sá, Andy Shevchenko, Sam Daly
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sam Daly <sam@samdaly.ie>
commit 95e8a48d7a85d4226934020e57815a3316d3a14b upstream.
ads1298_pga_settings has 7 elements but ADS1298_MASK_CH_PGA can yield
values 0-7. If it yields a value >= 7, this causes an out-of-bounds
array access. Add a bounds check and return -EINVAL if the index
is out of range.
Note that the remaining value b111 is reserved so should not be seen
in a correctly functioning system.
Assisted-by: gkh_clanker_2000
Cc: stable <stable@kernel.org>
Cc: Jonathan Cameron <jic23@kernel.org>
Cc: David Lechner <dlechner@baylibre.com>
Cc: "Nuno Sá" <nuno.sa@analog.com>
Cc: Andy Shevchenko <andy@kernel.org>
Signed-off-by: Sam Daly <sam@samdaly.ie>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/iio/adc/ti-ads1298.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/iio/adc/ti-ads1298.c
+++ b/drivers/iio/adc/ti-ads1298.c
@@ -279,6 +279,7 @@ static const u8 ads1298_pga_settings[] =
static int ads1298_get_scale(struct ads1298_private *priv,
int channel, int *val, int *val2)
{
+ unsigned int pga_idx;
int ret;
unsigned int regval;
u8 gain;
@@ -302,7 +303,11 @@ static int ads1298_get_scale(struct ads1
if (ret)
return ret;
- gain = ads1298_pga_settings[FIELD_GET(ADS1298_MASK_CH_PGA, regval)];
+ pga_idx = FIELD_GET(ADS1298_MASK_CH_PGA, regval);
+ if (pga_idx >= ARRAY_SIZE(ads1298_pga_settings))
+ return -EINVAL;
+
+ gain = ads1298_pga_settings[pga_idx];
*val /= gain; /* Full scale is VREF / gain */
*val2 = ADS1298_BITS_PER_SAMPLE - 1; /* Signed, hence the -1 */
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 35/49] Input: rmi4 - fix register descriptor address calculation
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (33 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 34/49] iio: adc: ti-ads1298: add bounds check to pga_settings index Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 36/49] Input: rmi4 - refactor register descriptor parsing Greg Kroah-Hartman
` (17 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dmitry Torokhov
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit a98518e72439fd42cbfe641c2896543cb088e3d1 upstream.
When reading the register descriptor, the base address is incremented by
1 to read the presence register block. However, after reading the
presence register block, the address is incorrectly incremented by only
1 byte (++addr) instead of the actual size of the presence block
(size_presence_reg). This causes the subsequent structure block read to
read from the wrong memory location if the presence block is larger than
1 byte.
Fix this by advancing the address by size_presence_reg.
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Link: https://patch.msgid.link/20260505045952.1570713-1-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -594,7 +594,7 @@ int rmi_read_register_desc(struct rmi_de
ret = rmi_read_block(d, addr, buf, size_presence_reg);
if (ret)
return ret;
- ++addr;
+ addr += size_presence_reg;
if (buf[0] == 0) {
presense_offset = 3;
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 36/49] Input: rmi4 - refactor register descriptor parsing
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (34 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 35/49] Input: rmi4 - fix register descriptor address calculation Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 37/49] Input: rmi4 - fix type overflow in register counts Greg Kroah-Hartman
` (16 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dmitry Torokhov
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit 0adb483fbf2dc43c875cd7550a58b41e92efc52d upstream.
Factor out parsing a register descriptor item from
rmi_read_register_desc() and ensure there are no out-of-bounds accesses.
Use get_unaligned_le16() and get_unaligned_le32() for reading multi-byte
values.
Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Link: https://patch.msgid.link/20260505045952.1570713-2-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_driver.c | 124 ++++++++++++++++++++++++----------------
1 file changed, 76 insertions(+), 48 deletions(-)
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -22,6 +22,7 @@
#include <uapi/linux/input.h>
#include <linux/rmi.h>
#include <linux/export.h>
+#include <linux/unaligned.h>
#include "rmi_bus.h"
#include "rmi_driver.h"
@@ -558,30 +559,74 @@ int rmi_scan_pdt(struct rmi_device *rmi_
return retval < 0 ? retval : 0;
}
+static int rmi_parse_register_desc_item(struct rmi_register_desc_item *item,
+ const u8 *buf, size_t size)
+{
+ unsigned int offset = 0;
+ unsigned int map_offset = 0;
+ int b;
+
+ if (offset >= size)
+ return -EIO;
+
+ item->reg_size = buf[offset++];
+ if (item->reg_size == 0) {
+ if (size - offset < 2)
+ return -EIO;
+ item->reg_size = get_unaligned_le16(&buf[offset]);
+ offset += 2;
+ }
+
+ if (item->reg_size == 0) {
+ if (size - offset < 4)
+ return -EIO;
+ item->reg_size = get_unaligned_le32(&buf[offset]);
+ offset += 4;
+ }
+
+ do {
+ if (offset >= size)
+ return -EIO;
+
+ for (b = 0; b < 7; b++) {
+ if (buf[offset] & BIT(b)) {
+ if (map_offset >= RMI_REG_DESC_SUBPACKET_BITS)
+ return -EIO;
+ __set_bit(map_offset, item->subpacket_map);
+ }
+ ++map_offset;
+ }
+ } while (buf[offset++] & BIT(7));
+
+ item->num_subpackets = bitmap_weight(item->subpacket_map,
+ RMI_REG_DESC_SUBPACKET_BITS);
+
+ return offset;
+}
+
int rmi_read_register_desc(struct rmi_device *d, u16 addr,
- struct rmi_register_descriptor *rdesc)
+ struct rmi_register_descriptor *rdesc)
{
int ret;
u8 size_presence_reg;
u8 buf[35];
- int presense_offset = 1;
- u8 *struct_buf;
- int reg;
- int offset = 0;
- int map_offset = 0;
+ unsigned int presence_offset;
+ unsigned int map_offset;
+ unsigned int offset;
+ unsigned int reg;
int i;
int b;
/*
* The first register of the register descriptor is the size of
- * the register descriptor's presense register.
+ * the register descriptor's presence register.
*/
ret = rmi_read(d, addr, &size_presence_reg);
if (ret)
return ret;
++addr;
- if (size_presence_reg < 0 || size_presence_reg > 35)
+ if (size_presence_reg < 1 || size_presence_reg > 35)
return -EIO;
memset(buf, 0, sizeof(buf));
@@ -597,16 +642,23 @@ int rmi_read_register_desc(struct rmi_de
addr += size_presence_reg;
if (buf[0] == 0) {
- presense_offset = 3;
- rdesc->struct_size = buf[1] | (buf[2] << 8);
+ if (size_presence_reg < 3)
+ return -EIO;
+ presence_offset = 3;
+ rdesc->struct_size = get_unaligned_le16(&buf[1]);
} else {
+ presence_offset = 1;
rdesc->struct_size = buf[0];
}
- for (i = presense_offset; i < size_presence_reg; i++) {
+ map_offset = 0;
+ for (i = presence_offset; i < size_presence_reg; i++) {
for (b = 0; b < 8; b++) {
- if (buf[i] & (0x1 << b))
+ if (buf[i] & BIT(b)) {
+ if (map_offset >= RMI_REG_DESC_PRESENSE_BITS)
+ return -EIO;
bitmap_set(rdesc->presense_map, map_offset, 1);
+ }
++map_offset;
}
}
@@ -626,7 +678,7 @@ int rmi_read_register_desc(struct rmi_de
* I'm not using devm_kzalloc here since it will not be retained
* after exiting this function
*/
- struct_buf = kzalloc(rdesc->struct_size, GFP_KERNEL);
+ u8 *struct_buf __free(kfree) = kzalloc(rdesc->struct_size, GFP_KERNEL);
if (!struct_buf)
return -ENOMEM;
@@ -638,56 +690,32 @@ int rmi_read_register_desc(struct rmi_de
*/
ret = rmi_read_block(d, addr, struct_buf, rdesc->struct_size);
if (ret)
- goto free_struct_buff;
+ return ret;
reg = find_first_bit(rdesc->presense_map, RMI_REG_DESC_PRESENSE_BITS);
+ offset = 0;
for (i = 0; i < rdesc->num_registers; i++) {
struct rmi_register_desc_item *item = &rdesc->registers[i];
- int reg_size = struct_buf[offset];
+ int item_size;
- ++offset;
- if (reg_size == 0) {
- reg_size = struct_buf[offset] |
- (struct_buf[offset + 1] << 8);
- offset += 2;
- }
-
- if (reg_size == 0) {
- reg_size = struct_buf[offset] |
- (struct_buf[offset + 1] << 8) |
- (struct_buf[offset + 2] << 16) |
- (struct_buf[offset + 3] << 24);
- offset += 4;
- }
+ item_size = rmi_parse_register_desc_item(item,
+ &struct_buf[offset],
+ rdesc->struct_size - offset);
+ if (item_size < 0)
+ return item_size;
item->reg = reg;
- item->reg_size = reg_size;
-
- map_offset = 0;
-
- do {
- for (b = 0; b < 7; b++) {
- if (struct_buf[offset] & (0x1 << b))
- bitmap_set(item->subpacket_map,
- map_offset, 1);
- ++map_offset;
- }
- } while (struct_buf[offset++] & 0x80);
-
- item->num_subpackets = bitmap_weight(item->subpacket_map,
- RMI_REG_DESC_SUBPACKET_BITS);
+ offset += item_size;
rmi_dbg(RMI_DEBUG_CORE, &d->dev,
"%s: reg: %d reg size: %ld subpackets: %d\n", __func__,
item->reg, item->reg_size, item->num_subpackets);
reg = find_next_bit(rdesc->presense_map,
- RMI_REG_DESC_PRESENSE_BITS, reg + 1);
+ RMI_REG_DESC_PRESENSE_BITS, reg + 1);
}
-free_struct_buff:
- kfree(struct_buf);
- return ret;
+ return 0;
}
const struct rmi_register_desc_item *rmi_get_register_desc_item(
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 37/49] Input: rmi4 - fix type overflow in register counts
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (35 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 36/49] Input: rmi4 - refactor register descriptor parsing Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 38/49] Input: rmi4 - fix num_subpackets overflow in register descriptor Greg Kroah-Hartman
` (15 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dmitry Torokhov
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit a0a87e441238e07c5f7e3de133ef77a9d4229f01 upstream.
The number of registers in the RMI4 register descriptor is populated
by counting the bits in the presence map using bitmap_weight(). Since
the presence map can contain up to 256 bits (RMI_REG_DESC_PRESENSE_BITS),
storing this count in a u8 can overflow to 0 if all 256 bits are set.
Change the num_registers field in struct rmi_register_descriptor
from u8 to u16 to prevent potential integer overflow and ensure safe
processing of devices reporting large descriptors.
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Link: https://patch.msgid.link/20260505045952.1570713-3-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_driver.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -65,7 +65,7 @@ struct rmi_register_desc_item {
struct rmi_register_descriptor {
unsigned long struct_size;
unsigned long presense_map[BITS_TO_LONGS(RMI_REG_DESC_PRESENSE_BITS)];
- u8 num_registers;
+ u16 num_registers;
struct rmi_register_desc_item *registers;
};
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 38/49] Input: rmi4 - fix num_subpackets overflow in register descriptor
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (36 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 37/49] Input: rmi4 - fix type overflow in register counts Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 39/49] Input: rmi4 - fix memory leak in rmi_set_attn_data() Greg Kroah-Hartman
` (14 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dmitry Torokhov
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit 2b4b482d5c4c23c668b998a7da985aea0fa4a978 upstream.
RMI_REG_DESC_SUBPACKET_BITS is defined as 296 (37 * BITS_PER_BYTE). This
may overflow num_subpackets in struct rmi_register_desc_item which is
defined as a u8.
Fix this by changing the type of num_subpackets to u16.
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Link: https://patch.msgid.link/20260505045952.1570713-4-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_driver.h | 2 +-
drivers/input/rmi4/rmi_f12.c | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -53,7 +53,7 @@ struct pdt_entry {
struct rmi_register_desc_item {
u16 reg;
unsigned long reg_size;
- u8 num_subpackets;
+ u16 num_subpackets;
unsigned long subpacket_map[BITS_TO_LONGS(
RMI_REG_DESC_SUBPACKET_BITS)];
};
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -467,6 +467,13 @@ static int rmi_f12_probe(struct rmi_func
f12->data1 = item;
f12->data1_offset = data_offset;
data_offset += item->reg_size;
+
+ if (item->num_subpackets > 255) {
+ dev_err(&fn->dev, "Too many fingers declared: %d\n",
+ item->num_subpackets);
+ return -EINVAL;
+ }
+
sensor->nbr_fingers = item->num_subpackets;
sensor->report_abs = 1;
sensor->attn_size += item->reg_size;
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 39/49] Input: rmi4 - fix memory leak in rmi_set_attn_data()
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (37 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 38/49] Input: rmi4 - fix num_subpackets overflow in register descriptor Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 40/49] Input: rmi4 - iterative IRQ handler Greg Kroah-Hartman
` (13 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dmitry Torokhov
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit a55a683a8e2bddb5467baab3e597a93022d4ee05 upstream.
kfifo_put() returns 0 if the FIFO is full. In this case, we must
free the memory allocated for the attention data to avoid a leak.
Fixes: b908d3cd812a ("Input: synaptics-rmi4 - allow to add attention data")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Link: https://patch.msgid.link/20260505045952.1570713-5-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_driver.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -183,7 +183,11 @@ void rmi_set_attn_data(struct rmi_device
attn_data.size = size;
attn_data.data = fifo_data;
- kfifo_put(&drvdata->attn_fifo, attn_data);
+ if (!kfifo_put(&drvdata->attn_fifo, attn_data)) {
+ dev_warn_ratelimited(&rmi_dev->dev,
+ "Failed to enqueue attention data, FIFO full\n");
+ kfree(fifo_data);
+ }
}
EXPORT_SYMBOL_GPL(rmi_set_attn_data);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 40/49] Input: rmi4 - iterative IRQ handler
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (38 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 39/49] Input: rmi4 - fix memory leak in rmi_set_attn_data() Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 41/49] Input: rmi4 - fix bit count in bitmap_copy() Greg Kroah-Hartman
` (12 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dmitry Torokhov
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit b6ca982afd0e8fbcbb340092d3c6d3b4a217686c upstream.
The current IRQ handler uses recursion to drain the attention FIFO,
which can lead to stack overflow on deep queues. Convert it to a
loop.
Fixes: b908d3cd812a ("Input: synaptics-rmi4 - allow to add attention data")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Link: https://patch.msgid.link/20260505045952.1570713-6-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_driver.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -198,24 +198,24 @@ static irqreturn_t rmi_irq_fn(int irq, v
struct rmi4_attn_data attn_data = {0};
int ret, count;
- count = kfifo_get(&drvdata->attn_fifo, &attn_data);
- if (count) {
- *(drvdata->irq_status) = attn_data.irq_status;
- drvdata->attn_data = attn_data;
- }
+ do {
+ count = kfifo_get(&drvdata->attn_fifo, &attn_data);
+ if (count) {
+ *drvdata->irq_status = attn_data.irq_status;
+ drvdata->attn_data = attn_data;
+ }
- ret = rmi_process_interrupt_requests(rmi_dev);
- if (ret)
- rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
- "Failed to process interrupt request: %d\n", ret);
+ ret = rmi_process_interrupt_requests(rmi_dev);
+ if (ret)
+ rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
+ "Failed to process interrupt request: %d\n",
+ ret);
- if (count) {
- kfree(attn_data.data);
- drvdata->attn_data.data = NULL;
- }
-
- if (!kfifo_is_empty(&drvdata->attn_fifo))
- return rmi_irq_fn(irq, dev_id);
+ if (count) {
+ kfree(attn_data.data);
+ drvdata->attn_data.data = NULL;
+ }
+ } while (!kfifo_is_empty(&drvdata->attn_fifo));
return IRQ_HANDLED;
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 41/49] Input: rmi4 - fix bit count in bitmap_copy()
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (39 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 40/49] Input: rmi4 - iterative IRQ handler Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 42/49] crypto: qat - remove unused character device and IOCTLs Greg Kroah-Hartman
` (11 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dmitry Torokhov
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit f22dbbcbd1f70ed004a7bf8837e0f0c3cc230b78 upstream.
bitmap_copy() takes number of bits, not bytes (or longs). Correct
the bit count in rmi_driver_set_irq_bits() and
rmi_driver_clear_irq_bits().
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Link: https://patch.msgid.link/20260505045952.1570713-7-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_driver.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -388,9 +388,8 @@ static int rmi_driver_set_irq_bits(struc
__func__);
goto error_unlock;
}
- bitmap_copy(data->current_irq_mask, data->new_irq_mask,
- data->num_of_irq_regs);
+ bitmap_copy(data->current_irq_mask, data->new_irq_mask, data->irq_count);
bitmap_or(data->fn_irq_bits, data->fn_irq_bits, mask, data->irq_count);
error_unlock:
@@ -419,8 +418,8 @@ static int rmi_driver_clear_irq_bits(str
__func__);
goto error_unlock;
}
- bitmap_copy(data->current_irq_mask, data->new_irq_mask,
- data->num_of_irq_regs);
+
+ bitmap_copy(data->current_irq_mask, data->new_irq_mask, data->irq_count);
error_unlock:
mutex_unlock(&data->irq_mutex);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 42/49] crypto: qat - remove unused character device and IOCTLs
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (40 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 41/49] Input: rmi4 - fix bit count in bitmap_copy() Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 43/49] vc_screen: fix null-ptr-deref in vcs_notifier() during concurrent vcs_write Greg Kroah-Hartman
` (10 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Zhi Wang, Bin Yu, MingYu Wang,
Giovanni Cabiddu, Ahsan Atta, Herbert Xu
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
commit d237230728c567297f2f98b425d63156ab2ed17f upstream.
The QAT driver exposes a character device (qat_adf_ctl) with IOCTLs
for device configuration, start, stop, status query and enumeration.
These IOCTLs are not part of any public uAPI header and have no known
in-tree or out-of-tree users. Device lifecycle is already managed via
sysfs.
The ioctl interface also increases the attack surface and is the
subject of a number of bug reports.
Remove the character device, the IOCTL definitions, and the related
data structures (adf_dev_status_info, adf_user_cfg_key_val,
adf_user_cfg_section, adf_user_cfg_ctl_data). Drop the now-unused
adf_cfg_user.h header and strip adf_ctl_drv.c down to the minimal
module_init/module_exit hooks for workqueue, AER, and crypto/compression
algorithm registration.
Clean up leftover dead code that was only reachable from the removed
IOCTL paths: adf_cfg_del_all(), adf_devmgr_verify_id(),
adf_devmgr_get_num_dev(), adf_devmgr_get_dev_by_id(),
adf_get_vf_real_id() and the unused ADF_CFG macros.
Additionally, drop the entry associated to QAT IOCTLs in
ioctl-number.rst.
Cc: stable@vger.kernel.org
Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework")
Reported-by: Zhi Wang <wangzhi@stu.xidian.edu.cn>
Reported-by: Bin Yu <byu@xidian.edu.cn>
Reported-by: MingYu Wang <w15303746062@163.com>
Closes: https://lore.kernel.org/all/61d6d499.ab89.19b9b7f3186.Coremail.wangzhi_xd@stu.xidian.edu.cn/
Link: https://lore.kernel.org/all/20260508034841.256794-1-w15303746062@163.com/
Link: https://lore.kernel.org/all/20260508023542.256299-1-w15303746062@163.com/
Link: https://lore.kernel.org/all/20260504025120.98242-1-w15303746062@163.com/
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Reviewed-by: Ahsan Atta <ahsan.atta@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/userspace-api/ioctl/ioctl-number.rst | 1
drivers/crypto/intel/qat/qat_common/adf_cfg.c | 10
drivers/crypto/intel/qat/qat_common/adf_cfg.h | 1
drivers/crypto/intel/qat/qat_common/adf_cfg_common.h | 32 -
drivers/crypto/intel/qat/qat_common/adf_cfg_user.h | 38 -
drivers/crypto/intel/qat/qat_common/adf_common_drv.h | 3
drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c | 404 -------------------
drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c | 70 ---
8 files changed, 1 insertion(+), 558 deletions(-)
delete mode 100644 drivers/crypto/intel/qat/qat_common/adf_cfg_user.h
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -229,7 +229,6 @@ Code Seq# Include File
<mailto:gregkh@linuxfoundation.org>
'a' all linux/atm*.h, linux/sonet.h ATM on linux
<http://lrcwww.epfl.ch/>
-'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver
'b' 00-FF conflict! bit3 vme host bridge
<mailto:natalia@nikhefk.nikhef.nl>
'b' 00-0F linux/dma-buf.h conflict!
--- a/drivers/crypto/intel/qat/qat_common/adf_cfg.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.c
@@ -103,16 +103,6 @@ static void adf_cfg_section_del_all(stru
static void adf_cfg_section_del_all_except(struct list_head *head,
const char *section_name);
-void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
-{
- struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
-
- down_write(&dev_cfg_data->lock);
- adf_cfg_section_del_all(&dev_cfg_data->sec_list);
- up_write(&dev_cfg_data->lock);
- clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
-}
-
void adf_cfg_del_all_except(struct adf_accel_dev *accel_dev,
const char *section_name)
{
--- a/drivers/crypto/intel/qat/qat_common/adf_cfg.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_cfg.h
@@ -34,7 +34,6 @@ void adf_cfg_dev_remove(struct adf_accel
void adf_cfg_dev_dbgfs_add(struct adf_accel_dev *accel_dev);
void adf_cfg_dev_dbgfs_rm(struct adf_accel_dev *accel_dev);
int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name);
-void adf_cfg_del_all(struct adf_accel_dev *accel_dev);
void adf_cfg_del_all_except(struct adf_accel_dev *accel_dev,
const char *section_name);
int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
--- a/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_common.h
@@ -4,18 +4,11 @@
#define ADF_CFG_COMMON_H_
#include <linux/types.h>
-#include <linux/ioctl.h>
#define ADF_CFG_MAX_STR_LEN 64
#define ADF_CFG_MAX_KEY_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
#define ADF_CFG_MAX_VAL_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
#define ADF_CFG_MAX_SECTION_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
-#define ADF_CFG_BASE_DEC 10
-#define ADF_CFG_BASE_HEX 16
-#define ADF_CFG_ALL_DEVICES 0xFE
-#define ADF_CFG_NO_DEVICE 0xFF
-#define ADF_CFG_AFFINITY_WHATEVER 0xFF
-#define MAX_DEVICE_NAME_SIZE 32
#define ADF_MAX_DEVICES (32 * 32)
#define ADF_DEVS_ARRAY_SIZE BITS_TO_LONGS(ADF_MAX_DEVICES)
@@ -51,29 +44,4 @@ enum adf_device_type {
DEV_420XX,
DEV_6XXX,
};
-
-struct adf_dev_status_info {
- enum adf_device_type type;
- __u32 accel_id;
- __u32 instance_id;
- __u8 num_ae;
- __u8 num_accel;
- __u8 num_logical_accel;
- __u8 banks_per_accel;
- __u8 state;
- __u8 bus;
- __u8 dev;
- __u8 fun;
- char name[MAX_DEVICE_NAME_SIZE];
-};
-
-#define ADF_CTL_IOC_MAGIC 'a'
-#define IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS _IOW(ADF_CTL_IOC_MAGIC, 0, \
- struct adf_user_cfg_ctl_data)
-#define IOCTL_STOP_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 1, \
- struct adf_user_cfg_ctl_data)
-#define IOCTL_START_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 2, \
- struct adf_user_cfg_ctl_data)
-#define IOCTL_STATUS_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 3, __u32)
-#define IOCTL_GET_NUM_DEVICES _IOW(ADF_CTL_IOC_MAGIC, 4, __s32)
#endif
--- a/drivers/crypto/intel/qat/qat_common/adf_cfg_user.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) */
-/* Copyright(c) 2014 - 2020 Intel Corporation */
-#ifndef ADF_CFG_USER_H_
-#define ADF_CFG_USER_H_
-
-#include "adf_cfg_common.h"
-#include "adf_cfg_strings.h"
-
-struct adf_user_cfg_key_val {
- char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
- char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
- union {
- struct adf_user_cfg_key_val *next;
- __u64 padding3;
- };
- enum adf_cfg_val_type type;
-} __packed;
-
-struct adf_user_cfg_section {
- char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES];
- union {
- struct adf_user_cfg_key_val *params;
- __u64 padding1;
- };
- union {
- struct adf_user_cfg_section *next;
- __u64 padding3;
- };
-} __packed;
-
-struct adf_user_cfg_ctl_data {
- union {
- struct adf_user_cfg_section *config_section;
- __u64 padding;
- };
- __u8 device_id;
-} __packed;
-#endif
--- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
+++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h
@@ -68,10 +68,7 @@ int adf_devmgr_add_dev(struct adf_accel_
void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev,
struct adf_accel_dev *pf);
struct list_head *adf_devmgr_get_head(void);
-struct adf_accel_dev *adf_devmgr_get_dev_by_id(u32 id);
struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev);
-int adf_devmgr_verify_id(u32 id);
-void adf_devmgr_get_num_dev(u32 *num);
int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev);
int adf_dev_started(struct adf_accel_dev *accel_dev);
int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev);
--- a/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c
@@ -2,410 +2,13 @@
/* Copyright(c) 2014 - 2020 Intel Corporation */
#include <crypto/algapi.h>
+#include <linux/errno.h>
#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/bitops.h>
-#include <linux/pci.h>
-#include <linux/cdev.h>
-#include <linux/uaccess.h>
-#include "adf_accel_devices.h"
#include "adf_common_drv.h"
-#include "adf_cfg.h"
-#include "adf_cfg_common.h"
-#include "adf_cfg_user.h"
-
-#define ADF_CFG_MAX_SECTION 512
-#define ADF_CFG_MAX_KEY_VAL 256
-
-#define DEVICE_NAME "qat_adf_ctl"
-
-static DEFINE_MUTEX(adf_ctl_lock);
-static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
-
-static const struct file_operations adf_ctl_ops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = adf_ctl_ioctl,
- .compat_ioctl = compat_ptr_ioctl,
-};
-
-static const struct class adf_ctl_class = {
- .name = DEVICE_NAME,
-};
-
-struct adf_ctl_drv_info {
- unsigned int major;
- struct cdev drv_cdev;
-};
-
-static struct adf_ctl_drv_info adf_ctl_drv;
-
-static void adf_chr_drv_destroy(void)
-{
- device_destroy(&adf_ctl_class, MKDEV(adf_ctl_drv.major, 0));
- cdev_del(&adf_ctl_drv.drv_cdev);
- class_unregister(&adf_ctl_class);
- unregister_chrdev_region(MKDEV(adf_ctl_drv.major, 0), 1);
-}
-
-static int adf_chr_drv_create(void)
-{
- dev_t dev_id;
- struct device *drv_device;
- int ret;
-
- if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME)) {
- pr_err("QAT: unable to allocate chrdev region\n");
- return -EFAULT;
- }
-
- ret = class_register(&adf_ctl_class);
- if (ret)
- goto err_chrdev_unreg;
-
- adf_ctl_drv.major = MAJOR(dev_id);
- cdev_init(&adf_ctl_drv.drv_cdev, &adf_ctl_ops);
- if (cdev_add(&adf_ctl_drv.drv_cdev, dev_id, 1)) {
- pr_err("QAT: cdev add failed\n");
- goto err_class_destr;
- }
-
- drv_device = device_create(&adf_ctl_class, NULL,
- MKDEV(adf_ctl_drv.major, 0),
- NULL, DEVICE_NAME);
- if (IS_ERR(drv_device)) {
- pr_err("QAT: failed to create device\n");
- goto err_cdev_del;
- }
- return 0;
-err_cdev_del:
- cdev_del(&adf_ctl_drv.drv_cdev);
-err_class_destr:
- class_unregister(&adf_ctl_class);
-err_chrdev_unreg:
- unregister_chrdev_region(dev_id, 1);
- return -EFAULT;
-}
-
-static struct adf_user_cfg_ctl_data *adf_ctl_alloc_resources(unsigned long arg)
-{
- struct adf_user_cfg_ctl_data *cfg_data;
-
- cfg_data = memdup_user((void __user *)arg, sizeof(*cfg_data));
- if (IS_ERR(cfg_data))
- pr_err("QAT: failed to copy from user cfg_data.\n");
- return cfg_data;
-}
-
-static int adf_add_key_value_data(struct adf_accel_dev *accel_dev,
- const char *section,
- const struct adf_user_cfg_key_val *key_val)
-{
- if (key_val->type == ADF_HEX) {
- long *ptr = (long *)key_val->val;
- long val = *ptr;
-
- if (adf_cfg_add_key_value_param(accel_dev, section,
- key_val->key, (void *)val,
- key_val->type)) {
- dev_err(&GET_DEV(accel_dev),
- "failed to add hex keyvalue.\n");
- return -EFAULT;
- }
- } else {
- if (adf_cfg_add_key_value_param(accel_dev, section,
- key_val->key, key_val->val,
- key_val->type)) {
- dev_err(&GET_DEV(accel_dev),
- "failed to add keyvalue.\n");
- return -EFAULT;
- }
- }
- return 0;
-}
-
-static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev,
- struct adf_user_cfg_ctl_data *ctl_data)
-{
- struct adf_user_cfg_key_val key_val;
- struct adf_user_cfg_key_val *params_head;
- struct adf_user_cfg_section section, *section_head;
- int i, j;
-
- section_head = ctl_data->config_section;
-
- for (i = 0; section_head && i < ADF_CFG_MAX_SECTION; i++) {
- if (copy_from_user(§ion, (void __user *)section_head,
- sizeof(*section_head))) {
- dev_err(&GET_DEV(accel_dev),
- "failed to copy section info\n");
- goto out_err;
- }
-
- if (adf_cfg_section_add(accel_dev, section.name)) {
- dev_err(&GET_DEV(accel_dev),
- "failed to add section.\n");
- goto out_err;
- }
-
- params_head = section.params;
-
- for (j = 0; params_head && j < ADF_CFG_MAX_KEY_VAL; j++) {
- if (copy_from_user(&key_val, (void __user *)params_head,
- sizeof(key_val))) {
- dev_err(&GET_DEV(accel_dev),
- "Failed to copy keyvalue.\n");
- goto out_err;
- }
- if (adf_add_key_value_data(accel_dev, section.name,
- &key_val)) {
- goto out_err;
- }
- params_head = key_val.next;
- }
- section_head = section.next;
- }
- return 0;
-out_err:
- adf_cfg_del_all(accel_dev);
- return -EFAULT;
-}
-
-static int adf_ctl_ioctl_dev_config(struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- struct adf_user_cfg_ctl_data *ctl_data;
- struct adf_accel_dev *accel_dev;
- int ret = 0;
-
- ctl_data = adf_ctl_alloc_resources(arg);
- if (IS_ERR(ctl_data))
- return PTR_ERR(ctl_data);
-
- accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
- if (!accel_dev) {
- ret = -EFAULT;
- goto out;
- }
-
- if (adf_dev_started(accel_dev)) {
- ret = -EFAULT;
- goto out;
- }
-
- if (adf_copy_key_value_data(accel_dev, ctl_data)) {
- ret = -EFAULT;
- goto out;
- }
- set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
-out:
- kfree(ctl_data);
- return ret;
-}
-
-static int adf_ctl_is_device_in_use(int id)
-{
- struct adf_accel_dev *dev;
-
- list_for_each_entry(dev, adf_devmgr_get_head(), list) {
- if (id == dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
- if (adf_devmgr_in_reset(dev) || adf_dev_in_use(dev)) {
- dev_info(&GET_DEV(dev),
- "device qat_dev%d is busy\n",
- dev->accel_id);
- return -EBUSY;
- }
- }
- }
- return 0;
-}
-
-static void adf_ctl_stop_devices(u32 id)
-{
- struct adf_accel_dev *accel_dev;
-
- list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
- if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
- if (!adf_dev_started(accel_dev))
- continue;
-
- /* First stop all VFs */
- if (!accel_dev->is_vf)
- continue;
-
- adf_dev_down(accel_dev);
- }
- }
-
- list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
- if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
- if (!adf_dev_started(accel_dev))
- continue;
-
- adf_dev_down(accel_dev);
- }
- }
-}
-
-static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- int ret;
- struct adf_user_cfg_ctl_data *ctl_data;
-
- ctl_data = adf_ctl_alloc_resources(arg);
- if (IS_ERR(ctl_data))
- return PTR_ERR(ctl_data);
-
- if (adf_devmgr_verify_id(ctl_data->device_id)) {
- pr_err("QAT: Device %d not found\n", ctl_data->device_id);
- ret = -ENODEV;
- goto out;
- }
-
- ret = adf_ctl_is_device_in_use(ctl_data->device_id);
- if (ret)
- goto out;
-
- if (ctl_data->device_id == ADF_CFG_ALL_DEVICES)
- pr_info("QAT: Stopping all acceleration devices.\n");
- else
- pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
- ctl_data->device_id);
-
- adf_ctl_stop_devices(ctl_data->device_id);
-
-out:
- kfree(ctl_data);
- return ret;
-}
-
-static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- int ret;
- struct adf_user_cfg_ctl_data *ctl_data;
- struct adf_accel_dev *accel_dev;
-
- ctl_data = adf_ctl_alloc_resources(arg);
- if (IS_ERR(ctl_data))
- return PTR_ERR(ctl_data);
-
- ret = -ENODEV;
- accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
- if (!accel_dev)
- goto out;
-
- dev_info(&GET_DEV(accel_dev),
- "Starting acceleration device qat_dev%d.\n",
- ctl_data->device_id);
-
- ret = adf_dev_up(accel_dev, false);
-
- if (ret) {
- dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
- ctl_data->device_id);
- adf_dev_down(accel_dev);
- }
-out:
- kfree(ctl_data);
- return ret;
-}
-
-static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- u32 num_devices = 0;
-
- adf_devmgr_get_num_dev(&num_devices);
- if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices)))
- return -EFAULT;
-
- return 0;
-}
-
-static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- struct adf_hw_device_data *hw_data;
- struct adf_dev_status_info dev_info;
- struct adf_accel_dev *accel_dev;
-
- if (copy_from_user(&dev_info, (void __user *)arg,
- sizeof(struct adf_dev_status_info))) {
- pr_err("QAT: failed to copy from user.\n");
- return -EFAULT;
- }
-
- accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
- if (!accel_dev)
- return -ENODEV;
-
- hw_data = accel_dev->hw_device;
- dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
- dev_info.num_ae = hw_data->get_num_aes(hw_data);
- dev_info.num_accel = hw_data->get_num_accels(hw_data);
- dev_info.num_logical_accel = hw_data->num_logical_accel;
- dev_info.banks_per_accel = hw_data->num_banks
- / hw_data->num_logical_accel;
- strscpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
- dev_info.instance_id = hw_data->instance_id;
- dev_info.type = hw_data->dev_class->type;
- dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
- dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn);
- dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn);
-
- if (copy_to_user((void __user *)arg, &dev_info,
- sizeof(struct adf_dev_status_info))) {
- dev_err(&GET_DEV(accel_dev), "failed to copy status.\n");
- return -EFAULT;
- }
- return 0;
-}
-
-static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-{
- int ret;
-
- if (mutex_lock_interruptible(&adf_ctl_lock))
- return -EFAULT;
-
- switch (cmd) {
- case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS:
- ret = adf_ctl_ioctl_dev_config(fp, cmd, arg);
- break;
-
- case IOCTL_STOP_ACCEL_DEV:
- ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg);
- break;
-
- case IOCTL_START_ACCEL_DEV:
- ret = adf_ctl_ioctl_dev_start(fp, cmd, arg);
- break;
-
- case IOCTL_GET_NUM_DEVICES:
- ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg);
- break;
-
- case IOCTL_STATUS_ACCEL_DEV:
- ret = adf_ctl_ioctl_get_status(fp, cmd, arg);
- break;
- default:
- pr_err_ratelimited("QAT: Invalid ioctl %d\n", cmd);
- ret = -EFAULT;
- break;
- }
- mutex_unlock(&adf_ctl_lock);
- return ret;
-}
static int __init adf_register_ctl_device_driver(void)
{
- if (adf_chr_drv_create())
- goto err_chr_dev;
-
if (adf_init_misc_wq())
goto err_misc_wq;
@@ -437,15 +40,11 @@ err_pf_wq:
err_aer:
adf_exit_misc_wq();
err_misc_wq:
- adf_chr_drv_destroy();
-err_chr_dev:
- mutex_destroy(&adf_ctl_lock);
return -EFAULT;
}
static void __exit adf_unregister_ctl_device_driver(void)
{
- adf_chr_drv_destroy();
adf_exit_misc_wq();
adf_exit_aer();
adf_exit_vf_wq();
@@ -453,7 +52,6 @@ static void __exit adf_unregister_ctl_de
qat_crypto_unregister();
qat_compression_unregister();
adf_clean_vf_map(false);
- mutex_destroy(&adf_ctl_lock);
}
module_init(adf_register_ctl_device_driver);
--- a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c
@@ -45,19 +45,6 @@ static struct vf_id_map *adf_find_vf(u32
return NULL;
}
-static int adf_get_vf_real_id(u32 fake)
-{
- struct list_head *itr;
-
- list_for_each(itr, &vfs_table) {
- struct vf_id_map *ptr =
- list_entry(itr, struct vf_id_map, list);
- if (ptr->fake_id == fake)
- return ptr->id;
- }
- return -1;
-}
-
/**
* adf_clean_vf_map() - Cleans VF id mappings
* @vf: flag indicating whether mappings is cleaned
@@ -304,63 +291,6 @@ struct adf_accel_dev *adf_devmgr_pci_to_
}
EXPORT_SYMBOL_GPL(adf_devmgr_pci_to_accel_dev);
-struct adf_accel_dev *adf_devmgr_get_dev_by_id(u32 id)
-{
- struct list_head *itr;
- int real_id;
-
- mutex_lock(&table_lock);
- real_id = adf_get_vf_real_id(id);
- if (real_id < 0)
- goto unlock;
-
- id = real_id;
-
- list_for_each(itr, &accel_table) {
- struct adf_accel_dev *ptr =
- list_entry(itr, struct adf_accel_dev, list);
- if (ptr->accel_id == id) {
- mutex_unlock(&table_lock);
- return ptr;
- }
- }
-unlock:
- mutex_unlock(&table_lock);
- return NULL;
-}
-
-int adf_devmgr_verify_id(u32 id)
-{
- if (id == ADF_CFG_ALL_DEVICES)
- return 0;
-
- if (adf_devmgr_get_dev_by_id(id))
- return 0;
-
- return -ENODEV;
-}
-
-static int adf_get_num_dettached_vfs(void)
-{
- struct list_head *itr;
- int vfs = 0;
-
- mutex_lock(&table_lock);
- list_for_each(itr, &vfs_table) {
- struct vf_id_map *ptr =
- list_entry(itr, struct vf_id_map, list);
- if (ptr->bdf != ~0 && !ptr->attached)
- vfs++;
- }
- mutex_unlock(&table_lock);
- return vfs;
-}
-
-void adf_devmgr_get_num_dev(u32 *num)
-{
- *num = num_devices - adf_get_num_dettached_vfs();
-}
-
/**
* adf_dev_in_use() - Check whether accel_dev is currently in use
* @accel_dev: Pointer to acceleration device.
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 43/49] vc_screen: fix null-ptr-deref in vcs_notifier() during concurrent vcs_write
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (41 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 42/49] crypto: qat - remove unused character device and IOCTLs Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 44/49] serial: qcom_geni: Fix RX DMA stall when SE_DMA_RX_LEN_IN is zero Greg Kroah-Hartman
` (9 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Yi Yang, Jiri Slaby
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yi Yang <yiyang13@huawei.com>
commit a287620312dc6dcb9a093417a0e589bf30fcf38a upstream.
A KASAN null-ptr-deref was observed in vcs_notifier():
BUG: KASAN: null-ptr-deref in vcs_notifier+0x98/0x130
Read of size 2 at addr qmp_cmd_name: qmp_capabilities, arguments: {}
The issue is a race condition in vcs_write(). When the console_lock is
temporarily dropped (to copy data from userspace), the vc_data pointer
obtained from vcs_vc() may become stale. After re-acquiring the lock,
vcs_vc() is called again to re-validate the pointer. If the vc has been
deallocated in the meantime, vcs_vc() returns NULL, and the while loop
breaks (with written > 0). However, after the loop, vcs_scr_updated(vc)
is still called with the now-NULL vc pointer, leading to a null pointer
dereference in the notifier chain (vcs_notifier dereferences param->vc).
Fix this by adding a NULL check for vc before calling vcs_scr_updated().
Fixes: 8fb9ea65c9d1 ("vc_screen: reload load of struct vc_data pointer in vcs_write() to avoid UAF")
Cc: stable@vger.kernel.org
Signed-off-by: Yi Yang <yiyang13@huawei.com>
Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
Link: https://patch.msgid.link/20260604060734.2914976-1-yiyang13@huawei.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/vt/vc_screen.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/tty/vt/vc_screen.c
+++ b/drivers/tty/vt/vc_screen.c
@@ -686,7 +686,7 @@ vcs_write(struct file *file, const char
}
*ppos += written;
ret = written;
- if (written)
+ if (written && vc)
vcs_scr_updated(vc);
return ret;
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 44/49] serial: qcom_geni: Fix RX DMA stall when SE_DMA_RX_LEN_IN is zero
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (42 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 43/49] vc_screen: fix null-ptr-deref in vcs_notifier() during concurrent vcs_write Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 45/49] serial: 8250_dw: unregister 8250 port if clk_notifier_register() fails Greg Kroah-Hartman
` (8 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bartosz Golaszewski, Viken Dadhaniya
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
commit b93062b6d8a1b2d9bad235cac25558a909819026 upstream.
In qcom_geni_serial_handle_rx_dma(), geni_se_rx_dma_unprep() clears
port->rx_dma_addr before SE_DMA_RX_LEN_IN is read. If the register is zero,
for example when the RX stale counter fires on an idle line, the handler
returns without calling geni_se_rx_dma_prep().
The next RX DMA interrupt then hits the !port->rx_dma_addr guard and
returns immediately, so the RX DMA buffer is never rearmed and later input
is lost.
Keep the handler on the rearm path when rx_in is zero. Warn about the
unexpected zero-length DMA completion, skip received-data handling, and
always call geni_se_rx_dma_prep().
Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA")
Cc: stable@vger.kernel.org
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Link: https://patch.msgid.link/20260528-serial-rx-0-byte-fix-v2-1-b4195cfe342f@oss.qualcomm.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/qcom_geni_serial.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -904,12 +904,9 @@ static void qcom_geni_serial_handle_rx_d
port->rx_dma_addr = 0;
rx_in = readl(uport->membase + SE_DMA_RX_LEN_IN);
- if (!rx_in) {
- dev_warn(uport->dev, "serial engine reports 0 RX bytes in!\n");
- return;
- }
-
- if (!drop)
+ if (!rx_in)
+ dev_warn_ratelimited(uport->dev, "serial engine reports 0 RX bytes in!\n");
+ else if (!drop)
handle_rx_uart(uport, rx_in);
ret = geni_se_rx_dma_prep(&port->se, port->rx_buf,
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 45/49] serial: 8250_dw: unregister 8250 port if clk_notifier_register() fails
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (43 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 44/49] serial: qcom_geni: Fix RX DMA stall when SE_DMA_RX_LEN_IN is zero Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 46/49] drivers/base/memory: set mem->altmap after successful device registration Greg Kroah-Hartman
` (7 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Stepan Ionichev, Andy Shevchenko
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stepan Ionichev <sozdayvek@gmail.com>
commit 10fc708b4de7f86002d2d735a2dbf3b5b7f65692 upstream.
dw8250_probe() registers the 8250 port via serial8250_register_8250_port()
and then, if the device has a clock, registers a clock notifier. If
clk_notifier_register() fails, probe returns the error but leaves the
8250 port registered. The matching serial8250_unregister_port() lives
in dw8250_remove(), which is not called when probe fails, so the port
slot stays occupied until the device is rebound or the system is
rebooted. The devm-allocated driver data is freed while the port still
references it (via the saved private_data and serial_in/serial_out
callbacks), so any access to that port slot before a rebind is a
use-after-free hazard.
Unregister the port on the clk_notifier_register() error path.
Fixes: cc816969d7b5 ("serial: 8250_dw: Fix common clocks usage race condition")
Cc: stable@vger.kernel.org
Signed-off-by: Stepan Ionichev <sozdayvek@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20260514143746.23671-2-sozdayvek@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/8250/8250_dw.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -850,8 +850,10 @@ static int dw8250_probe(struct platform_
*/
if (data->clk) {
err = clk_notifier_register(data->clk, &data->clk_notifier);
- if (err)
+ if (err) {
+ serial8250_unregister_port(data->data.line);
return dev_err_probe(dev, err, "Failed to set the clock notifier\n");
+ }
queue_work(system_dfl_wq, &data->clk_work);
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 46/49] drivers/base/memory: set mem->altmap after successful device registration
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (44 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 45/49] serial: 8250_dw: unregister 8250 port if clk_notifier_register() fails Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:03 ` [PATCH 7.0 47/49] ksmbd: reject non-VALID session in compound request branch Greg Kroah-Hartman
` (6 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Georgi Djakov, Oscar Salvador (SUSE),
Vishal Verma, Mike Rapoport, Richard Cheng, David Hildenbrand,
Georgi Djakov, Rafael J. Wysocki, Andrew Morton
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Georgi Djakov <georgi.djakov@oss.qualcomm.com>
commit a2b8d7827f48ee54a686cb80e4a1d0ff954ec42a upstream.
If __add_memory_block() fails at xa_store() (under memory pressure for
example), device_unregister() is called, which eventually triggers
memory_block_release() with mem->altmap still set, causing a
WARN_ON(mem->altmap). This was triggered by modifying virtio-mem driver.
Fix this by delaying the assignment of mem->altmap until after
__add_memory_block() has succeeded.
Link: https://lore.kernel.org/20260514092657.3057141-1-georgi.djakov@oss.qualcomm.com
Fixes: 1a8c64e11043 ("mm/memory_hotplug: embed vmem_altmap details in memory block")
Signed-off-by: Georgi Djakov <georgi.djakov@oss.qualcomm.com>
Acked-by: Oscar Salvador (SUSE) <osalvador@kernel.org>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Richard Cheng <icheng@nvidia.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: Georgi Djakov <djakov@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/base/memory.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -807,7 +807,6 @@ static int add_memory_block(unsigned lon
mem->start_section_nr = block_id * sections_per_block;
mem->state = state;
mem->nid = nid;
- mem->altmap = altmap;
INIT_LIST_HEAD(&mem->group_next);
#ifndef CONFIG_NUMA
@@ -825,6 +824,8 @@ static int add_memory_block(unsigned lon
if (ret)
return ret;
+ mem->altmap = altmap;
+
if (group) {
mem->group = group;
list_add(&mem->group_next, &group->memory_blocks);
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 47/49] ksmbd: reject non-VALID session in compound request branch
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (45 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 46/49] drivers/base/memory: set mem->altmap after successful device registration Greg Kroah-Hartman
@ 2026-06-25 13:03 ` Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.0 48/49] media: vidtv: fix NULL pointer dereference in vidtv_mux_push_si Greg Kroah-Hartman
` (5 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:03 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Gil Portnoy, Namjae Jeon,
Steve French
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gil Portnoy <dddhkts1@gmail.com>
commit 609ca17d869d04ba249e32cdcbf13c0b1c66f43c upstream.
smb2_check_user_session() takes a shortcut for any operation that is not
the first in a COMPOUND request: it reuses work->sess (the session bound by
the first operation) and validates only the SessionId, then returns
"valid". It never re-checks work->sess->state == SMB2_SESSION_VALID, and a
SessionId of 0xFFFFFFFFFFFFFFFF (ULLONG_MAX, the MS-SMB2 related-operation
value) skips even the id comparison. The standalone path
(ksmbd_session_lookup_all() plus the SESSION_SETUP state machine) does
enforce the VALID state; the compound branch bypasses all of it.
A SESSION_SETUP carrying only an NTLM Type-1 (NtLmNegotiate) blob publishes
a fresh SMB2_SESSION_IN_PROGRESS session whose sess->user is still NULL
(->user is assigned later, by ntlm_authenticate()). Used as operation 1 of
a COMPOUND with operation 2 = TREE_CONNECT (related, SessionId=ULLONG_MAX,
\\host\IPC$), the tree-connect then runs on that IN_PROGRESS session and
reaches ksmbd_ipc_tree_connect_request(), which dereferences
user_name(sess->user) with sess->user == NULL (transport_ipc.c:687/701/704)
-> remote NULL-pointer dereference and a kernel Oops that wedges the ksmbd
worker for all clients.
Reject any non-first compound operation that lands on a session which is
not SMB2_SESSION_VALID, mirroring the validity the standalone lookup path
enforces. SESSION_SETUP itself legitimately runs on an IN_PROGRESS session,
but it is never carried as a non-first compound operation, so multi-leg
authentication is unaffected by this check.
Fixes: 5005bcb42191 ("ksmbd: validate session id and tree id in the compound request")
Cc: stable@vger.kernel.org
Signed-off-by: Gil Portnoy <dddhkts1@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/smb/server/smb2pdu.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -614,6 +614,11 @@ int smb2_check_user_session(struct ksmbd
sess_id, work->sess->id);
return -EINVAL;
}
+ if (work->sess->state != SMB2_SESSION_VALID) {
+ pr_err("compound request on a non-valid session (state %d)\n",
+ work->sess->state);
+ return -EINVAL;
+ }
return 1;
}
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 48/49] media: vidtv: fix NULL pointer dereference in vidtv_mux_push_si
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (46 preceding siblings ...)
2026-06-25 13:03 ` [PATCH 7.0 47/49] ksmbd: reject non-VALID session in compound request branch Greg Kroah-Hartman
@ 2026-06-25 13:04 ` Greg Kroah-Hartman
2026-06-25 13:04 ` [PATCH 7.0 49/49] virtiofs: fix UAF on submount umount Greg Kroah-Hartman
` (4 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:04 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+814c351d094f4f1a1b86,
Ruslan Valiyev, Hans Verkuil
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruslan Valiyev <linuxoid@gmail.com>
commit 7d8bf3d8f91073f4db347ed3aa6302b56107499c upstream.
syzbot reported a general protection fault in
vidtv_psi_ts_psi_write_into [1].
vidtv_mux_get_pid_ctx() can return NULL, but vidtv_mux_push_si() does
not check for this before dereferencing the returned pointer to access
the continuity counter. This leads to a general protection fault when
accessing a near-NULL address.
The root cause is that vidtv_mux_pid_ctx_init() does not check the
return value of vidtv_mux_create_pid_ctx_once() for PMT section PIDs.
If the allocation fails, the PID context is never created, but init
returns success. The subsequent vidtv_mux_push_si() call then gets
NULL from vidtv_mux_get_pid_ctx() and crashes.
Fix both the root cause (add error check in vidtv_mux_pid_ctx_init
for PMT PIDs) and add defensive NULL checks in vidtv_mux_push_si for
all vidtv_mux_get_pid_ctx() calls.
[1]
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
Workqueue: events vidtv_mux_tick
RIP: 0010:vidtv_psi_ts_psi_write_into+0x54a/0xbc0 drivers/media/test-drivers/vidtv/vidtv_psi.c:197
Call Trace:
<TASK>
vidtv_psi_table_header_write_into drivers/media/test-drivers/vidtv/vidtv_psi.c:799 [inline]
vidtv_psi_pmt_write_into+0x3b2/0xa70 drivers/media/test-drivers/vidtv/vidtv_psi.c:1231
vidtv_mux_push_si+0x932/0xe80 drivers/media/test-drivers/vidtv/vidtv_mux.c:196
vidtv_mux_tick+0xe9b/0x1480 drivers/media/test-drivers/vidtv/vidtv_mux.c:408
Fixes: f90cf6079bf67 ("media: vidtv: add a bridge driver")
Cc: stable@vger.kernel.org
Reported-by: syzbot+814c351d094f4f1a1b86@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=814c351d094f4f1a1b86
Signed-off-by: Ruslan Valiyev <linuxoid@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/test-drivers/vidtv/vidtv_mux.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/media/test-drivers/vidtv/vidtv_mux.c
+++ b/drivers/media/test-drivers/vidtv/vidtv_mux.c
@@ -101,7 +101,8 @@ static int vidtv_mux_pid_ctx_init(struct
/* add a ctx for all PMT sections */
while (p) {
pid = vidtv_psi_get_pat_program_pid(p);
- vidtv_mux_create_pid_ctx_once(m, pid);
+ if (!vidtv_mux_create_pid_ctx_once(m, pid))
+ goto free;
p = p->next;
}
@@ -170,6 +171,9 @@ static u32 vidtv_mux_push_si(struct vidt
nit_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_NIT_PID);
eit_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_EIT_PID);
+ if (!pat_ctx || !sdt_ctx || !nit_ctx || !eit_ctx)
+ return 0;
+
pat_args.offset = m->mux_buf_offset;
pat_args.continuity_counter = &pat_ctx->cc;
@@ -186,6 +190,8 @@ static u32 vidtv_mux_push_si(struct vidt
}
pmt_ctx = vidtv_mux_get_pid_ctx(m, pmt_pid);
+ if (!pmt_ctx)
+ continue;
pmt_args.offset = m->mux_buf_offset;
pmt_args.pmt = m->si.pmt_secs[i];
^ permalink raw reply [flat|nested] 54+ messages in thread* [PATCH 7.0 49/49] virtiofs: fix UAF on submount umount
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (47 preceding siblings ...)
2026-06-25 13:04 ` [PATCH 7.0 48/49] media: vidtv: fix NULL pointer dereference in vidtv_mux_push_si Greg Kroah-Hartman
@ 2026-06-25 13:04 ` Greg Kroah-Hartman
2026-06-25 13:44 ` [PATCH 7.0 00/49] 7.0.14-rc1 review Florian Fainelli
` (3 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Greg Kroah-Hartman @ 2026-06-25 13:04 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Aurélien Bombo, Zhihao Cheng,
Greg Kurz, Miklos Szeredi
7.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miklos Szeredi <mszeredi@redhat.com>
commit 06b41351779e9289e8785694ade9042ae85e41ea upstream.
iput() called from fuse_release_end() can Oops if the super block has
already been destroyed. Normally this is prevented by waiting for
num_waiting to go down to zero before commencing with super block shutdown.
This only works, however, for the last submount instance, as the wait
counter is per connection, not per superblock.
Revert to using synchronous release requests for the auto_submounts case,
which is virtiofs only at this time.
Reported-by: Aurélien Bombo <abombo@microsoft.com>
Reported-by: Zhihao Cheng <chengzhihao1@huawei.com>
Cc: Greg Kurz <gkurz@redhat.com>
Closes: https://github.com/kata-containers/kata-containers/issues/12589
Fixes: 26e5c67deb2e ("fuse: fix livelock in synchronous file put from fuseblk workers")
Cc: stable@vger.kernel.org
Reviewed-by: Greg Kurz <gkurz@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/fuse/file.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -374,8 +374,14 @@ void fuse_file_release(struct inode *ino
* aio and closes the fd before the aio completes. Since aio takes its
* own ref to the file, the IO completion has to drop the ref, which is
* how the fuse server can end up closing its clients' files.
+ *
+ * Exception is virtio-fs, which is not affected by the above (server is
+ * on host, cannot close open files in guest). Virtio-fs needs sync
+ * release, because the num_waiting mechanism to wait for all requests
+ * before commencing with fs shutdown doesn't work if submounts are
+ * used.
*/
- fuse_file_put(ff, false);
+ fuse_file_put(ff, ff->fm->fc->auto_submounts);
}
void fuse_release_common(struct file *file, bool isdir)
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH 7.0 00/49] 7.0.14-rc1 review
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (48 preceding siblings ...)
2026-06-25 13:04 ` [PATCH 7.0 49/49] virtiofs: fix UAF on submount umount Greg Kroah-Hartman
@ 2026-06-25 13:44 ` Florian Fainelli
2026-06-25 15:27 ` Brett A C Sheffield
` (2 subsequent siblings)
52 siblings, 0 replies; 54+ messages in thread
From: Florian Fainelli @ 2026-06-25 13:44 UTC (permalink / raw)
To: Greg Kroah-Hartman, stable
Cc: patches, linux-kernel, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, sudipm.mukherjee, rwarsow, conor,
hargar, broonie, achill, sr
On 6/25/2026 2:03 PM, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 7.0.14 release.
> There are 49 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Sat, 27 Jun 2026 12:54:50 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v7.x/stable-review/patch-7.0.14-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-7.0.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on
BMIPS_GENERIC:
Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
--
Florian
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH 7.0 00/49] 7.0.14-rc1 review
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (49 preceding siblings ...)
2026-06-25 13:44 ` [PATCH 7.0 00/49] 7.0.14-rc1 review Florian Fainelli
@ 2026-06-25 15:27 ` Brett A C Sheffield
2026-06-25 17:30 ` Justin Forbes
2026-06-25 18:06 ` Peter Schneider
52 siblings, 0 replies; 54+ messages in thread
From: Brett A C Sheffield @ 2026-06-25 15:27 UTC (permalink / raw)
To: gregkh
Cc: stable, patches, linux-kernel, torvalds, akpm, linux, shuah,
patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr,
Brett A C Sheffield
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 7.0.14-rc1-gb1302a8a9f8c #1 SMP PREEMPT_DYNAMIC Thu Jun 25 15:07:36 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Tested-by: Brett A C Sheffield <bacs@librecast.net>
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH 7.0 00/49] 7.0.14-rc1 review
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (50 preceding siblings ...)
2026-06-25 15:27 ` Brett A C Sheffield
@ 2026-06-25 17:30 ` Justin Forbes
2026-06-25 18:06 ` Peter Schneider
52 siblings, 0 replies; 54+ messages in thread
From: Justin Forbes @ 2026-06-25 17:30 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: stable, patches, linux-kernel, torvalds, akpm, linux, shuah,
patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr
On Thu, Jun 25, 2026 at 02:03:12PM +0100, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 7.0.14 release.
> There are 49 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Sat, 27 Jun 2026 12:54:50 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v7.x/stable-review/patch-7.0.14-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-7.0.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
Tested rc1 against the Fedora build system (aarch64, ppc64le, s390x,
x86_64), and boot tested x86_64. No regressions noted.
Tested-by: Justin M. Forbes <jforbes@fedoraproject.org>
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH 7.0 00/49] 7.0.14-rc1 review
2026-06-25 13:03 [PATCH 7.0 00/49] 7.0.14-rc1 review Greg Kroah-Hartman
` (51 preceding siblings ...)
2026-06-25 17:30 ` Justin Forbes
@ 2026-06-25 18:06 ` Peter Schneider
52 siblings, 0 replies; 54+ messages in thread
From: Peter Schneider @ 2026-06-25 18:06 UTC (permalink / raw)
To: Greg Kroah-Hartman, stable
Cc: patches, linux-kernel, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, sudipm.mukherjee,
rwarsow, conor, hargar, broonie, achill, sr
Am 25.06.2026 um 15:03 schrieb Greg Kroah-Hartman:
> This is the start of the stable review cycle for the 7.0.14 release.
> There are 49 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 server. No dmesg oddities or regressions found.
Tested-by: Peter Schneider <pschneider1968@googlemail.com>
Beste Grüße,
Peter Schneider
--
Climb the mountain not to plant your flag, but to embrace the challenge,
enjoy the air and behold the view. Climb it so you can see the world,
not so the world can see you. -- David McCullough Jr.
OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244
Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc
https://keys.mailvelope.com/pks/lookup?op=get&search=pschneider1968@googlemail.com
https://keys.mailvelope.com/pks/lookup?op=get&search=pschneider1968@gmail.com
^ permalink raw reply [flat|nested] 54+ messages in thread