mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: linux-input@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
	Benjamin Tissoires <bentiss@kernel.org>,
	 Jiri Kosina <jikos@kernel.org>,
	Christian Lamparter <chunkeey@gmail.com>
Subject: [PATCH] Input: reject parent overrides on managed input devices
Date: Fri, 9 Oct 2026 20:54:28 -0700	[thread overview]
Message-ID: <asmCc1VxVPLIMgY6@google.com> (raw)

When an input device is allocated with devm_input_allocate_device(), the
owner struct device is set as dev->dev.parent and holds the
devm_input_device_release resource. Later, input_register_device()
attaches the devm_input_device_unregister resource to dev->dev.parent.

Clearing or overriding dev->dev.parent before registration splits devres
ownership across different devices, which breaks managed lifetime
assumptions.

Verify via devres_find() that dev->dev.parent is non-NULL and still
holds the matching devm_input_device_release entry before registering a
managed input device, rejecting registration with -EINVAL otherwise.

Also add KUnit test coverage in input_test.c verifying that reparented
and NULL-parent managed input devices are rejected while preserving the
owner parent succeeds.

Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/input.c            |  8 ++++++++
 drivers/input/tests/input_test.c | 34 ++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index ac0369414687..76ed9ff40584 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2417,6 +2417,14 @@ int input_register_device(struct input_dev *dev)
 	}
 
 	if (dev->devres_managed) {
+		if (!dev->dev.parent ||
+		    !devres_find(dev->dev.parent, devm_input_device_release,
+				 devm_input_device_match, dev)) {
+			dev_err(&dev->dev,
+				"Parent of managed input device was overridden, refusing to register\n");
+			return -EINVAL;
+		}
+
 		devres = devres_alloc(devm_input_device_unregister,
 				      sizeof(*devres), GFP_KERNEL);
 		if (!devres)
diff --git a/drivers/input/tests/input_test.c b/drivers/input/tests/input_test.c
index e105ce71a920..b8c8f04c041b 100644
--- a/drivers/input/tests/input_test.c
+++ b/drivers/input/tests/input_test.c
@@ -8,6 +8,7 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 
+#include <kunit/device.h>
 #include <kunit/test.h>
 
 #define POLL_INTERVAL 100
@@ -161,11 +162,44 @@ static void input_test_grab(struct kunit *test)
 	input_put_device(input_dev);
 }
 
+static void input_test_managed_parent_override(struct kunit *test)
+{
+	struct device *owner, *other_dev;
+	struct input_dev *input_dev;
+
+	owner = kunit_device_register(test, "input-test-owner");
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, owner);
+
+	other_dev = kunit_device_register(test, "input-test-other");
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, other_dev);
+
+	/* Overriding dev.parent to another device must be rejected */
+	input_dev = devm_input_allocate_device(owner);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, input_dev);
+	input_dev->name = "Managed input device (reparented)";
+	input_dev->dev.parent = other_dev;
+	KUNIT_EXPECT_EQ(test, input_register_device(input_dev), -EINVAL);
+
+	/* Clearing dev.parent to NULL must be rejected */
+	input_dev = devm_input_allocate_device(owner);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, input_dev);
+	input_dev->name = "Managed input device (null parent)";
+	input_dev->dev.parent = NULL;
+	KUNIT_EXPECT_EQ(test, input_register_device(input_dev), -EINVAL);
+
+	/* Preserving original owner as dev.parent succeeds */
+	input_dev = devm_input_allocate_device(owner);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, input_dev);
+	input_dev->name = "Managed input device (valid parent)";
+	KUNIT_EXPECT_EQ(test, input_register_device(input_dev), 0);
+}
+
 static struct kunit_case input_tests[] = {
 	KUNIT_CASE(input_test_polling),
 	KUNIT_CASE(input_test_timestamp),
 	KUNIT_CASE(input_test_match_device_id),
 	KUNIT_CASE(input_test_grab),
+	KUNIT_CASE(input_test_managed_parent_override),
 	{ /* sentinel */ }
 };
 
-- 
2.56.0.385.gd3acb90ef8-goog


-- 
Dmitry

                 reply	other threads:[~2026-10-10  3:54 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=asmCc1VxVPLIMgY6@google.com \
    --to=dmitry.torokhov@gmail.com \
    --cc=bentiss@kernel.org \
    --cc=chunkeey@gmail.com \
    --cc=jikos@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®