BPF List
 help / color / mirror / Atom feed
* [PATCH v3 00/13] Fix leaks in rc core
@ 2026-07-22 10:23 Sean Young
  2026-07-22 10:23 ` [PATCH v3 12/13] media: rc: Fix use after free in bpf progs Sean Young
  0 siblings, 1 reply; 3+ messages in thread
From: Sean Young @ 2026-07-22 10:23 UTC (permalink / raw)
  To: linux-media; +Cc: Sean Young, bpf

Changes since v2:
 - sashiko had many more good review comments

Changes since v1:
 - sashiko had many good review comments
 - Added fix rc: Use after free in ir_raw_event_handle()
 - Added fix meson-ir-tx: Ensure probe error is propagated
 - Added fix redrat3: Ensure all urbs are suspended
 - Added fix media: redrat3: Error path leaves device in transmitting state
 - streamzap fix was incorrect
 - Other minor fixes


Sean Young (13):
  media: streamzap: Add missing rc_unregister_device()
  media: redrat3: Ensure rc device is freed if enable_detector() fails
  media: redrat3: Ensure we don't read beyond the end of the packet
  media: redrat3: Ensure all urbs are suspended
  media: redrat3: Error path leaves device in transmitting state
  media: sunxi-cir: Ensure no more interrupts can occur before free
  media: meson-ir-tx: Ensure clock is disabled on unbind
  media: meson-ir-tx: Ensure rc_free_device() is called on unbind
  media: meson-ir-tx: Ensure probe error is propagated
  media: ir-hix5hd2: Ensure rdev is setup before interrupts are enabled
  media: rc: Use after free in ir_raw_event_handle()
  media: rc: Fix use after free in bpf progs
  media: rc: Fix race condition during rc_register_device()

 drivers/media/rc/bpf-lirc.c    | 18 ++++++++++-----
 drivers/media/rc/ir-hix5hd2.c  |  5 +++--
 drivers/media/rc/meson-ir-tx.c | 14 +++++-------
 drivers/media/rc/rc-ir-raw.c   | 40 ++++++++++------------------------
 drivers/media/rc/rc-main.c     | 18 +++++++++------
 drivers/media/rc/redrat3.c     | 35 ++++++++++++++++++++++++-----
 drivers/media/rc/streamzap.c   |  1 +
 drivers/media/rc/sunxi-cir.c   |  2 +-
 8 files changed, 75 insertions(+), 58 deletions(-)

-- 
2.55.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v3 12/13] media: rc: Fix use after free in bpf progs
  2026-07-22 10:23 [PATCH v3 00/13] Fix leaks in rc core Sean Young
@ 2026-07-22 10:23 ` Sean Young
  2026-07-22 10:49   ` sashiko-bot
  0 siblings, 1 reply; 3+ messages in thread
From: Sean Young @ 2026-07-22 10:23 UTC (permalink / raw)
  To: linux-media, Sean Young, Mauro Carvalho Chehab, Patrice Chotard,
	Hans Verkuil
  Cc: linux-kernel, bpf

Since commit dccc0c3ddf8f ("media: rc: fix race between unregister and
urb/irq callbacks"), rcdev->raw is no longer set to NULL after device
unregister. raw->progs could point to stale data.

Fixes: dccc0c3ddf8f ("media: rc: fix race between unregister and urb/irq callbacks")
Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/bpf-lirc.c  | 18 +++++++++++++-----
 drivers/media/rc/rc-ir-raw.c | 11 +++--------
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c
index 2f7564f26445..14ab611e7445 100644
--- a/drivers/media/rc/bpf-lirc.c
+++ b/drivers/media/rc/bpf-lirc.c
@@ -148,12 +148,13 @@ static int lirc_bpf_attach(struct rc_dev *rcdev, struct bpf_prog *prog)
 	if (ret)
 		return ret;
 
-	raw = rcdev->raw;
-	if (!raw) {
+	if (!rcdev->registered) {
 		ret = -ENODEV;
 		goto unlock;
 	}
 
+	raw = rcdev->raw;
+
 	old_array = lirc_rcu_dereference(raw->progs);
 	if (old_array && bpf_prog_array_length(old_array) >= BPF_MAX_PROGS) {
 		ret = -E2BIG;
@@ -186,12 +187,13 @@ static int lirc_bpf_detach(struct rc_dev *rcdev, struct bpf_prog *prog)
 	if (ret)
 		return ret;
 
-	raw = rcdev->raw;
-	if (!raw) {
+	if (!rcdev->registered) {
 		ret = -ENODEV;
 		goto unlock;
 	}
 
+	raw = rcdev->raw;
+
 	old_array = lirc_rcu_dereference(raw->progs);
 	ret = bpf_prog_array_copy(old_array, prog, NULL, 0, &new_array);
 	/*
@@ -235,7 +237,8 @@ void lirc_bpf_free(struct rc_dev *rcdev)
 	struct bpf_prog_array_item *item;
 	struct bpf_prog_array *array;
 
-	array = lirc_rcu_dereference(rcdev->raw->progs);
+	array = rcu_replace_pointer(rcdev->raw->progs, NULL,
+				    lockdep_is_held(&ir_raw_handler_lock));
 	if (!array)
 		return;
 
@@ -316,6 +319,11 @@ int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
 	if (ret)
 		goto put;
 
+	if (!rcdev->registered) {
+		ret = -ENODEV;
+		goto unlock;
+	}
+
 	progs = lirc_rcu_dereference(rcdev->raw->progs);
 	cnt = progs ? bpf_prog_array_length(progs) : 0;
 
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index f066176c9f37..26962b500b0c 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -650,8 +650,11 @@ int ir_raw_event_register(struct rc_dev *dev)
 void ir_raw_event_free(struct rc_dev *dev)
 {
 	if (dev->raw) {
+		mutex_lock(&ir_raw_handler_lock);
 		if (dev->raw->thread)
 			put_task_struct(dev->raw->thread);
+		lirc_bpf_free(dev);
+		mutex_unlock(&ir_raw_handler_lock);
 		kfree(dev->raw);
 		dev->raw = NULL;
 	}
@@ -661,9 +664,6 @@ void ir_raw_event_unregister(struct rc_dev *dev)
 {
 	struct ir_raw_handler *handler;
 
-	if (!dev || !dev->raw)
-		return;
-
 	kthread_stop(dev->raw->thread);
 	timer_delete_sync(&dev->raw->edge_handle);
 
@@ -676,11 +676,6 @@ void ir_raw_event_unregister(struct rc_dev *dev)
 
 	lirc_bpf_free(dev);
 
-	/*
-	 * A user can be calling bpf(BPF_PROG_{QUERY|ATTACH|DETACH}), so
-	 * ensure that the raw member is null on unlock; this is how
-	 * "device gone" is checked.
-	 */
 	mutex_unlock(&ir_raw_handler_lock);
 }
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v3 12/13] media: rc: Fix use after free in bpf progs
  2026-07-22 10:23 ` [PATCH v3 12/13] media: rc: Fix use after free in bpf progs Sean Young
@ 2026-07-22 10:49   ` sashiko-bot
  0 siblings, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-07-22 10:49 UTC (permalink / raw)
  To: Sean Young; +Cc: bpf, media-ci

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] NULL pointer dereference in BPF LIRC operations due to missing `!raw` check on device registration error path.
--

--- Patch [12]: [PATCH v3 12/13] media: rc: Fix use after free in bpf progs ---
commit 7dc21e94d34583cca33adec11dc3c1b8af880d26
Author: Sean Young <sean@mess.org>

media: rc: Fix use after free in bpf progs
    
Since commit dccc0c3ddf8f ("media: rc: fix race between unregister and
urb/irq callbacks"), rcdev->raw is no longer set to NULL after device
unregister. raw->progs could point to stale data.

> diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c
> index 2f7564f26445c..14ab611e74457 100644
> --- a/drivers/media/rc/bpf-lirc.c
> +++ b/drivers/media/rc/bpf-lirc.c
> @@ -148,12 +148,13 @@ static int lirc_bpf_attach(struct rc_dev *rcdev, struct bpf_prog *prog)
>  	if (ret)
>  		return ret;
>  
> -	raw = rcdev->raw;
> -	if (!raw) {
> +	if (!rcdev->registered) {
>  		ret = -ENODEV;
>  		goto unlock;
>  	}
>  
> +	raw = rcdev->raw;
> +
>  	old_array = lirc_rcu_dereference(raw->progs);

[Severity: High]
Can this lead to a NULL pointer dereference if rc_register_device() fails?

In rc_register_device(), dev->registered is set to true before lirc_register()
makes the device visible to userspace. If a subsequent initialization step fails
(such as input_register_device() or ir_raw_event_register()), the error path
calls ir_raw_event_free(dev), which frees dev->raw and sets it to NULL.

However, dev->registered is never reverted to false. If a concurrent userspace
process opens /dev/lircX and calls bpf(BPF_PROG_ATTACH) while the fd is kept
open, the !rcdev->registered check here would pass. The raw pointer would
then be NULL, causing lirc_rcu_dereference(raw->progs) to crash.

[ ... ]

> @@ -186,12 +187,13 @@ static int lirc_bpf_detach(struct rc_dev *rcdev, struct bpf_prog *prog)
>  	if (ret)
>  		return ret;
>  
> -	raw = rcdev->raw;
> -	if (!raw) {
> +	if (!rcdev->registered) {
>  		ret = -ENODEV;
>  		goto unlock;
>  	}
>  
> +	raw = rcdev->raw;
> +
>  	old_array = lirc_rcu_dereference(raw->progs);

[Severity: High]
Could the same NULL pointer dereference occur here in lirc_bpf_detach() if
userspace races with device registration failure?

[ ... ]

> @@ -316,6 +319,11 @@ int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
>  	if (ret)
>  		goto put;
>  
> +	if (!rcdev->registered) {
> +		ret = -ENODEV;
> +		goto unlock;
> +	}
> +
>  	progs = lirc_rcu_dereference(rcdev->raw->progs);

[Severity: High]
Does this code also suffer from the same NULL pointer dereference risk on
rcdev->raw when rc_register_device() hits an error path?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1784715737.git.sean@mess.org?part=12

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-22 10:49 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-22 10:23 [PATCH v3 00/13] Fix leaks in rc core Sean Young
2026-07-22 10:23 ` [PATCH v3 12/13] media: rc: Fix use after free in bpf progs Sean Young
2026-07-22 10:49   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox