* [PATCH v6 0/7] Add helper for security policies
@ 2026-03-24 9:52 Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 1/7] of: add of_property_write_string_array() Fabian Pflug
` (6 more replies)
0 siblings, 7 replies; 11+ messages in thread
From: Fabian Pflug @ 2026-03-24 9:52 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer; +Cc: Fabian Pflug, Ahmad Fatoum
This series adds helper functions to the security policy framework to
do additional work based on the selected policy.
Like adding the policy name to the commandline and configuring pinmux
based on the selected policy.
If this series is to be applied after Ahamad's bootm change series, then
the block to change the commandline has to be moved up to roughly line
720 into the function bootm_boot_prep, where all the other
bootm_data->provide_*** checks are, so that the previous context remains
the same.
Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
Changes in v6:
- Made active_policy static
- Add trailer for Ahamad
- Link to v5: https://lore.barebox.org/barebox/20260320-v2026-02-0-topic-sconfig_console-v5-0-2efcaa7cb03e@pengutronix.de
Changes in v5:
- Fix error in kernel_pinctrl. The array was never written back.
- Link to v4: https://lore.barebox.org/barebox/20260320-v2026-02-0-topic-sconfig_console-v4-0-ac93d797f8cf@pengutronix.de
Changes in v4:
- removed the global variable active_policy and replaced with a getter
function
- add sanity check for is_allow parameter
- add new notifier chain to security_policy on change without checking
policies is_allowed
- rewrote the pinctrl to make use of new notify chain
- changed pinctrl to use barebox,policy-<active-policy>-<name> to
replace pinctrl for <name> instead of replacing 'default'
- Link to v3: https://lore.barebox.org/barebox/20260318-v2026-02-0-topic-sconfig_console-v3-0-e26055294723@pengutronix.de
Changes in v3:
- replaced while loop with of_tree_for_each_node_from
- removed unsused variable definition in base.c
- Link to v2: https://lore.barebox.org/barebox/20260316-v2026-02-0-topic-sconfig_console-v2-0-1eee8c762beb@pengutronix.de
Changes in v2:
- Add of_property_write_string_array function
- Add selftest for of_property_write_string_array
- Add exra-check for active-policy
- Use "linux.bootargs.dyn.policy" instead of version without dyn
- Iterate over device-nodes instead of recurse through tree
- Link to v1: https://lore.barebox.org/barebox/20260312-v2026-02-0-topic-sconfig_console-v1-0-4c3fccafab1e@pengutronix.de
---
Fabian Pflug (7):
of: add of_property_write_string_array()
security: policy: sanity check parameters
security: policy: remove global active_policy var
security: policy: add notifier chain for name change
common: bootm: add policy to commandline
drivers: pinctrl: configure pinctrl based on policy name
security: kernel_pinctrl: fixup pinctrl in kernel dts
commands/sconfig.c | 9 +++++-
common/bootm.c | 24 ++++++++++++++
drivers/of/base.c | 43 +++++++++++++++++++++++++
drivers/pinctrl/pinctrl.c | 73 +++++++++++++++++++++++++++++++++++++++++--
include/bootm.h | 5 +++
include/of.h | 3 ++
include/security/config.h | 1 +
include/security/policy.h | 3 +-
security/Kconfig.policy | 15 ++++++++-
security/Makefile | 1 +
security/kernel_pinctrl.c | 67 +++++++++++++++++++++++++++++++++++++++
security/policy.c | 23 +++++++++-----
test/self/of_manipulation.c | 14 ++++++++-
test/self/of_manipulation.dts | 5 +++
14 files changed, 272 insertions(+), 14 deletions(-)
---
base-commit: 1d386a53086d28a0c4eda138ae9408a418b97b7e
change-id: 20260311-v2026-02-0-topic-sconfig_console-194842a14e1d
Best regards,
--
Fabian Pflug <f.pflug@pengutronix.de>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v6 1/7] of: add of_property_write_string_array()
2026-03-24 9:52 [PATCH v6 0/7] Add helper for security policies Fabian Pflug
@ 2026-03-24 9:52 ` Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 2/7] security: policy: sanity check parameters Fabian Pflug
` (5 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Fabian Pflug @ 2026-03-24 9:52 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer; +Cc: Fabian Pflug
Helper function to write an array of string into a property.
Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
drivers/of/base.c | 43 +++++++++++++++++++++++++++++++++++++++++++
include/of.h | 3 +++
test/self/of_manipulation.c | 14 +++++++++++++-
test/self/of_manipulation.dts | 5 +++++
4 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 460b5e2f4b..376a2ac6a8 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1570,6 +1570,49 @@ int of_property_write_u64_array(struct device_node *np,
return 0;
}
+/**
+ * of_property_write_string_array - Write strings to a property. If
+ * the property does not exist, it will be created and appended to the given
+ * device node.
+ *
+ * @np: device node to which the property value is to be written.
+ * @propname: name of the property to be written.
+ * @values: pointer to array elements to write.
+ * @sz: number of array elements to write.
+ *
+ * Search for a property in a device node and write a string to
+ * it. If the property does not exist, it will be created and appended to
+ * the device node. Returns 0 on success, -ENOMEM if the property or array
+ * of elements cannot be created, -EINVAL if no strings specified.
+ */
+int of_property_write_string_array(struct device_node *np,
+ const char *propname, const char **values,
+ size_t sz)
+{
+ char *buf = NULL, *next;
+ size_t len = 0;
+ int ret = 0, i;
+
+ for (i = 0; i < sz; i++)
+ len += strlen(values[i]) + 1;
+
+ if (!len)
+ return -EINVAL;
+
+ buf = malloc(len);
+ if (!buf)
+ return -ENOMEM;
+
+ next = buf;
+
+ for (i = 0; i < sz; i++)
+ next = stpcpy(next, values[i]) + 1;
+
+ ret = of_set_property(np, propname, buf, len, 1);
+ free(buf);
+ return ret;
+}
+
/**
* of_property_write_strings - Write strings to a property. If
* the property does not exist, it will be created and appended to the given
diff --git a/include/of.h b/include/of.h
index ba8d1e358d..34439ee763 100644
--- a/include/of.h
+++ b/include/of.h
@@ -310,6 +310,9 @@ extern int of_property_write_string(struct device_node *np, const char *propname
const char *value);
extern int of_property_write_strings(struct device_node *np, const char *propname,
...) __attribute__((__sentinel__));
+int of_property_write_string_array(struct device_node *np,
+ const char *propname, const char **values,
+ size_t sz);
int of_property_sprintf(struct device_node *np, const char *propname, const char *fmt, ...)
__printf(3, 4);
diff --git a/test/self/of_manipulation.c b/test/self/of_manipulation.c
index 8d645b1137..faf948a17b 100644
--- a/test/self/of_manipulation.c
+++ b/test/self/of_manipulation.c
@@ -71,13 +71,19 @@ static void test_of_basics(struct device_node *root)
static void test_of_property_strings(struct device_node *root)
{
- struct device_node *np1, *np2, *np3, *np4;
+ struct device_node *np1, *np2, *np3, *np4, *np5;
char properties[] = "ayy\0bee\0sea";
+ static const char * const prop_array[] = {
+ "ayy",
+ "bee\0\0\0",
+ "sea\0",
+ };
np1 = of_new_node(root, "np1");
np2 = of_new_node(root, "np2");
np3 = of_new_node(root, "np3");
np4 = of_new_node(root, "np4");
+ np5 = of_new_node(root, "np5");
of_property_sprintf(np1, "property-single", "%c%c%c", 'a', 'y', 'y');
@@ -108,6 +114,12 @@ static void test_of_property_strings(struct device_node *root)
of_prepend_property(np4, "property-multi", "ayy", 4);
assert_equal(np3, np4);
+
+ of_property_write_string_array(np5, "property-single", prop_array, 1);
+
+ of_property_write_string_array(np5, "property-multi", prop_array, 3);
+
+ assert_equal(np4, np5);
}
static void __init test_of_manipulation(void)
diff --git a/test/self/of_manipulation.dts b/test/self/of_manipulation.dts
index 2cc6773fa9..7a1fb1217d 100644
--- a/test/self/of_manipulation.dts
+++ b/test/self/of_manipulation.dts
@@ -34,4 +34,9 @@ np4 {
property-single = "ayy";
property-multi = "ayy", "bee", "sea";
};
+
+ np5 {
+ property-single = "ayy";
+ property-multi = "ayy", "bee", "sea";
+ };
};
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v6 2/7] security: policy: sanity check parameters
2026-03-24 9:52 [PATCH v6 0/7] Add helper for security policies Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 1/7] of: add of_property_write_string_array() Fabian Pflug
@ 2026-03-24 9:52 ` Fabian Pflug
2026-03-24 14:35 ` Ahmad Fatoum
2026-03-24 9:52 ` [PATCH v6 3/7] security: policy: remove global active_policy var Fabian Pflug
` (4 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Fabian Pflug @ 2026-03-24 9:52 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer; +Cc: Fabian Pflug
Do a sanity check for the the is_allowed, before using it as array
index.
Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
commands/sconfig.c | 7 ++++++-
security/policy.c | 2 ++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/commands/sconfig.c b/commands/sconfig.c
index 02c3a6b1ed..3ca4478270 100644
--- a/commands/sconfig.c
+++ b/commands/sconfig.c
@@ -37,7 +37,12 @@ static void sconfig_print(const struct security_policy *policy)
static int sconfig_command_notify(struct notifier_block *nb,
unsigned long opt, void *unused)
{
- bool allow = is_allowed(NULL, opt);
+ bool allow;
+
+ if (opt >= SCONFIG_NUM)
+ return 0;
+
+ allow = is_allowed(NULL, opt);
printf("%s%s%s%s\n", allow ? green : red, allow ? "+" : "-", nc,
sconfig_names[opt]);
diff --git a/security/policy.c b/security/policy.c
index 85333d9e6f..95e7bf99a2 100644
--- a/security/policy.c
+++ b/security/policy.c
@@ -52,6 +52,8 @@ static bool __is_allowed(const struct security_policy *policy, unsigned option)
{
if (!policy)
return true;
+ if (WARN(option > SCONFIG_NUM))
+ return false;
return policy->policy[option];
}
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v6 3/7] security: policy: remove global active_policy var
2026-03-24 9:52 [PATCH v6 0/7] Add helper for security policies Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 1/7] of: add of_property_write_string_array() Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 2/7] security: policy: sanity check parameters Fabian Pflug
@ 2026-03-24 9:52 ` Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 4/7] security: policy: add notifier chain for name change Fabian Pflug
` (3 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Fabian Pflug @ 2026-03-24 9:52 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer; +Cc: Fabian Pflug, Ahmad Fatoum
Replace with a getter function called security_policy_get_active(), that
automatically initializes the active_policy, if an initial policy is
set.
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
commands/sconfig.c | 2 ++
include/security/policy.h | 3 +--
security/Kconfig.policy | 3 ++-
security/policy.c | 18 +++++++++++-------
4 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/commands/sconfig.c b/commands/sconfig.c
index 3ca4478270..7afb24366b 100644
--- a/commands/sconfig.c
+++ b/commands/sconfig.c
@@ -114,6 +114,7 @@ static int do_sconfig_flags(int argc, char *argv[])
static struct security_policy *alloc_policy(void)
{
struct security_policy *override;
+ const struct security_policy *active_policy = security_policy_get_active();
override = xmalloc(sizeof(*override));
@@ -137,6 +138,7 @@ static void free_policy(struct security_policy *policy)
static int do_sconfig(int argc, char *argv[])
{
+ const struct security_policy *active_policy = security_policy_get_active();
struct security_policy *override;
bool allow_color;
int i, ret;
diff --git a/include/security/policy.h b/include/security/policy.h
index c41220ef3b..11490bf173 100644
--- a/include/security/policy.h
+++ b/include/security/policy.h
@@ -25,9 +25,8 @@
#define POLICY_TAMPER "tamper"
#define POLICY_FIELD_RETURN "return"
-extern const struct security_policy *active_policy;
-
const struct security_policy *security_policy_get(const char *name);
+const struct security_policy *security_policy_get_active(void);
int security_policy_activate(const struct security_policy *policy);
int security_policy_select(const char *name);
diff --git a/security/Kconfig.policy b/security/Kconfig.policy
index 9ea52e91da..e778327b0d 100644
--- a/security/Kconfig.policy
+++ b/security/Kconfig.policy
@@ -49,7 +49,8 @@ config SECURITY_POLICY_INIT
prompt "Initial security policy"
help
The policy named here will be automatically selected the first
- time a security policy is to be consulted.
+ time a security policy is to be consulted or the currently active
+ policy is queried.
It's recommended to use a restrictive policy here and remove
the restrictions if needed instead of the other way round.
diff --git a/security/policy.c b/security/policy.c
index 95e7bf99a2..fadcca4463 100644
--- a/security/policy.c
+++ b/security/policy.c
@@ -43,7 +43,7 @@ struct policy_list_entry {
struct list_head list;
};
-const struct security_policy *active_policy;
+static const struct security_policy *active_policy;
static LIST_HEAD(policy_list);
NOTIFIER_HEAD(sconfig_notifier_list);
@@ -60,15 +60,12 @@ static bool __is_allowed(const struct security_policy *policy, unsigned option)
bool is_allowed(const struct security_policy *policy, unsigned option)
{
- policy = policy ?: active_policy;
-
if (WARN(option > SCONFIG_NUM))
return false;
- if (!policy && *CONFIG_SECURITY_POLICY_INIT) {
- security_policy_select(CONFIG_SECURITY_POLICY_INIT);
- policy = active_policy;
- }
+ /* initialize and use active policy if none is selected */
+ if (!policy)
+ policy = security_policy_get_active();
if (policy) {
bool allow = __is_allowed(policy, option);
@@ -108,6 +105,13 @@ int security_policy_activate(const struct security_policy *policy)
return 0;
}
+const struct security_policy *security_policy_get_active(void)
+{
+ if (!active_policy && *CONFIG_SECURITY_POLICY_INIT)
+ security_policy_select(CONFIG_SECURITY_POLICY_INIT);
+ return active_policy;
+}
+
const struct security_policy *security_policy_get(const char *name)
{
const struct policy_list_entry *entry;
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v6 4/7] security: policy: add notifier chain for name change
2026-03-24 9:52 [PATCH v6 0/7] Add helper for security policies Fabian Pflug
` (2 preceding siblings ...)
2026-03-24 9:52 ` [PATCH v6 3/7] security: policy: remove global active_policy var Fabian Pflug
@ 2026-03-24 9:52 ` Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 5/7] common: bootm: add policy to commandline Fabian Pflug
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Fabian Pflug @ 2026-03-24 9:52 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer; +Cc: Fabian Pflug
Add an additional notifier chain, that gets called, whenever a security
policy itself is changed, independent of the policies that have changed,
which could be used to inform users about the currently selected policy
name.
Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
include/security/config.h | 1 +
security/policy.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/include/security/config.h b/include/security/config.h
index b37ef4272c..35a5e963f7 100644
--- a/include/security/config.h
+++ b/include/security/config.h
@@ -20,6 +20,7 @@ extern const char *sconfig_names[SCONFIG_NUM];
int sconfig_lookup(const char *name);
extern struct notifier_head sconfig_notifier_list;
+extern struct notifier_head sconfig_name_notifier;
bool is_allowed(const struct security_policy *policy, unsigned option);
diff --git a/security/policy.c b/security/policy.c
index fadcca4463..7795d6dfce 100644
--- a/security/policy.c
+++ b/security/policy.c
@@ -47,6 +47,7 @@ static const struct security_policy *active_policy;
static LIST_HEAD(policy_list);
NOTIFIER_HEAD(sconfig_notifier_list);
+NOTIFIER_HEAD(sconfig_name_notifier);
static bool __is_allowed(const struct security_policy *policy, unsigned option)
{
@@ -102,6 +103,8 @@ int security_policy_activate(const struct security_policy *policy)
notifier_call_chain(&sconfig_notifier_list, i, NULL);
}
+ notifier_call_chain(&sconfig_name_notifier, 0, NULL);
+
return 0;
}
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v6 5/7] common: bootm: add policy to commandline
2026-03-24 9:52 [PATCH v6 0/7] Add helper for security policies Fabian Pflug
` (3 preceding siblings ...)
2026-03-24 9:52 ` [PATCH v6 4/7] security: policy: add notifier chain for name change Fabian Pflug
@ 2026-03-24 9:52 ` Fabian Pflug
2026-03-24 14:34 ` Ahmad Fatoum
2026-03-24 9:52 ` [PATCH v6 6/7] drivers: pinctrl: configure pinctrl based on policy name Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 7/7] security: kernel_pinctrl: fixup pinctrl in kernel dts Fabian Pflug
6 siblings, 1 reply; 11+ messages in thread
From: Fabian Pflug @ 2026-03-24 9:52 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer; +Cc: Fabian Pflug
If security policies are used, then the variable bootm.provide_policy
can be set to automatically append the currently selected security
policy to the kernel commandline with the prefix
barebox.security.policy=
This allows the the system to behave different based on the selected
security policy.
Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
common/bootm.c | 24 ++++++++++++++++++++++++
include/bootm.h | 5 +++++
2 files changed, 29 insertions(+)
diff --git a/common/bootm.c b/common/bootm.c
index d43079bb81..68631c392d 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -22,6 +22,7 @@
#include <uncompress.h>
#include <zero_page.h>
#include <security/config.h>
+#include <security/policy.h>
static LIST_HEAD(handler_list);
static struct sconfig_notifier_block sconfig_notifier;
@@ -75,6 +76,7 @@ static int bootm_dryrun;
static int bootm_earlycon;
static int bootm_provide_machine_id;
static int bootm_provide_hostname;
+static int bootm_provide_policy;
static int bootm_verbosity;
static int bootm_efi_mode = BOOTM_EFI_AVAILABLE;
@@ -97,6 +99,7 @@ void bootm_data_init_defaults(struct bootm_data *data)
data->appendroot = bootm_appendroot;
data->provide_machine_id = bootm_provide_machine_id;
data->provide_hostname = bootm_provide_hostname;
+ data->provide_policy = bootm_provide_policy;
data->verbose = bootm_verbosity;
data->dryrun = bootm_dryrun;
data->efi_boot = bootm_efi_mode;
@@ -118,6 +121,7 @@ void bootm_data_restore_defaults(const struct bootm_data *data)
bootm_appendroot = data->appendroot;
bootm_provide_machine_id = data->provide_machine_id;
bootm_provide_hostname = data->provide_hostname;
+ bootm_provide_policy = data->provide_policy;
bootm_verbosity = data->verbose;
bootm_dryrun = data->dryrun;
bootm_efi_mode = data->efi_boot;
@@ -759,6 +763,21 @@ int bootm_boot(struct bootm_data *bootm_data)
free(hostname_bootarg);
}
+ if (IS_ENABLED(CONFIG_SECURITY_POLICY) && bootm_data->provide_policy) {
+ char *policy_bootargs;
+ const struct security_policy *active_policy = security_policy_get_active();
+
+ if (active_policy && !active_policy->name) {
+ pr_err("Providing policy is enabled but policy has no name\n");
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ policy_bootargs = basprintf("barebox.security.policy=%s", active_policy->name);
+ globalvar_add_simple("linux.bootargs.dyn.policy", policy_bootargs);
+ free(policy_bootargs);
+ }
+
pr_info("\nLoading %s '%s'", file_type_to_string(data->kernel_type),
data->os_file);
if (data->kernel_type == filetype_uimage &&
@@ -967,6 +986,8 @@ static int bootm_init(void)
globalvar_add_simple_bool("bootm.earlycon", &bootm_earlycon);
globalvar_add_simple_bool("bootm.provide_machine_id", &bootm_provide_machine_id);
globalvar_add_simple_bool("bootm.provide_hostname", &bootm_provide_hostname);
+ if (IS_ENABLED(CONFIG_SECURITY_POLICY))
+ globalvar_add_simple_bool("bootm.provide_policy", &bootm_provide_policy);
if (IS_ENABLED(CONFIG_BOOTM_INITRD)) {
globalvar_add_simple("bootm.initrd", NULL);
globalvar_add_simple("bootm.initrd.loadaddr", NULL);
@@ -1030,3 +1051,6 @@ BAREBOX_MAGICVAR(global.bootm.root_dev, "bootm default root device (overrides de
BAREBOX_MAGICVAR(global.bootm.root_param, "bootm root parameter name (normally 'root' for root=/dev/...)");
BAREBOX_MAGICVAR(global.bootm.provide_machine_id, "If true, append systemd.machine_id=$global.machine_id to Kernel command line");
BAREBOX_MAGICVAR(global.bootm.provide_hostname, "If true, append systemd.hostname=$global.hostname to Kernel command line");
+#ifdef CONFIG_SECURITY_POLICY
+BAREBOX_MAGICVAR(global.bootm.provide_policy, "Add barebox.security.policy= option to Kernel");
+#endif
diff --git a/include/bootm.h b/include/bootm.h
index 21feb1ca98..a712010b2b 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -46,6 +46,11 @@ struct bootm_data {
* of global.hostname to Kernel.
*/
bool provide_hostname;
+ /*
+ * provide_policy - if true, try to add barebox.security.policy= with
+ * with value of currently selected policy
+ */
+ bool provide_policy;
enum bootm_efi_mode efi_boot;
unsigned long initrd_address;
unsigned long os_address;
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v6 6/7] drivers: pinctrl: configure pinctrl based on policy name
2026-03-24 9:52 [PATCH v6 0/7] Add helper for security policies Fabian Pflug
` (4 preceding siblings ...)
2026-03-24 9:52 ` [PATCH v6 5/7] common: bootm: add policy to commandline Fabian Pflug
@ 2026-03-24 9:52 ` Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 7/7] security: kernel_pinctrl: fixup pinctrl in kernel dts Fabian Pflug
6 siblings, 0 replies; 11+ messages in thread
From: Fabian Pflug @ 2026-03-24 9:52 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer; +Cc: Fabian Pflug
When using security policies to disable console input on the default
console, it might be more advantagous to also disable the RX pin hard
in pinctrl, so that if there is a software error with the security
policy implementation input does not reach to system and cannot be
exploited.
An example devicetree could look like this:
/ {
chosen {
stdout-path = &uart3;
};
};
&uart3 {
pinctrl-names = "default", "barebox,policy-devel-default";
pinctrl-0 = <&pinctrl_uart3_tx_only>;
pinctrl-1 = <&pinctrl_uart3_interactive>;
status = "okay";
};
&iomuxc {
pinctrl_uart3_interactive: uart3ingrp {
fsl,pins = <MX8MP_IOMUXC_SD1_DATA6__UART3_DCE_TX 0x140>,
<MX8MP_IOMUXC_SD1_DATA7__UART3_DCE_RX 0x140>;
};
pinctrl_uart3_tx_only: uart3txgrp {
fsl,pins = <MX8MP_IOMUXC_SD1_DATA6__UART3_DCE_TX 0x140>,
<MX8MP_IOMUXC_SD1_DATA7__GPIO2_IO09 0x140>;
};
};
This would apply the devel pinmux on selecting the devel config and the
default on every other security policy configuration.
A Kconfig option to enable this feature has been chosen, because parsing
pinctrl and mapping the names is a lot of string operations, that could
increase boottime for a feature, that is maybe not needed for everyone.
Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
drivers/pinctrl/pinctrl.c | 73 +++++++++++++++++++++++++++++++++++++++++++++--
security/Kconfig.policy | 12 ++++++++
2 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c
index 01567aa5ae..eb4103c5fd 100644
--- a/drivers/pinctrl/pinctrl.c
+++ b/drivers/pinctrl/pinctrl.c
@@ -10,11 +10,22 @@
#include <linux/overflow.h>
#include <errno.h>
#include <of.h>
+#include <security/config.h>
+#include <security/policy.h>
struct pinctrl {
struct device_node consumer_np;
};
+LIST_HEAD(pinctrl_devices_name_list);
+
+struct pinctrl_devices_name_info {
+ struct device_node *node;
+ const char *name;
+ struct list_head list;
+};
+
+
static LIST_HEAD(pinctrl_consumer_list);
struct pinctrl_state {
@@ -218,15 +229,48 @@ int pinctrl_select_state(struct pinctrl *pinctrl, struct pinctrl_state *state)
return ret;
}
+static void of_pinctrl_policy_update_or_add(struct device_node *np, const char *name)
+{
+ struct pinctrl_devices_name_info *dev;
+
+ list_for_each_entry(dev, &pinctrl_devices_name_list, list) {
+ if (dev->node == np) {
+ free_const(dev->name);
+ dev->name = xstrdup_const(name);
+ return;
+ }
+ }
+ dev = xzalloc(sizeof(*dev));
+ dev->node = np;
+ dev->name = xstrdup_const(name);
+ list_add(&dev->list, &pinctrl_devices_name_list);
+}
+
int of_pinctrl_select_state(struct device_node *np, const char *name)
{
struct pinctrl *pinctrl = of_pinctrl_get(np);
- struct pinctrl_state *state;
+ struct pinctrl_state *state = NULL;
if (!of_find_property(np, "pinctrl-0", NULL))
return 0;
- state = pinctrl_lookup_state(pinctrl, name);
+ if (IS_ENABLED(CONFIG_SECURITY_POLICY_PINCTRL)) {
+ const struct security_policy *active_policy = security_policy_get_active();
+
+ of_pinctrl_policy_update_or_add(np, name);
+
+ if (active_policy && active_policy->name && name) {
+ char *policy_pinctrl;
+
+ policy_pinctrl = basprintf("barebox,policy-%s-%s",
+ active_policy->name,
+ name);
+ state = pinctrl_lookup_state(pinctrl, policy_pinctrl);
+ free(policy_pinctrl);
+ }
+ }
+ if (IS_ERR_OR_NULL(state))
+ state = pinctrl_lookup_state(pinctrl, name);
if (IS_ERR(state))
return PTR_ERR(state);
@@ -331,3 +375,28 @@ void of_pinctrl_unregister_consumer(struct device *dev)
}
}
#endif
+
+static int pinctrl_change_policy(struct notifier_block *nb,
+ unsigned long _ignored,
+ void *_data)
+{
+ struct pinctrl_devices_name_info *dev;
+
+ list_for_each_entry(dev, &pinctrl_devices_name_list, list) {
+ of_pinctrl_select_state(dev->node, dev->name);
+ }
+ return 0;
+}
+
+static struct notifier_block pinctrl_policy_notifier = {
+ .notifier_call = pinctrl_change_policy
+};
+
+static int pinctrl_policy_init(void)
+{
+ if (!IS_ENABLED(CONFIG_SECURITY_POLICY_PINCTRL))
+ return 0;
+
+ return notifier_chain_register(&sconfig_name_notifier, &pinctrl_policy_notifier);
+}
+pure_initcall(pinctrl_policy_init);
diff --git a/security/Kconfig.policy b/security/Kconfig.policy
index e778327b0d..2c8e8399a0 100644
--- a/security/Kconfig.policy
+++ b/security/Kconfig.policy
@@ -69,6 +69,18 @@ config SECURITY_POLICY_DEFAULT_PERMISSIVE
A security policy should always be selected, either early on by
board code or via CONFIG_SECURITY_POLICY_INIT.
+config SECURITY_POLICY_PINCTRL
+ bool "Update pinctrl based on policy-name"
+ help
+ When selecting a pinctrl with the name <pinctrlname>, if there exists
+ a pinctrl with the name barebox,policy-<policyname>-<pinctrlname>,
+ then this pinctrl will be used instead.
+ This could be used for example to disable the RX (and TX) Pin in
+ lockdown mode for the console or disable the usage of SPI.
+
+ Enabling this option does increase the boottime.
+ If unsure, say N.
+
config SECURITY_POLICY_PATH
string
depends on SECURITY_POLICY
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v6 7/7] security: kernel_pinctrl: fixup pinctrl in kernel dts
2026-03-24 9:52 [PATCH v6 0/7] Add helper for security policies Fabian Pflug
` (5 preceding siblings ...)
2026-03-24 9:52 ` [PATCH v6 6/7] drivers: pinctrl: configure pinctrl based on policy name Fabian Pflug
@ 2026-03-24 9:52 ` Fabian Pflug
2026-03-24 14:57 ` Ahmad Fatoum
6 siblings, 1 reply; 11+ messages in thread
From: Fabian Pflug @ 2026-03-24 9:52 UTC (permalink / raw)
To: BAREBOX, Sascha Hauer; +Cc: Fabian Pflug
Going through the kernel dts and replacing
barebox,policy-<active_policy>-<name> with <name> and <name> with
old_<name> if a policy pinctrl has ben found in order to change pinctrl
not only for barebox, but also for kernel when booting with security
profiles.
Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
security/Makefile | 1 +
security/kernel_pinctrl.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+)
diff --git a/security/Makefile b/security/Makefile
index 1096cbfb9b..2e8cdfe7c2 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -2,6 +2,7 @@
obj-$(CONFIG_SECURITY_POLICY) += policy.o
obj-$(CONFIG_SECURITY_POLICY_NAMES) += sconfig_names.o
+obj-$(CONFIG_SECURITY_POLICY_PINCTRL) += kernel_pinctrl.o
obj-$(CONFIG_CRYPTO_KEYSTORE) += keystore.o
obj-$(CONFIG_JWT) += jwt.o
obj-pbl-$(CONFIG_HAVE_OPTEE) += optee.o
diff --git a/security/kernel_pinctrl.c b/security/kernel_pinctrl.c
new file mode 100644
index 0000000000..f02acdfd55
--- /dev/null
+++ b/security/kernel_pinctrl.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <linux/printk.h>
+#include <pinctrl.h>
+#include <security/policy.h>
+#include <security/config.h>
+
+/* Maximun number of names to be available in pinctrl-names. Best guess.*/
+#define MAX_NAMES 10
+
+
+/**
+ * Replace 'default' with 'old_default' and 'barebox,policy-<active_policy>-default'
+ * with 'default', if both are found in pinctrl.
+ * Same for every other name, that starts with barebox,policy-<active_policy>- and
+ * has another name without the prefix.
+ */
+static int kernel_of_fixup_pinctrl(struct device_node *root, void *unused)
+{
+ char *basename;
+ int base_len;
+ struct device_node *node;
+ const struct security_policy *active_policy = security_policy_get_active();
+
+ if (!active_policy || !active_policy->name)
+ return -EINVAL;
+ basename = basprintf("barebox,policy-%s-", active_policy->name);
+ base_len = strlen(basename);
+
+ list_for_each_entry(node, &root->list, list) {
+ const char *names[MAX_NAMES];
+ int num_read;
+ bool changed = false;
+
+ num_read = of_property_read_string_array(node, "pinctrl-names", names, MAX_NAMES);
+
+ for (int i = 0; i < num_read; i++) {
+ if (strncmp(basename, names[i], base_len) == 0) {
+ const char *name = names[i] + base_len;
+
+ for (int ii = 0; ii < num_read; ii++) {
+ if (strcmp(name, names[ii]) == 0) {
+ /* this never gets freed,
+ * but we are starting the kernel,
+ * so there should be no problem.
+ */
+ names[ii] = basprintf("old_%s", name);
+ names[i] = name;
+ changed = true;
+ break;
+ }
+ }
+ }
+ }
+ if (changed)
+ of_property_write_string_array(node, "pinctrl-names", names, num_read);
+ }
+ free(basename);
+ return 0;
+}
+
+static int policy_console_pinctrl_init(void)
+{
+ return of_register_fixup(kernel_of_fixup_pinctrl, NULL);
+}
+late_initcall(policy_console_pinctrl_init);
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v6 5/7] common: bootm: add policy to commandline
2026-03-24 9:52 ` [PATCH v6 5/7] common: bootm: add policy to commandline Fabian Pflug
@ 2026-03-24 14:34 ` Ahmad Fatoum
0 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2026-03-24 14:34 UTC (permalink / raw)
To: Fabian Pflug, BAREBOX, Sascha Hauer
Hello,
On 3/24/26 10:52 AM, Fabian Pflug wrote:
> + if (IS_ENABLED(CONFIG_SECURITY_POLICY) && bootm_data->provide_policy) {
> + char *policy_bootargs;
> + const struct security_policy *active_policy = security_policy_get_active();
if active_policy is set to NULL here
> +
> + if (active_policy && !active_policy->name) {
This is skipped
> + pr_err("Providing policy is enabled but policy has no name\n");
> + ret = -EINVAL;
> + goto err_out;
> + }
> +
> + policy_bootargs = basprintf("barebox.security.policy=%s", active_policy->name);
and here you have a NULL pointer dereference.
Instead you likely want to have
if (!active_policy || !active_policy->name)
Although, I find the active_policy->name check unnecessary as there is
always a name, because sconfigpost always emits one.
Cheers,
Ahmad
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v6 2/7] security: policy: sanity check parameters
2026-03-24 9:52 ` [PATCH v6 2/7] security: policy: sanity check parameters Fabian Pflug
@ 2026-03-24 14:35 ` Ahmad Fatoum
0 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2026-03-24 14:35 UTC (permalink / raw)
To: Fabian Pflug, BAREBOX, Sascha Hauer
Hi,
On 3/24/26 10:52 AM, Fabian Pflug wrote:
> Do a sanity check for the the is_allowed, before using it as array
> index.
>
> Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
> ---
> commands/sconfig.c | 7 ++++++-
> security/policy.c | 2 ++
> 2 files changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/commands/sconfig.c b/commands/sconfig.c
> index 02c3a6b1ed..3ca4478270 100644
> --- a/commands/sconfig.c
> +++ b/commands/sconfig.c
> @@ -37,7 +37,12 @@ static void sconfig_print(const struct security_policy *policy)
> static int sconfig_command_notify(struct notifier_block *nb,
> unsigned long opt, void *unused)
> {
> - bool allow = is_allowed(NULL, opt);
> + bool allow;
> +
> + if (opt >= SCONFIG_NUM)
> + return 0;
Here you use >=
> +
> + allow = is_allowed(NULL, opt);
>
> printf("%s%s%s%s\n", allow ? green : red, allow ? "+" : "-", nc,
> sconfig_names[opt]);
> diff --git a/security/policy.c b/security/policy.c
> index 85333d9e6f..95e7bf99a2 100644
> --- a/security/policy.c
> +++ b/security/policy.c
> @@ -52,6 +52,8 @@ static bool __is_allowed(const struct security_policy *policy, unsigned option)
> {
> if (!policy)
> return true;
> + if (WARN(option > SCONFIG_NUM))
> + return false;
and here only >
I think you want both to be >= because option is an index?
Thanks,
Ahmad
>
> return policy->policy[option];
> }
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v6 7/7] security: kernel_pinctrl: fixup pinctrl in kernel dts
2026-03-24 9:52 ` [PATCH v6 7/7] security: kernel_pinctrl: fixup pinctrl in kernel dts Fabian Pflug
@ 2026-03-24 14:57 ` Ahmad Fatoum
0 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2026-03-24 14:57 UTC (permalink / raw)
To: Fabian Pflug, BAREBOX, Sascha Hauer
On 3/24/26 10:52 AM, Fabian Pflug wrote:
> Going through the kernel dts and replacing
> barebox,policy-<active_policy>-<name> with <name> and <name> with
> old_<name> if a policy pinctrl has ben found in order to change pinctrl
been
> not only for barebox, but also for kernel when booting with security
> profiles.
>
> Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
> ---
> security/Makefile | 1 +
> security/kernel_pinctrl.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 68 insertions(+)
>
> diff --git a/security/Makefile b/security/Makefile
> index 1096cbfb9b..2e8cdfe7c2 100644
> --- a/security/Makefile
> +++ b/security/Makefile
> @@ -2,6 +2,7 @@
>
> obj-$(CONFIG_SECURITY_POLICY) += policy.o
> obj-$(CONFIG_SECURITY_POLICY_NAMES) += sconfig_names.o
> +obj-$(CONFIG_SECURITY_POLICY_PINCTRL) += kernel_pinctrl.o
> obj-$(CONFIG_CRYPTO_KEYSTORE) += keystore.o
> obj-$(CONFIG_JWT) += jwt.o
> obj-pbl-$(CONFIG_HAVE_OPTEE) += optee.o
> diff --git a/security/kernel_pinctrl.c b/security/kernel_pinctrl.c
> new file mode 100644
> index 0000000000..f02acdfd55
> --- /dev/null
> +++ b/security/kernel_pinctrl.c
> @@ -0,0 +1,67 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#include <common.h>
> +#include <linux/printk.h>
> +#include <pinctrl.h>
> +#include <security/policy.h>
> +#include <security/config.h>
> +
> +/* Maximun number of names to be available in pinctrl-names. Best guess.*/
Maximum
> +#define MAX_NAMES 10
> +
> +
> +/**
> + * Replace 'default' with 'old_default' and 'barebox,policy-<active_policy>-default'
> + * with 'default', if both are found in pinctrl.
> + * Same for every other name, that starts with barebox,policy-<active_policy>- and
> + * has another name without the prefix.
> + */
> +static int kernel_of_fixup_pinctrl(struct device_node *root, void *unused)
> +{
> + char *basename;
> + int base_len;
> + struct device_node *node;
> + const struct security_policy *active_policy = security_policy_get_active();
> +
> + if (!active_policy || !active_policy->name)
> + return -EINVAL;
> + basename = basprintf("barebox,policy-%s-", active_policy->name);
> + base_len = strlen(basename);
> +
> + list_for_each_entry(node, &root->list, list) {
> + const char *names[MAX_NAMES];
> + int num_read;
> + bool changed = false;
> +
> + num_read = of_property_read_string_array(node, "pinctrl-names", names, MAX_NAMES);
I haven't seen a device with 10 pincontrol groups, but it would be good
to emit a warning message here if it happens.
You can use of_property_count_strings() to count the strings.
> +
> + for (int i = 0; i < num_read; i++) {
> + if (strncmp(basename, names[i], base_len) == 0) {
> + const char *name = names[i] + base_len;
> +
> + for (int ii = 0; ii < num_read; ii++) {
> + if (strcmp(name, names[ii]) == 0) {
> + /* this never gets freed,
> + * but we are starting the kernel,
> + * so there should be no problem.
> + */
> + names[ii] = basprintf("old_%s", name);
> + names[i] = name;
> + changed = true;
> + break;
> + }
> + }
> + }
> + }
> + if (changed)
> + of_property_write_string_array(node, "pinctrl-names", names, num_read);
> + }
> + free(basename);
> + return 0;
> +}
> +
> +static int policy_console_pinctrl_init(void)
Misleading name
> +{
> + return of_register_fixup(kernel_of_fixup_pinctrl, NULL);
> +}
> +late_initcall(policy_console_pinctrl_init);
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-03-24 14:58 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-24 9:52 [PATCH v6 0/7] Add helper for security policies Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 1/7] of: add of_property_write_string_array() Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 2/7] security: policy: sanity check parameters Fabian Pflug
2026-03-24 14:35 ` Ahmad Fatoum
2026-03-24 9:52 ` [PATCH v6 3/7] security: policy: remove global active_policy var Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 4/7] security: policy: add notifier chain for name change Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 5/7] common: bootm: add policy to commandline Fabian Pflug
2026-03-24 14:34 ` Ahmad Fatoum
2026-03-24 9:52 ` [PATCH v6 6/7] drivers: pinctrl: configure pinctrl based on policy name Fabian Pflug
2026-03-24 9:52 ` [PATCH v6 7/7] security: kernel_pinctrl: fixup pinctrl in kernel dts Fabian Pflug
2026-03-24 14:57 ` Ahmad Fatoum
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox