[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250711-usb_authentication-v2-4-2878690e6b6d@ssi.gouv.fr>
Date: Fri, 11 Jul 2025 10:41:25 +0200
From: nicolas.bouchinet@....cyber.gouv.fr
To: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc: Luc Bonnafoux <luc.bonnafoux@....gouv.fr>,
Alan Stern <stern@...land.harvard.edu>, Kannappan R <r.kannappan@...el.com>,
Sabyrzhan Tasbolatov <snovitoll@...il.com>,
Krzysztof Kozlowski <krzysztof.kozlowski@...aro.org>,
Stefan Eichenberger <stefan.eichenberger@...adex.com>,
Thomas Gleixner <tglx@...utronix.de>, Pawel Laszczak <pawell@...ence.com>,
Ma Ke <make_ruc2021@....com>, Jeff Johnson <jeff.johnson@....qualcomm.com>,
Luc Bonnafoux <luc.bonnafoux@....cyber.gouv.fr>,
Nicolas Bouchinet <nicolas.bouchinet@....gouv.fr>,
linux-kernel@...r.kernel.org, linux-usb@...r.kernel.org
Subject: [RFC PATCH v2 4/4] usb: core: Add sysctl to configure
authentication timeouts
From: Nicolas Bouchinet <nicolas.bouchinet@....gouv.fr>
The kernel.usb.authent_engine_register_timeout let a user configure in
seconds the time the kernel will wait for a userspace usb authentication
policy engine to register itself.
The kernel.usb.authent_engine_response_timeout let a user configure in
seconds the time the kernel will wait for the registered userspace usb
authentication policy engine to reply to messages.
Co-developed-by: Luc Bonnafoux <luc.bonnafoux@....gouv.fr>
Signed-off-by: Luc Bonnafoux <luc.bonnafoux@....gouv.fr>
Signed-off-by: Nicolas Bouchinet <nicolas.bouchinet@....gouv.fr>
---
drivers/usb/core/Makefile | 1 +
drivers/usb/core/authent.h | 14 ++++++++++
drivers/usb/core/authent_netlink.c | 26 +++++++++++-------
drivers/usb/core/sysctl.c | 55 ++++++++++++++++++++++++++++++++++++++
drivers/usb/core/usb.c | 8 ++++++
include/linux/usb.h | 9 +++++++
6 files changed, 104 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 7ba1a89cf3de7a398889eee1820f2bfbbc4280f5..2ec59764fe5ade682368890b4cd30bb3cdad7746 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -15,6 +15,7 @@ endif
usbcore-$(CONFIG_OF) += of.o
usbcore-$(CONFIG_USB_PCI) += hcd-pci.o
usbcore-$(CONFIG_ACPI) += usb-acpi.o
+usbcore-$(CONFIG_SYSCTL) += sysctl.o
ifdef CONFIG_USB_ONBOARD_DEV
usbcore-y += ../misc/onboard_usb_dev_pdevs.o
diff --git a/drivers/usb/core/authent.h b/drivers/usb/core/authent.h
index 2cf6d577131084a97f5c30fadaace1eac7e83c11..7c3264793c6ab5d44fa453b3b70c41882c96ff0d 100644
--- a/drivers/usb/core/authent.h
+++ b/drivers/usb/core/authent.h
@@ -169,6 +169,20 @@ struct usb_authent_error_resp_hd {
__u8 errorData;
} __packed;
+extern uint usb_auth_wait_userspace_timeout;
+extern uint usb_auth_wait_response_timeout;
+
+#define DEFAULT_USB_AUTHENT_WAIT_USERSPACE_TIMEOUT 30
+#define DEFAULT_USB_AUTHENT_WAIT_RESPONSE_TIMEOUT 300
+
+#ifdef CONFIG_SYSCTL
+extern int usb_register_sysctl(void);
+extern void usb_unregister_sysctl(void);
+#else
+# define usb_auth_init_sysctl() (0)
+# define usb_auth_exit_sysctl() do { } while (0)
+#endif
+
#ifdef CONFIG_USB_AUTHENTICATION
int usb_authenticate_device(struct usb_device *dev);
#else
diff --git a/drivers/usb/core/authent_netlink.c b/drivers/usb/core/authent_netlink.c
index 9848f219e0e4807563f0f0432a0f1108cd6a0454..731ecadee934ae712735dae5932c0e595720245d 100644
--- a/drivers/usb/core/authent_netlink.c
+++ b/drivers/usb/core/authent_netlink.c
@@ -21,11 +21,15 @@
#include <uapi/linux/usb/usb_auth_netlink.h>
#include "authent.h"
#include "authent_netlink.h"
+#include "authent.h"
#define WAIT_USERSPACE_TIMEOUT 30
#define WAIT_RESPONSE_TIMEOUT 300
#define USBAUTH_MAX_RESP_SIZE 128
+uint usb_auth_wait_userspace_timeout = DEFAULT_USB_AUTHENT_WAIT_USERSPACE_TIMEOUT;
+uint usb_auth_wait_response_timeout = DEFAULT_USB_AUTHENT_WAIT_RESPONSE_TIMEOUT;
+
/**
* struct usb_auth_req - Define an outstanding request between the kernel and userspace
*
@@ -609,7 +613,8 @@ int usb_policy_engine_check_digest(const u32 route, const u8 *const digests,
return -EINVAL;
}
- if (!wait_event_timeout(usb_req_wq, pol_eng_pid != 0, HZ * WAIT_USERSPACE_TIMEOUT)) {
+ if (!wait_event_timeout(usb_req_wq, pol_eng_pid != 0,
+ HZ * usb_auth_wait_userspace_timeout)) {
pr_err("%s: userspace not available\n", __func__);
return -ECOMM;
}
@@ -675,7 +680,7 @@ int usb_policy_engine_check_digest(const u32 route, const u8 *const digests,
if (!wait_event_timeout(usb_req_wq,
usb_auth_outstanding_reqs[index].done == 1,
- HZ * WAIT_RESPONSE_TIMEOUT)) {
+ HZ * usb_auth_wait_response_timeout)) {
pr_err("%s: userspace response not available\n", __func__);
usb_auth_release_reqs_slot(index);
return -ECOMM;
@@ -740,7 +745,8 @@ int usb_policy_engine_check_cert_chain(const u32 route,
return -EINVAL;
}
- if (!wait_event_timeout(usb_req_wq, pol_eng_pid != 0, HZ * WAIT_USERSPACE_TIMEOUT)) {
+ if (!wait_event_timeout(usb_req_wq, pol_eng_pid != 0,
+ HZ * usb_auth_wait_userspace_timeout)) {
pr_err("%s: userspace not available\n", __func__);
return -ECOMM;
}
@@ -814,7 +820,7 @@ int usb_policy_engine_check_cert_chain(const u32 route,
if (!wait_event_timeout(usb_req_wq,
usb_auth_outstanding_reqs[index].done == 1,
- HZ * WAIT_RESPONSE_TIMEOUT)) {
+ HZ * usb_auth_wait_response_timeout)) {
pr_err("%s: userspace response not available\n", __func__);
usb_auth_release_reqs_slot(index);
return -ECOMM;
@@ -852,8 +858,8 @@ int usb_policy_engine_generate_challenge(const u32 id, u8 *nonce)
struct sk_buff *skb = NULL;
u32 index = 0;
- /* Arbitrary 30s wait before giving up */
- if (!wait_event_timeout(usb_req_wq, pol_eng_pid != 0, HZ * WAIT_USERSPACE_TIMEOUT)) {
+ if (!wait_event_timeout(usb_req_wq, pol_eng_pid != 0,
+ HZ * usb_auth_wait_userspace_timeout)) {
pr_err("%s: userspace not available\n", __func__);
return -ECOMM;
}
@@ -902,7 +908,7 @@ int usb_policy_engine_generate_challenge(const u32 id, u8 *nonce)
if (!wait_event_timeout(usb_req_wq,
usb_auth_outstanding_reqs[index].done == 1,
- HZ * WAIT_RESPONSE_TIMEOUT)) {
+ HZ * usb_auth_wait_response_timeout)) {
pr_err("%s: userspace response not available\n", __func__);
usb_auth_release_reqs_slot(index);
return -ECOMM;
@@ -953,7 +959,8 @@ int usb_policy_engine_check_challenge(const u32 id,
return -EINVAL;
}
- if (!wait_event_timeout(usb_req_wq, pol_eng_pid != 0, HZ * WAIT_USERSPACE_TIMEOUT)) {
+ if (!wait_event_timeout(usb_req_wq, pol_eng_pid != 0,
+ HZ * usb_auth_wait_userspace_timeout)) {
pr_err("%s: userspace not available\n", __func__);
return -ECOMM;
}
@@ -1016,9 +1023,10 @@ int usb_policy_engine_check_challenge(const u32 id,
__func__, ret);
return -ECOMM;
}
+
if (!wait_event_timeout(usb_req_wq,
usb_auth_outstanding_reqs[index].done == 1,
- HZ * WAIT_RESPONSE_TIMEOUT)) {
+ HZ * usb_auth_wait_response_timeout)) {
pr_err("%s: userspace response not available\n", __func__);
usb_auth_release_reqs_slot(index);
return -ECOMM;
diff --git a/drivers/usb/core/sysctl.c b/drivers/usb/core/sysctl.c
new file mode 100644
index 0000000000000000000000000000000000000000..a9f917e34e8e914cb60653a56fa90a4790bf6011
--- /dev/null
+++ b/drivers/usb/core/sysctl.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPDX-FileCopyrightText: (C) 2025 ANSSI
+ *
+ * USB Authentication netlink interface
+ *
+ * Author: Luc Bonnafoux <luc.bonnafoux@....gouv.fr>
+ * Author: Nicolas Bouchinet <nicolas.bouchinet@....gouv.fr>
+ *
+ */
+
+#include <linux/sysctl.h>
+#include <linux/usb.h>
+#include "authent.h"
+
+static const unsigned long max_ms = 3600;
+
+static const struct ctl_table usb_sysctls[] = {
+#ifdef CONFIG_USB_AUTHENTICATION
+ {
+ .procname = "authent_engine_register_timeout",
+ .data = &usb_auth_wait_userspace_timeout,
+ .maxlen = sizeof(usb_auth_wait_userspace_timeout),
+ .mode = 0644,
+ .proc_handler = proc_douintvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = (void*)&max_ms,
+ },
+ {
+ .procname = "authent_engine_response_timeout",
+ .data = &usb_auth_wait_response_timeout,
+ .maxlen = sizeof(usb_auth_wait_response_timeout),
+ .mode = 0644,
+ .proc_handler = proc_douintvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = (void*)&max_ms,
+ },
+#endif
+};
+
+static struct ctl_table_header *usb_sysctl_table;
+
+int __init usb_register_sysctl(void)
+{
+ usb_sysctl_table = register_sysctl("kernel/usb", usb_sysctls);
+ if (!usb_sysctl_table)
+ return -ENOMEM;
+ return 0;
+}
+
+void usb_unregister_sysctl(void)
+{
+ unregister_sysctl_table(usb_sysctl_table);
+ usb_sysctl_table = NULL;
+}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 421cec9966912ccc62ce163733f46cab05503bd6..0d88a072146dc0ec88314733ae92c835585f722d 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -46,6 +46,7 @@
#include <linux/dma-mapping.h>
#include "hub.h"
+#include "authent.h"
#include "authent_netlink.h"
const char *usbcore_name = "usbcore";
@@ -1082,6 +1083,10 @@ static int __init usb_init(void)
usb_acpi_register();
+ retval = usb_register_sysctl();
+ if (retval)
+ goto sysctl_init_failed;
+
#ifdef CONFIG_USB_AUTHENTICATION
retval = usb_auth_init_netlink();
if (retval)
@@ -1127,6 +1132,8 @@ static int __init usb_init(void)
bus_notifier_failed:
bus_unregister(&usb_bus_type);
bus_register_failed:
+ usb_unregister_sysctl();
+sysctl_init_failed:
usb_acpi_unregister();
usb_debugfs_cleanup();
out:
@@ -1151,6 +1158,7 @@ static void __exit usb_exit(void)
class_unregister(&usbmisc_class);
bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
bus_unregister(&usb_bus_type);
+ usb_unregister_sysctl();
usb_acpi_unregister();
usb_debugfs_cleanup();
idr_destroy(&usb_bus_idr);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index e9037c8120b43556f8610f9acb3ad4129e847b98..b616c0fb79be33aace2c052ea3ecd1dd0641a024 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -2062,6 +2062,15 @@ extern void usb_led_activity(enum usb_led_event ev);
static inline void usb_led_activity(enum usb_led_event ev) {}
#endif
+/* sysctl.c */
+#ifdef CONFIG_SYSCTL
+extern int usb_register_sysctl(void);
+extern void usb_unregister_sysctl(void);
+#else
+static inline int usb_register_sysctl(void) { return 0; }
+static inline void usb_unregister_sysctl(void) { }
+#endif /* CONFIG_SYSCTL */
+
#endif /* __KERNEL__ */
#endif
--
2.50.0
Powered by blists - more mailing lists