LSM: Add lsm= boot parameter
RFC PATCH 1/1 LSM: Add lsm= boot parameter
Hi everybody,
This is a first try of adding lsm= boot parameter.
Current situation is:
1- Ignore wrong input, with a small warning to users. 2- If user didn't specify a specific module, none will be loaded
Basically, the patch adds a @name attribute to each LSM. It also adds a security_module_chosen(op) method where each LSM _must_ pass before calling register_security().
Thanks,
Documentation/kernel-parameters.txt | 4 ++++ include/linux/security.h | 10 ++++++++++ security/dummy.c | 3 ++- security/security.c | 35 +++++++++++++++++++++++++++++++++++ security/selinux/hooks.c | 5 ++++- security/smack/smack_lsm.c | 7 +++++++ 6 files changed, 62 insertions(+), 2 deletions(-)
---
Documentation/kernel-parameters.txt +4 -0
@@ -374,6 +374,10 @@ and is between 256 and 4096 characters. It is defined in the file possible to determine what the correct size should be. This option provides an override for these situations. + lsm= [SECURITY] Choose an LSM to enable at boot. If this boot + parameter is not specified, no security module will be + loaded. + capability.disable= [SECURITY] Disable capabilities. This would normally be used only if an alternative security model is to be
include/linux/security.h +10 -0
@@ -42,6 +42,9 @@extern unsigned securebits; +/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10 +struct ctl_table ;struct audit_krule ;
@@ -118,6 +121,10 @@ struct request_sock;/** * struct security_operations - main security structure * +* Security module identifier. +* +* @name: LSM name +* * Security hooks for program execution operations. * * @bprm_alloc_security:
@@ -1262,6 +1269,8 @@ struct request_sock;* This is the main security structure. */ struct security_operations { +char name[SECURITY_NAME_MAX +1 ]; +int (*ptrace) (struct task_struct * parent,struct task_struct * child); int (*capget) (struct task_struct * target, kernel_cap_t * effective,
@@ -1530,6 +1539,7 @@ struct security_operations {/* prototypes */ extern int security_init (void ); +extern int security_module_chosen (struct security_operations *ops);extern int register_security (struct security_operations *ops);extern int mod_reg_security (const char *name,struct security_operations *ops); extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
security/dummy.c +2 -1
@@ -1022,7 +1022,7 @@ static inline void dummy_audit_rule_free(void *lsmrule)#endif /* CONFIG_AUDIT */ -struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = {"dummy" };#define set_to_dummy_if_null (ops, function) \ do { \
@@ -1035,6 +1035,7 @@ struct security_operations dummy_security_ops;void security_fixup_ops (struct security_operations *ops) { +BUG_ON (!ops->name);set_to_dummy_if_null (ops, ptrace);set_to_dummy_if_null (ops, capget);set_to_dummy_if_null (ops, capset_check);
security/security.c +35 -0
@@ -17,6 +17,8 @@#include <linux/kernel.h> #include <linux/security.h> +/* Boot time LSM user choice */ +char chosen_lsm[SECURITY_NAME_MAX +1 ];/* things that live in dummy.c */ extern struct security_operations dummy_security_ops;
@@ -67,6 +69,39 @@ int __init security_init(void)return 0 ; } +/* Save user chosen LSM */ +static int __init choose_lsm (char *str) +{ +if (strlen (str) >SECURITY_NAME_MAX ) { +printk (KERN_INFO "Security: LSM name length extends possible " +"limit.\n" ); +printk (KERN_INFO "Security: Ignoring passed lsm= parameter.\n" ); +return 0 ; + } + +strncpy (chosen_lsm, str,SECURITY_NAME_MAX ); +return 1 ; +} +__setup ("lsm=" , choose_lsm); + +/** +* security_module_chosen - Load given security module on boot ? +* @ops: a pointer to the struct security_operations that is to be checked. +* +* Return true if the passed LSM is the one chosen by user at +* boot time, otherwise return false. +*/ +int security_module_chosen (struct security_operations *ops) +{ +if (!ops || !ops->name) +return 0 ; + +if (strncmp (ops->name, chosen_lsm,SECURITY_NAME_MAX )) +return 0 ; + +return 1 ; +} +/** * register_security - registers a security framework with the kernel * @ops: a pointer to the struct security_options that is to be registered
security/selinux/hooks.c +4 -1
@@ -5247,6 +5247,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)#endif static struct security_operations selinux_ops = { + .name ="selinux" , + .ptrace = selinux_ptrace, .capget = selinux_capget, .capset_check = selinux_capset_check,
@@ -5443,7 +5445,8 @@ static __init int selinux_init(void) {struct task_security_struct *tsec; -if (!selinux_enabled) { +if (!selinux_enabled || !security_module_chosen (&selinux_ops)) { + selinux_enabled =0 ;printk (KERN_INFO "SELinux: Disabled at boot.\n" );return 0 ; }
security/smack/smack_lsm.c +7 -0
@@ -2358,6 +2358,8 @@ static void smack_release_secctx(char *secdata, u32 seclen) }static struct security_operations smack_ops = { + .name ="smack" , + .ptrace = smack_ptrace, .capget = cap_capget, .capset_check = cap_capset_check,
@@ -2485,6 +2487,11 @@ static struct security_operations smack_ops = {*/ static __init int smack_init (void ) { +if (!security_module_chosen (&smack_ops)) { +printk (KERN_INFO "Smack: Disabled at boot.\n" ); +return 0 ; + } +printk (KERN_INFO "Smack: Initializing.\n" );/*
Signature · 5 lines
"Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
Casey Schaufler
maintainerQuoted 7 lines · --- "Ahmed S. Darwish
Hi everybody,
This is a first try of adding lsm= boot parameter.
Current situation is:
1- Ignore wrong input, with a small warning to users. 2- If user didn't specify a specific module, none will be loaded
I'm not fond of this behavior for the case where only one LSM has been built in. Fedora, for example, ought to boot SELinux without specifing lsm=SELinux, and all the rest should boot whatever they are built with. In the case where a kernel is built with conflicting LSMs (today SELinux and Smack) I see this as a useful way to decide which to use until you get your kernel rebuilt sanely, so it appears to be worth having.
Quoted 213 lines
Basically, the patch adds a @name attribute to each LSM. It also adds a
security_module_chosen(op)method where each LSM _must_ pass before callingregister_security().Thanks,
Documentation/kernel-parameters.txt | 4 ++++ include/linux/security.h | 10 ++++++++++ security/dummy.c | 3 ++- security/security.c | 35 +++++++++++++++++++++++++++++++++++ security/selinux/hooks.c | 5 ++++- security/smack/smack_lsm.c | 7 +++++++ 6 files changed, 62 insertions(+), 2 deletions(-)Signed-off-by Ahmed S. Darwish <[email protected]>---
Documentation/kernel-parameters.txt +0
-0@@ -374,6 +374,10 @@ and is between 256 and 4096 characters. It is defined inthe file
Documentation/kernel-parameters.txt +4
-0possible to determine what the correct size should be. This option provides an override for these situations. + lsm= [SECURITY] Choose an LSM to enable at boot. If this boot + parameter is not specified, no security module will be + loaded. + capability.disable= [SECURITY] Disable capabilities. This would normally be used only if an alternative security model is to beinclude/linux/security.h +10
-0@@ -42,6 +42,9 @@extern unsigned securebits; +/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10 +struct ctl_table ;struct audit_krule ;@@ -118,6 +121,10 @@ struct request_sock;/** * struct security_operations - main security structure * +* Security module identifier. +* +* @name: LSM name +* * Security hooks for program execution operations. * * @bprm_alloc_security: @@ -1262,6 +1269,8 @@ struct request_sock;* This is the main security structure. */ struct security_operations { +char name[SECURITY_NAME_MAX +1 ]; +int (*ptrace) (struct task_struct * parent,struct task_struct * child); int (*capget) (struct task_struct * target, kernel_cap_t * effective,@@ -1530,6 +1539,7 @@ struct security_operations {/* prototypes */ extern int security_init (void ); +extern int security_module_chosen (struct security_operations *ops);extern int register_security (struct security_operations *ops);extern int mod_reg_security (const char *name,struct security_operations *ops);extern struct dentry *securityfs_create_file(const char *name,
mode_tmode,security/dummy.c +2
-1@@ -1022,7 +1022,7 @@ static inline void dummy_audit_rule_free(void *lsmrule)#endif /* CONFIG_AUDIT */ -struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = {"dummy" };#define set_to_dummy_if_null (ops, function) \ do { \@@ -1035,6 +1035,7 @@ struct security_operations dummy_security_ops;void security_fixup_ops (struct security_operations *ops) { +BUG_ON (!ops->name);set_to_dummy_if_null (ops, ptrace);set_to_dummy_if_null (ops, capget);set_to_dummy_if_null (ops, capset_check);security/security.c +35
-0@@ -17,6 +17,8 @@#include <linux/kernel.h> #include <linux/security.h> +/* Boot time LSM user choice */ +char chosen_lsm[SECURITY_NAME_MAX +1 ];/* things that live in dummy.c */ extern struct security_operations dummy_security_ops;@@ -67,6 +69,39 @@ int __init security_init(void)return 0 ; } +/* Save user chosen LSM */ +static int __init choose_lsm (char *str) +{ +if (strlen (str) >SECURITY_NAME_MAX ) { +printk (KERN_INFO "Security: LSM name length extends possible " +"limit.\n" ); +printk (KERN_INFO "Security: Ignoring passed lsm= parameter.\n" ); +return 0 ; + } + +strncpy (chosen_lsm, str,SECURITY_NAME_MAX ); +return 1 ; +} +__setup ("lsm=" , choose_lsm); + +/** +* security_module_chosen - Load given security module on boot ? +* @ops: a pointer to the struct security_operations that is to be checked. +* +* Return true if the passed LSM is the one chosen by user at +* boot time, otherwise return false. +*/ +int security_module_chosen (struct security_operations *ops) +{ +if (!ops || !ops->name) +return 0 ; + +if (strncmp (ops->name, chosen_lsm,SECURITY_NAME_MAX )) +return 0 ; + +return 1 ; +} +/** * register_security - registers a security framework with the kernel * @ops: a pointer to the struct security_options that is to be registered security/selinux/hooks.c +2
-0@@ -5247,6 +5247,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)#endif static struct security_operations selinux_ops = { + .name ="selinux" , + .ptrace = selinux_ptrace, .capget = selinux_capget,security/selinux/hooks.c +2
-1.capset_check = selinux_capset_check,@@ -5443,7 +5445,8 @@ static __init int selinux_init(void) {struct task_security_struct *tsec; -if (!selinux_enabled) { +if (!selinux_enabled || !security_module_chosen (&selinux_ops)) { + selinux_enabled =0 ;printk (KERN_INFO "SELinux: Disabled at boot.\n" );return 0 ; }security/smack/smack_lsm.c +2
-0@@ -2358,6 +2358,8 @@ static void smack_release_secctx(char *secdata, u32 seclen) }static struct security_operations smack_ops = { + .name ="smack" , + .ptrace = smack_ptrace, .capget = cap_capget,security/smack/smack_lsm.c +5
-0.capset_check = cap_capset_check,@@ -2485,6 +2487,11 @@ static struct security_operations smack_ops = {*/ static __init int smack_init (void ) { +if (!security_module_chosen (&smack_ops)) { +printk (KERN_INFO "Smack: Disabled at boot.\n" ); +return 0 ; + } +printk (KERN_INFO "Smack: Initializing.\n" );/* Signature · 7 lines
-- "Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
Casey Schaufler
[email protected]
Quoted 11 lines · Casey Schaufler
Quoted 7 lines · --- "Ahmed S. Darwish
Hi everybody,
This is a first try of adding lsm= boot parameter.
Current situation is:
1- Ignore wrong input, with a small warning to users. 2- If user didn't specify a specific module, none will be loaded
Quoted 8 lines
I'm not fond of this behavior for the case where only one LSM has been built in. Fedora, for example, ought to boot SELinux without specifing lsm=SELinux, and all the rest should boot whatever they are built with. In the case where a kernel is built with conflicting LSMs (today SELinux and Smack) I see this as a useful way to decide which to use until you get your kernel rebuilt sanely, so it appears to be worth having.
...
Remarks:
Your comment would be covered if the default for this boot parameter (if not explicitely set through the boot loader would not be "disabled" but set through kconfig (based on the selected LSMs).
We should really get this resolved for 2.6.25.
security= suggestion is IMHO more intuitive than lsm=
cu
Adrian
Signature · 4 lines
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon SeedCasey Schaufler
maintainerQuoted 21 lines · --- Adrian Bunk
Quoted 11 lines · Casey Schaufler
Quoted 7 lines · --- "Ahmed S. Darwish
Hi everybody,
This is a first try of adding lsm= boot parameter.
Current situation is:
1- Ignore wrong input, with a small warning to users. 2- If user didn't specify a specific module, none will be loadedQuoted 8 lines
I'm not fond of this behavior for the case where only one LSM has been built in. Fedora, for example, ought to boot SELinux without specifing lsm=SELinux, and all the rest should boot whatever they are built with. In the case where a kernel is built with conflicting LSMs (today SELinux and Smack) I see this as a useful way to decide which to use until you get your kernel rebuilt sanely, so it appears to be worth having.
...
Quoted 5 lines
Remarks:
Your comment would be covered if the default for this boot parameter (if not explicitely set through the boot loader would not be "disabled" but set through kconfig (based on the selected LSMs).
Agreed.
Quoted 1 line
We should really get this resolved for 2.6.25.
Agreed.
Quoted 1 line
security= suggestion is IMHO more intuitive than lsm=
security is a very overloaded term, but since this is one of the ways it's already loaded in I could be OK with that.
Casey Schaufler
[email protected]
PATCH 1/1 LSM: Add security= boot parameter
Hi!,
Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module.
User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen.
LSM modules must check now if they are allowed to register by calling security_module_enable(ops) first. Modify SELinux and SMACK to do so.
---
I'll send a similar patch for 2.6.25 if no more concerns for the patch exist.
Adrian, Casey, Does this one have any more issues ?
Documentation/kernel-parameters.txt | 6 ++++ include/linux/security.h | 12 +++++++++ security/dummy.c | 3 +- security/security.c | 47 +++++++++++++++++++++++++++++++++++- security/selinux/hooks.c | 5 +++ security/smack/smack_lsm.c | 7 +++++
6 files changed, 77 insertions(+), 3 deletions(-)
Documentation/kernel-parameters.txt +6 -0
@@ -374,6 +374,12 @@ and is between 256 and 4096 characters. It is defined in the file possible to determine what the correct size should be. This option provides an override for these situations. + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be + loaded. An invalid security module name will be treated + as if no module has been chosen. + capability.disable= [SECURITY] Disable capabilities. This would normally be used only if an alternative security model is to be
include/linux/security.h +12 -0
@@ -42,6 +42,9 @@extern unsigned securebits; +/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10 +struct ctl_table ;/*
@@ -117,6 +120,12 @@ struct request_sock;/** * struct security_operations - main security structure * +* Security module identifier. +* +* @name: +* A string that acts as unique identifeir for the LSM with max number +* of characters = SECURITY_NAME_MAX. +* * Security hooks for program execution operations. * * @bprm_alloc_security:
@@ -1218,6 +1227,8 @@ struct request_sock;* This is the main security structure. */ struct security_operations { +char name[SECURITY_NAME_MAX +1 ]; +int (*ptrace) (struct task_struct * parent,struct task_struct * child); int (*capget) (struct task_struct * target, kernel_cap_t * effective,
@@ -1477,6 +1488,7 @@ struct security_operations {/* prototypes */ extern int security_init (void ); +extern int security_module_enable (struct security_operations *ops);extern int register_security (struct security_operations *ops);extern int mod_reg_security (const char *name,struct security_operations *ops); extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
security/dummy.c +2 -1
@@ -986,7 +986,7 @@ static int dummy_key_getsecurity(struct key *key, char **_buffer)#endif /* CONFIG_KEYS */ -struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = {"dummy" };#define set_to_dummy_if_null (ops, function) \ do { \
@@ -999,6 +999,7 @@ struct security_operations dummy_security_ops;void security_fixup_ops (struct security_operations *ops) { +BUG_ON (!ops->name);set_to_dummy_if_null (ops, ptrace);set_to_dummy_if_null (ops, capget);set_to_dummy_if_null (ops, capset_check);
security/security.c +46 -1
71 lines not on this page · raw message
security/selinux/hooks.c +4 -1
@@ -5233,6 +5233,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)#endif static struct security_operations selinux_ops = { + .name ="selinux" , + .ptrace = selinux_ptrace, .capget = selinux_capget, .capset_check = selinux_capset_check,
@@ -5420,7 +5422,8 @@ static __init int selinux_init(void) {struct task_security_struct *tsec; -if (!selinux_enabled) { +if (!selinux_enabled || !security_module_enable (&selinux_ops)) { + selinux_enabled =0 ;printk (KERN_INFO "SELinux: Disabled at boot.\n" );return 0 ; }
security/smack/smack_lsm.c +7 -0
@@ -2358,6 +2358,8 @@ static void smack_release_secctx(char *secdata, u32 seclen) }static struct security_operations smack_ops = { + .name ="smack" , + .ptrace = smack_ptrace, .capget = cap_capget, .capset_check = cap_capset_check,
@@ -2485,6 +2487,11 @@ static struct security_operations smack_ops = {*/ static __init int smack_init (void ) { +if (!security_module_enable (&smack_ops)) { +printk (KERN_INFO "Smack: Disabled at boot.\n" ); +return 0 ; + } +printk (KERN_INFO "Smack: Initializing.\n" );/*
Signature · 5 lines
"Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
Casey Schaufler
maintainerRe: [PATCH -v2 -mm] LSM: Add security= boot parameter
Quoted 39 lines · --- "Ahmed S. Darwish
Hi!,
Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module.
User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen.
LSM modules must check now if they are allowed to register by calling
security_module_enable(ops)first. Modify SELinux and SMACK to do so.Signed-off-by Ahmed S. Darwish <[email protected]>---
I'll send a similar patch for 2.6.25 if no more concerns for the patch exist.
Adrian, Casey, Does this one have any more issues ?
Documentation/kernel-parameters.txt | 6 ++++ include/linux/security.h | 12 +++++++++ security/dummy.c | 3 +- security/security.c | 47 +++++++++++++++++++++++++++++++++++- security/selinux/hooks.c | 5 +++ security/smack/smack_lsm.c | 7 +++++6 files changed, 77 insertions(+), 3 deletions(-)Documentation/kernel-parameters.txt +0
-0@@ -374,6 +374,12 @@ and is between 256 and 4096 characters. It is defined inthe file
Documentation/kernel-parameters.txt and is between 256 and 4096 characters. It is defined in the file · line 382
Quoted 9 lines
Documentation/kernel-parameters.txt +6
-0possible to determine what the correct size should be. This option provides an override for these situations. + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be + loaded. An invalid security module name will be treated + as if no module has been chosen. +
Yes, this is better.
Quoted 163 lines
Documentation/kernel-parameters.txt +0
-0capability.disable= [SECURITY] Disable capabilities. This would normally be used only if an alternative security model is to beinclude/linux/security.h +12
-0@@ -42,6 +42,9 @@extern unsigned securebits; +/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10 +struct ctl_table ;/* @@ -117,6 +120,12 @@ struct request_sock;/** * struct security_operations - main security structure * +* Security module identifier. +* +* @name: +* A string that acts as unique identifeir for the LSM with max number +* of characters = SECURITY_NAME_MAX. +* * Security hooks for program execution operations. * * @bprm_alloc_security: @@ -1218,6 +1227,8 @@ struct request_sock;* This is the main security structure. */ struct security_operations { +char name[SECURITY_NAME_MAX +1 ]; +int (*ptrace) (struct task_struct * parent,struct task_struct * child); int (*capget) (struct task_struct * target, kernel_cap_t * effective,@@ -1477,6 +1488,7 @@ struct security_operations {/* prototypes */ extern int security_init (void ); +extern int security_module_enable (struct security_operations *ops);extern int register_security (struct security_operations *ops);extern int mod_reg_security (const char *name,struct security_operations *ops);extern struct dentry *securityfs_create_file(const char *name,
mode_tmode,security/dummy.c +1
-1@@ -986,7 +986,7 @@ static int dummy_key_getsecurity(struct key *key, char **_buffer)#endif /* CONFIG_KEYS */ -struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = {"dummy" };#define set_to_dummy_if_null (ops, function) \security/dummy.c +1
-0do { \@@ -999,6 +999,7 @@ struct security_operations dummy_security_ops;void security_fixup_ops (struct security_operations *ops) { +BUG_ON (!ops->name);set_to_dummy_if_null (ops, ptrace);set_to_dummy_if_null (ops, capget);set_to_dummy_if_null (ops, capset_check);security/security.c +46
-1@@ -17,6 +17,9 @@#include <linux/kernel.h> #include <linux/security.h> +/* Boot-time LSM user choice */ +static char chosen_lsm[SECURITY_NAME_MAX +1 ]; +static atomic_t security_ops_registered =ATOMIC_INIT (0 );/* things that live in dummy.c */ extern struct security_operations dummy_security_ops;@@ -67,13 +70,54 @@ int __init security_init(void)return 0 ; } +/* Save user chosen LSM */ +static int __init choose_lsm (char *str) +{ +if (strlen (str) >SECURITY_NAME_MAX ) { +printk (KERN_INFO "Security: LSM name length extends possible" +"limit.\n" ); +printk (KERN_INFO "Security: Ignoring passed security= " +"parameter.\n" ); +return 0 ; + } + +strncpy (chosen_lsm, str,SECURITY_NAME_MAX ); +return 1 ; +} +__setup ("security=" , choose_lsm); + +/** +* security_module_enable - Load given security module on boot ? +* @ops: a pointer to the struct security_operations that is to be checked. +* +* Return true if: +* -The passed LSM is the one chosen by user at boot time, +* -or user didsn't specify a specific LSM and we're the first to ask +* for registeration permissoin. +* Otherwise, return false. +*/ +int security_module_enable (struct security_operations *ops) +{ +if (!ops || !ops->name) +return 0 ; + +if (!*chosen_lsm && !atomic_read (&security_ops_registered)) +return 1 ; + +if (!strncmp (ops->name, chosen_lsm,SECURITY_NAME_MAX )) +return 1 ; + +return 0 ; +} +/** * register_security - registers a security framework with the kernel * @ops: a pointer to the struct security_options that is to be registered * * This function is to allow a security module to register itself with the * kernel security subsystem. Some rudimentary checking is done on the @ops -* value passed to this function. +* value passed to this function. You'll need to check first if your LSM +* is allowed to register by calling security_module_enable(@ops). * * If there is already a security module registered with the kernel, * an error will be returned. Otherwise 0 is returned on success. @@ -90,6 +134,7 @@ int register_security(struct security_operations *ops)return -EAGAIN ; security_ops = ops; +atomic_inc (&security_ops_registered);return 0 ; }security/selinux/hooks.c +2
-0@@ -5233,6 +5233,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)#endif static struct security_operations selinux_ops = { + .name ="selinux" , + .ptrace = selinux_ptrace, .capget = selinux_capget,security/selinux/hooks.c +0
-0.capset_check = selinux_capset_check,
security/selinux/hooks.c static __init int selinux_init(void) · line 5427
Quoted 7 lines
security/selinux/hooks.c +2
-1@@ -5420,7 +5422,8 @@ static __init int selinux_init(void) {struct task_security_struct *tsec; -if (!selinux_enabled) { +if (!selinux_enabled || !security_module_enable (&selinux_ops)) { + selinux_enabled =0 ;printk (KERN_INFO "SELinux: Disabled at boot.\n" );
How about "SELinux: Not enabled because LSM %s is already enabled.\n"
Quoted 17 lines
security/selinux/hooks.c +0
-0return 0 ; }security/smack/smack_lsm.c +2
-0@@ -2358,6 +2358,8 @@ static void smack_release_secctx(char *secdata, u32 seclen) }static struct security_operations smack_ops = { + .name ="smack" , + .ptrace = smack_ptrace, .capget = cap_capget,security/smack/smack_lsm.c +0
-0.capset_check = cap_capset_check,
security/smack/smack_lsm.c static struct security_operations smack_ops = { · line 2491
Quoted 5 lines
security/smack/smack_lsm.c +2
-0@@ -2485,6 +2487,11 @@ static struct security_operations smack_ops = {*/ static __init int smack_init (void ) { +if (!security_module_enable (&smack_ops)) { +printk (KERN_INFO "Smack: Disabled at boot.\n" );
How about "Smack: Not enabled because LSM %s is already enabled.\n"
Quoted 17 lines
security/smack/smack_lsm.c +3
-0+return 0 ; + } +printk (KERN_INFO "Smack: Initializing.\n" );/* Signature · 7 lines
-- "Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
Casey Schaufler
[email protected]
Re: [PATCH -v2 -mm] LSM: Add security= boot parameter
Quoted 3 lines · Casey Schaufler
Quoted 1 line · --- "Ahmed S. Darwish
...
Quoted 12 lines
Quoted 12 lines
static struct
security_operationsselinux_ops= {security/selinux/hooks.c +2
-0+ .name = "selinux", + .ptrace = selinux_ptrace, .capget = selinux_capget, .capset_check = selinux_capset_check,@@ -5420,7 +5422,8 @@ static __init int selinux_init(void) {struct task_security_struct *tsec;
Quoted 7 lines
security/selinux/hooks.c static __init int selinux_init(void) · line 5427
Quoted 4 lines
security/selinux/hooks.c +2
-1-if (!selinux_enabled) { +if (!selinux_enabled || !security_module_enable (&selinux_ops)) { + selinux_enabled =0 ;printk (KERN_INFO "SELinux: Disabled at boot.\n" );How about "SELinux: Not enabled because LSM %s is already enabled.\n"
Looks better. I'll resend the patch once I know the answer of the SMP point I asked about in the same thread.
Regards,
Signature · 5 lines
"Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
Re: [PATCH -v2 -mm] LSM: Add security= boot parameter
In reply to Ahmed S. DarwishQuoted 2 lines · Ahmed S. Darwish
Hi!,
...
Quoted 4 lines
LSM modules must check now if they are allowed to register by calling
security_module_enable(ops)first. Modify SELinux and SMACK to do so.
...
Quoted 5 lines
security/security.c +3
-0+/* Boot-time LSM user choice */ +static char chosen_lsm[SECURITY_NAME_MAX +1 ]; +static atomic_t security_ops_registered =ATOMIC_INIT (0 );
...
Quoted 8 lines
security/security.c +8
-0+int security_module_enable (struct security_operations *ops) +{ +if (!ops || !ops->name) +return 0 ; + +if (!*chosen_lsm && !atomic_read (&security_ops_registered)) +return 1 ; +
...
security/security.c int register_security(struct security_operations *ops) · line 138
Quoted 6 lines
security/security.c +1
-0@@ -90,6 +134,7 @@ int register_security(struct security_operations *ops)return -EAGAIN ; security_ops = ops; +atomic_inc (&security_ops_registered);
I'm worried about an implementation detail here. Must the LSM init calls sequence:
asmlinkage void __init start_kernel(void)
{
preempt_disable();
...
security_init();
...int __init security_init(void)
{
...
do_security_initcalls();
}
static void __init do_security_initcalls(void)
{
initcall_t *call;
call = __security_initcall_start;
while (call < __security_initcall_end) {
(*call) ();
call++;
}
}be SMP safe ?
In other words, can the two LSMs 'security_initcall()'s (i.e. smack_init() and selinux_init()) be executed concurrently ?
If so, this patch won't be safe.
I'll send a modified one once I know the answer.
Thanks everybody,
Signature · 5 lines
"Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
PATCH 1/1 LSM: Add security= boot parameter
Hi!,
[
Fixed two bugs:
- concurrency: incrementing and testing atomic_t in different places.
- overflow: not ending string with NULL after using strncpy().
- I'll never write a patch when I'm asleep, sorry :(
Added more verbose messages to SMACK and SELinux if they were not chosen on boot.
Casey: Failing to take permission to register an LSM does not mean that
the other has registered its security_ops yet. It just means that the other asked for allowance to call register_security(). It's not yet guraranteed that this registration succeeded.
This means that adding "SELinux: failed to load, LSM %s is loaded" may lead to %s = "dummy" in case of a highly concurrent SMP system.
]
-->
Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module.
User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen.
LSM modules must check now if they are allowed to register by calling security_module_enable(ops) first. Modify SELinux and SMACK to do so.
---
Documentation/kernel-parameters.txt | 6 ++++ include/linux/security.h | 12 +++++++++ security/dummy.c | 2 - security/security.c | 46 +++++++++++++++++++++++++++++++++--- security/selinux/hooks.c | 12 +++++++++ security/smack/smack_lsm.c | 11 ++++++++
6 files changed, 85 insertions(+), 4 deletions(-)
Documentation/kernel-parameters.txt +6 -0
@@ -374,6 +374,12 @@ and is between 256 and 4096 characters. It is defined in the file possible to determine what the correct size should be. This option provides an override for these situations. + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be + loaded. An invalid security module name will be treated + as if no module has been chosen. + capability.disable= [SECURITY] Disable capabilities. This would normally be used only if an alternative security model is to be
include/linux/security.h +12 -0
@@ -42,6 +42,9 @@extern unsigned securebits; +/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10 +struct ctl_table ;/*
@@ -117,6 +120,12 @@ struct request_sock;/** * struct security_operations - main security structure * +* Security module identifier. +* +* @name: +* A string that acts as a unique identifeir for the LSM with max number +* of characters = SECURITY_NAME_MAX. +* * Security hooks for program execution operations. * * @bprm_alloc_security:
@@ -1218,6 +1227,8 @@ struct request_sock;* This is the main security structure. */ struct security_operations { +char name[SECURITY_NAME_MAX +1 ]; +int (*ptrace) (struct task_struct * parent,struct task_struct * child); int (*capget) (struct task_struct * target, kernel_cap_t * effective,
@@ -1477,6 +1488,7 @@ struct security_operations {/* prototypes */ extern int security_init (void ); +extern int security_module_enable (struct security_operations *ops);extern int register_security (struct security_operations *ops);extern int mod_reg_security (const char *name,struct security_operations *ops); extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
security/dummy.c +1 -1
@@ -986,7 +986,7 @@ static int dummy_key_getsecurity(struct key *key, char **_buffer)#endif /* CONFIG_KEYS */ -struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = {"dummy" };#define set_to_dummy_if_null (ops, function) \ do { \
security/security.c +43 -2
69 lines not on this page · raw message
security/selinux/hooks.c +11 -0
@@ -5233,6 +5233,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)#endif static struct security_operations selinux_ops = { + .name ="selinux" , + .ptrace = selinux_ptrace, .capget = selinux_capget, .capset_check = selinux_capset_check,
@@ -5425,6 +5427,15 @@ static __init int selinux_init(void)return 0 ; } +if (!security_module_enable (&selinux_ops)) { + selinux_enabled =0 ; +printk (KERN_INFO "SELinux: Security registration was not allowed.\n" ); +printk (KERN_INFO "SELinux: Another security module was chosen.\n" ); +printk (KERN_INFO "SELinux: Use security=%s to force choosing " +"SELinux on boot.\n" , selinux_ops.name); +return 0 ; + } +printk (KERN_INFO "SELinux: Initializing.\n" );/* Set the security state for the initial task. */
security/smack/smack_lsm.c +10 -0
@@ -2358,6 +2358,8 @@ static void smack_release_secctx(char *secdata, u32 seclen) }static struct security_operations smack_ops = { + .name ="smack" , + .ptrace = smack_ptrace, .capget = cap_capget, .capset_check = cap_capset_check,
@@ -2485,6 +2487,14 @@ static struct security_operations smack_ops = {*/ static __init int smack_init (void ) { +if (!security_module_enable (&smack_ops)) { +printk (KERN_INFO "Smack: Security registration was not allowed.\n" ); +printk (KERN_INFO "Smack: Another security module was chosen.\n" ); +printk (KERN_INFO "Smack: Use security=%s to force choosing " +"Smack on boot.\n" , smack_ops.name); +return 0 ; + } +printk (KERN_INFO "Smack: Initializing.\n" );/*
---
"Better to light a candle, than curse the darkness"
Ahmed S. Darwish
Homepage: http://darwish.07.googlepages.com
Blog: http://darwish-07.blogspot.com
Casey Schaufler
maintainerRe: [PATCH -v3 -mm] LSM: Add security= boot parameter
Quoted 11 lines · --- "Ahmed S. Darwish
Hi!,
[
Fixed two bugs:
- concurrency: incrementing and testingatomic_tin different places.
- overflow: not ending string with NULL after usingstrncpy().
- I'll never write a patch when I'm asleep, sorry :(Added more verbose messages to SMACK and SELinux if they were not chosen on boot.
Quoted 8 lines
Casey: Failing to take permission to register an LSM does not mean that
the other has registered itssecurity_opsyet. It just means that the other asked for allowance to callregister_security(). It's not yet guraranteed that this registration succeeded.This means that adding "SELinux: failed to load, LSM %s is loaded" may lead to %s = "dummy" in case of a highly concurrent SMP system.
]
Personally, I'd be OK with seeing "dummy" on my Altix on occasion. :-) Perhaps "SELinux: Not registered, %s is reported" would address the concern. It would be really good to see the value in the 99 44/100% of the cases where it is available, even if it means admitting that there are limited circumstances where you might know that someone got there ahead of you, but not who it was. I don't think it's worth going to heroic efforts to make sure it's available.
Casey Schaufler
[email protected]
James Morris
maintainerRe: [PATCH -v3 -mm] LSM: Add security= boot parameter
In reply to Ahmed S. DarwishQuoted 11 lines · Ahmed S. Darwish
Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module.
User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen.
LSM modules must check now if they are allowed to register by calling
security_module_enable(ops)first. Modify SELinux and SMACK to do so.
I think this can be simplified by folding the logic into register_security(), rather than having a two-stage LSM registration process.
So, this function would now look like
int register_security(ops, *status);
and set *status to LSM_WAS_CHOSEN (or similar) if the module being registered was also chosen via the security= parameter. If there is no value for the parameter, the first module to register is automatically chosen, to preserve existing behavior.
The calling code can then decide what to do, e.g. not panic if registration failed and the LSM was not chosen; panic on failure when it was chosen.
Quoted 1 line
+static
atomic_tsecurity_ops_enabled=ATOMIC_INIT(-1);
I'd suggest getting rid of this atomic and using a spinlock to protect the global chosen_lsm string, which is always filled when an LSM registers.
security/security.c int __init security_init(void) · line 77
Quoted 6 lines
security/security.c +5
-0+/* Save user chosen LSM */ +static int __init choose_lsm (char *str) +{ +strncpy (chosen_lsm, str,SECURITY_NAME_MAX ); + chosen_lsm[SECURITY_NAME_MAX ] =NULL ;
You should never need to set the last byte to NULL -- it's initialized to that and by definition should never be overwritten.
security/security.c int __init security_init(void) · line 99
Quoted 4 lines
security/security.c +4
-0+int security_module_enable (struct security_operations *ops) +{ +if (!ops || !ops->name) +return 0 ;
Lack of ops->name during registration needs to be a BUG_ON.
- James
Signature · 2 lines
James Morris <[email protected]>
Re: [PATCH -v3 -mm] LSM: Add security= boot parameter
Hi James,
Quoted 22 lines · James Morris
Quoted 11 lines · Ahmed S. Darwish
Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module.
User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen.
LSM modules must check now if they are allowed to register by calling
security_module_enable(ops)first. Modify SELinux and SMACK to do so.I think this can be simplified by folding the logic into
register_security(), rather than having a two-stage LSM registration process.So, this function would now look like
int register_security(ops, *status);
Quoted 9 lines
and set *status to
LSM_WAS_CHOSEN(or similar) if the module being registered was also chosen via the security= parameter. If there is no value for the parameter, the first module to register is automatically chosen, to preserve existing behavior.The calling code can then decide what to do, e.g. not panic if registration failed and the LSM was not chosen; panic on failure when it was chosen.
I liked to do it like that at first, but I faced two problems:
SElinux (As you already know ;)) does the security setup of the initial task before calling register_security. Would it be safe to do this setup after registeration ?
Same case occurs for Smack, it does some locking initializations and setup initial task's security before registration.
Personally, I feel that it's nicer to let the LSM know if it's
OK to initialize itself before hitting _the point of no return_ (registration).
Anyway, I have no problem to implement it using *status if my concerns are wrong.
Quoted 15 lines
Quoted 1 line
+static
atomic_tsecurity_ops_enabled=ATOMIC_INIT(-1);I'd suggest getting rid of this atomic and using a spinlock to protect the global
chosen_lsmstring, which is always filled when an LSM registers.security/security.c int __init security_init(void) · line 77
Quoted 6 lines
security/security.c +5
-0+/* Save user chosen LSM */ +static int __init choose_lsm (char *str) +{ +strncpy (chosen_lsm, str,SECURITY_NAME_MAX ); + chosen_lsm[SECURITY_NAME_MAX ] =NULL ;You should never need to set the last byte to NULL -- it's initialized to that and by definition should never be overwritten.
Quoted 7 lines
security/security.c int __init security_init(void) · line 99
Quoted 4 lines
security/security.c +4
-0+int security_module_enable (struct security_operations *ops) +{ +if (!ops || !ops->name) +return 0 ;Lack of
ops->nameduring registration needs to be aBUG_ON.
You'll find above three points fixed the next send. Thank you.
Regards,
Signature · 5 lines
"Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
Re: [PATCH -v3 -mm] LSM: Add security= boot parameter
Quoted 35 lines · Ahmed S. Darwish
Hi James,
Quoted 22 lines · James Morris
Quoted 11 lines · Ahmed S. Darwish
Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module.
User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen.
LSM modules must check now if they are allowed to register by calling
security_module_enable(ops)first. Modify SELinux and SMACK to do so.I think this can be simplified by folding the logic into
register_security(), rather than having a two-stage LSM registration process.So, this function would now look like
int register_security(ops, *status);Quoted 9 lines
and set *status to
LSM_WAS_CHOSEN(or similar) if the module being registered was also chosen via the security= parameter. If there is no value for the parameter, the first module to register is automatically chosen, to preserve existing behavior.The calling code can then decide what to do, e.g. not panic if registration failed and the LSM was not chosen; panic on failure when it was chosen.
Quoted 5 lines
I liked to do it like that at first, but I faced two problems:
SElinux (As you already know ;)) does the security setup of the initial task before calling
register_security. Would it be safe to do this setup after registeration ?
I wouldn't recommend it - the hook functions presume that the initial task security blob has been set up already, and that other dependencies like the inode security cache and access vector cache have been created and can be used. We have to assume that the security hooks can start being invoked as soon as we call register_security(), even if in practice it won't happen until after the init function completes.
Quoted 36 lines
Same case occurs for Smack, it does some locking initializations and setup initial task's security before registration.
Personally, I feel that it's nicer to let the LSM know if it's
OK to initialize itself before hitting_thepoint of noreturn_(registration).Anyway, I have no problem to implement it using *status if my concerns are wrong.
Quoted 15 lines
Quoted 1 line
+static
atomic_tsecurity_ops_enabled=ATOMIC_INIT(-1);I'd suggest getting rid of this atomic and using a spinlock to protect the global
chosen_lsmstring, which is always filled when an LSM registers.security/security.c int __init security_init(void) · line 77
Quoted 6 lines
security/security.c +5
-0+/* Save user chosen LSM */ +static int __init choose_lsm (char *str) +{ +strncpy (chosen_lsm, str,SECURITY_NAME_MAX ); + chosen_lsm[SECURITY_NAME_MAX ] =NULL ;You should never need to set the last byte to NULL -- it's initialized to that and by definition should never be overwritten.
Quoted 7 lines
security/security.c int __init security_init(void) · line 99
Quoted 4 lines
security/security.c +4
-0+int security_module_enable (struct security_operations *ops) +{ +if (!ops || !ops->name) +return 0 ;Lack of
ops->nameduring registration needs to be aBUG_ON.You'll find above three points fixed the next send. Thank you.
Regards,
Signature · 2 lines
Stephen Smalley National Security Agency
PATCH 1/1 LSM: Add security= boot parameter
Hi!,
Quoted 4 lines · Stephen Smalley
Quoted 2 lines · Ahmed S. Darwish
Hi James,
....
Quoted 5 lines
Quoted 4 lines
SElinux (As you already know ;)) does the security setup of the initial task before calling
register_security. Would it be safe to do this setup after registeration ?
Quoted 7 lines
I wouldn't recommend it - the hook functions presume that the initial task security blob has been set up already, and that other dependencies like the inode security cache and access vector cache have been created and can be used. We have to assume that the security hooks can start being invoked as soon as we call
register_security(), even if in practice it won't happen until after the init function completes.
OK, the patch will stick with the two-stage registration model to give a safe initialization time for LSMs.
james: Could you please make it OK to use the atomic counter instead of
the spinlock ? It'll just add unneeded complexity. We only set `chosen_lsm' once at the parameters parsing time.
Changes (per James suggestions):
- Added a BUG_ON(!ops->name).
- Removed a redundant setting of last string character to NULL.
Sample Output:
[ 0.065487] SELinux: Initializing. [ 0.067115] SELinux: Starting in permissive mode [ 0.067186] Smack: Another security module was chosen. [ 0.067345] Smack: Use security=smack to force loading Smack on boot.
-->
Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module.
User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen.
LSM modules must check now if they are allowed to register by calling security_module_enable(ops) first. Modify SELinux and SMACK to do so.
---
Documentation/kernel-parameters.txt | 6 ++++ include/linux/security.h | 12 +++++++++ security/dummy.c | 2 -+ security/security.c | 45 ++++++++++++++++++++++++++++++++++-- security/selinux/hooks.c | 10 ++++++++ security/smack/smack_lsm.c | 9 +++++++
6 files changed, 81 insertions(+), 3 deletions(-)
Documentation/kernel-parameters.txt +6 -0
@@ -374,6 +374,12 @@ and is between 256 and 4096 characters. It is defined in the file possible to determine what the correct size should be. This option provides an override for these situations. + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be + loaded. An invalid security module name will be treated + as if no module has been chosen. + capability.disable= [SECURITY] Disable capabilities. This would normally be used only if an alternative security model is to be
include/linux/security.h +12 -0
@@ -42,6 +42,9 @@extern unsigned securebits; +/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10 +struct ctl_table ;struct audit_krule ;
@@ -118,6 +121,12 @@ struct request_sock;/** * struct security_operations - main security structure * +* Security module identifier. +* +* @name: +* A string that acts as a unique identifeir for the LSM with max number +* of characters = SECURITY_NAME_MAX. +* * Security hooks for program execution operations. * * @bprm_alloc_security:
@@ -1262,6 +1271,8 @@ struct request_sock;* This is the main security structure. */ struct security_operations { +char name[SECURITY_NAME_MAX +1 ]; +int (*ptrace) (struct task_struct * parent,struct task_struct * child); int (*capget) (struct task_struct * target, kernel_cap_t * effective,
@@ -1530,6 +1541,7 @@ struct security_operations {/* prototypes */ extern int security_init (void ); +extern int security_module_enable (struct security_operations *ops);extern int register_security (struct security_operations *ops);extern int mod_reg_security (const char *name,struct security_operations *ops); extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
security/dummy.c +1 -1
@@ -1022,7 +1022,7 @@ static inline void dummy_audit_rule_free(void *lsmrule)#endif /* CONFIG_AUDIT */ -struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = {"dummy" };#define set_to_dummy_if_null (ops, function) \ do { \
security/security.c +43 -2
69 lines not on this page · raw message
security/selinux/hooks.c +10 -0
@@ -5247,6 +5247,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)#endif static struct security_operations selinux_ops = { + .name ="selinux" , + .ptrace = selinux_ptrace, .capget = selinux_capget, .capset_check = selinux_capset_check,
@@ -5448,6 +5450,14 @@ static __init int selinux_init(void)return 0 ; } +if (!security_module_enable (&selinux_ops)) { + selinux_enabled =0 ; +printk (KERN_INFO "SELinux: Another security module was chosen.\n" ); +printk (KERN_INFO "SELinux: Use security=%s to force loading " +"SELinux on boot.\n" , selinux_ops.name); +return 0 ; + } +printk (KERN_INFO "SELinux: Initializing.\n" );/* Set the security state for the initial task. */
security/smack/smack_lsm.c +9 -0
@@ -2358,6 +2358,8 @@ static void smack_release_secctx(char *secdata, u32 seclen) }static struct security_operations smack_ops = { + .name ="smack" , + .ptrace = smack_ptrace, .capget = cap_capget, .capset_check = cap_capset_check,
@@ -2485,6 +2487,13 @@ static struct security_operations smack_ops = {*/ static __init int smack_init (void ) { +if (!security_module_enable (&smack_ops)) { +printk (KERN_INFO "Smack: Another security module was chosen.\n" ); +printk (KERN_INFO "Smack: Use security=%s to force loading " +"Smack on boot.\n" , smack_ops.name); +return 0 ; + } +printk (KERN_INFO "Smack: Initializing.\n" );/*
Signature · 5 lines
"Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
James Morris
maintainerRe: [PATCH -v4 -mm] LSM: Add security= boot parameter
security/security.c unsigned long mmap_min_addr = CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR; · line 37
Quoted 6 lines · Ahmed S. Darwish
static inline int
verify(struct security_operations *ops){security/security.c +1
-1/* verify the security_operations structure exists */ -if (!ops) +if (!ops || !ops->name)return -EINVAL ;
verify() will now be called after ops->name has been referenced, so these checks won't be necessary now.
security/security.c int __init security_init(void) · line 99
Quoted 6 lines
security/security.c +6
-0+int security_module_enable (struct security_operations *ops) +{ +if (!ops || !ops->name) { +BUG (); +return 0 ; + }
It's not going to return after BUG(), and actually, you can probably just rely on the subsequent oops (i.e. no check needed).
security/security.c int __init security_init(void) · line 105
Quoted 6 lines
security/security.c +6
-0+ +if (!*chosen_lsm &&atomic_inc_and_test (&security_ops_enabled)) +return 1 ; + +if (!strncmp (ops->name, chosen_lsm,SECURITY_NAME_MAX )) +return 1 ;
I still think you should use a spinlock here to make the semantics simpler. Dispense with the confusingly named security_ops_enabled, and fill chosen_lsm in with the first lsm to regsiter if none chosen at boot.
security/selinux/hooks.c static __init int selinux_init(void) · line 5457
Quoted 3 lines
security/selinux/hooks.c +3
-0+printk (KERN_INFO "SELinux: Another security module was chosen.\n" ); +printk (KERN_INFO "SELinux: Use security=%s to force loading " +"SELinux on boot.\n" , selinux_ops.name);
These messages are not going to scale, e.g. what if there are 20 LSMs compiled in, and they all print this on boot? Just print the chosen LSM in security_module_enabled().
- James
Signature · 2 lines
James Morris <[email protected]>
PATCH 1/1 LSM: Add security= boot parameter
Hi!,
[
Fix stuff mentioned by James in parent mail:
- use spinlocks instead of atomic counter (yes, this is clearer).
- remove redundant BUG_ON
- don't let LSMs loudly complain when they aren't chosen. ]
-->
Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module.
User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen.
LSM modules must check now if they are allowed to register by calling security_module_enable(ops) first. Modify SELinux and SMACK to do so.
---
Documentation/kernel-parameters.txt | 6 ++++ include/linux/security.h | 12 +++++++++ security/dummy.c | 2 - security/security.c | 46 +++++++++++++++++++++++++++++++++++- security/selinux/hooks.c | 7 +++++ security/smack/smack_lsm.c | 5 +++
6 files changed, 76 insertions(+), 2 deletions(-)
Documentation/kernel-parameters.txt +6 -0
@@ -374,6 +374,12 @@ and is between 256 and 4096 characters. It is defined in the file possible to determine what the correct size should be. This option provides an override for these situations. + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be + loaded. An invalid security module name will be treated + as if no module has been chosen. + capability.disable= [SECURITY] Disable capabilities. This would normally be used only if an alternative security model is to be
include/linux/security.h +12 -0
@@ -42,6 +42,9 @@extern unsigned securebits; +/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10 +struct ctl_table ;struct audit_krule ;
@@ -118,6 +121,12 @@ struct request_sock;/** * struct security_operations - main security structure * +* Security module identifier. +* +* @name: +* A string that acts as a unique identifeir for the LSM with max number +* of characters = SECURITY_NAME_MAX. +* * Security hooks for program execution operations. * * @bprm_alloc_security:
@@ -1262,6 +1271,8 @@ struct request_sock;* This is the main security structure. */ struct security_operations { +char name[SECURITY_NAME_MAX +1 ]; +int (*ptrace) (struct task_struct * parent,struct task_struct * child); int (*capget) (struct task_struct * target, kernel_cap_t * effective,
@@ -1530,6 +1541,7 @@ struct security_operations {/* prototypes */ extern int security_init (void ); +extern int security_module_enable (struct security_operations *ops);extern int register_security (struct security_operations *ops);extern int mod_reg_security (const char *name,struct security_operations *ops); extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
security/dummy.c +1 -1
@@ -1022,7 +1022,7 @@ static inline void dummy_audit_rule_free(void *lsmrule)#endif /* CONFIG_AUDIT */ -struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = {"dummy" };#define set_to_dummy_if_null (ops, function) \ do { \
security/security.c +45 -1
69 lines not on this page · raw message
security/selinux/hooks.c +7 -0
@@ -5247,6 +5247,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)#endif static struct security_operations selinux_ops = { + .name ="selinux" , + .ptrace = selinux_ptrace, .capget = selinux_capget, .capset_check = selinux_capset_check,
@@ -5443,6 +5445,11 @@ static __init int selinux_init(void) {struct task_security_struct *tsec; +if (!security_module_enable (&selinux_ops)) { + selinux_enabled =0 ; +return 0 ; + } +if (!selinux_enabled) {printk (KERN_INFO "SELinux: Disabled at boot.\n" );return 0 ;
security/smack/smack_lsm.c +5 -0
@@ -2358,6 +2358,8 @@ static void smack_release_secctx(char *secdata, u32 seclen) }static struct security_operations smack_ops = { + .name ="smack" , + .ptrace = smack_ptrace, .capget = cap_capget, .capset_check = cap_capset_check,
@@ -2485,6 +2487,9 @@ static struct security_operations smack_ops = {*/ static __init int smack_init (void ) { +if (!security_module_enable (&smack_ops)) +return 0 ; +printk (KERN_INFO "Smack: Initializing.\n" );/*
Signature · 5 lines
"Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
Re: [PATCH -v5 -mm] LSM: Add security= boot parameter
Quoted 1 line · Ahmed S. Darwish
Signed-off-by Ahmed S. Darwish <[email protected]>
Quoted 4 lines
security/security.c +4
-0+int rc =1 ; + +spin_lock (&chosen_lsm_lock); +if (!*chosen_lsm)
security/security.c int __init security_init(void) · line 110
Quoted 10 lines
security/security.c +10
-0+strncpy (chosen_lsm, ops->name,SECURITY_NAME_MAX ); + else if (strncmp(ops->name, chosen_lsm, SECURITY_NAME_MAX)) + rc =0 ; +spin_unlock (&chosen_lsm_lock); + +if (rc) +printk (KERN_INFO "Security: Loading '%s' security module.\n" , + ops->name); + +return rc;
Possibly consider using 0 for success and -EBUSY on failure (but not a showstopper for me, as it's not really an "error").
- James
Signature · 2 lines
James Morris <[email protected]>
Re: [PATCH -v5 -mm] LSM: Add security= boot parameter
In reply to Ahmed S. DarwishQuoted 25 lines · On Tue, 4 Mar 2008 05:04:07 +0200 "Ahmed S. Darwish" <[email protected]>…
Hi!,
[
Fix stuff mentioned by James in parent mail:
- use spinlocks instead of atomic counter (yes, this is clearer).
- remove redundantBUG_ON
- don't let LSMs loudly complain when they aren't chosen. ]-->
Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module.
User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen.
LSM modules must check now if they are allowed to register by calling
security_module_enable(ops)first. Modify SELinux and SMACK to do so....
include/linux/security.h line 46
Quoted 2 lines
include/linux/security.h +2
-0+/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10
Is this long enough?
security/dummy.c static inline void dummy_audit_rule_free(void *lsmrule) · line 1025
Quoted 7 lines
struct
ctl_table;
structaudit_krule;...
security/dummy.c +1
-1-struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = {"dummy" };
Please don't rely upon the layout of data structures in this manner. Use ".name = ".
Quoted 18 lines
#define
set_to_dummy_if_null(ops, function)\(quoted diff) +0
-0do { \security/security.c +3
-0@@ -17,6 +17,9 @@#include <linux/kernel.h> #include <linux/security.h> +/* Boot-time LSM user choice */ +static spinlock_t chosen_lsm_lock; +static char chosen_lsm[SECURITY_NAME_MAX +1 ];/* things that live in dummy.c */ extern struct security_operations dummy_security_ops;
security/security.c int __init security_init(void) · line 68
Quoted 4 lines
security/security.c +1
-0@@ -62,18 +65,59 @@ int __init security_init(void) } security_ops = &dummy_security_ops; +spin_lock_init (&chosen_lsm_lock);
Please remove this and use compile-time initialisation with DEFINE_SPINLOCK.
Do we actually need the lock? This code is only called at boot-time if I understand it correctly?
Can chosen_lsm[] be __initdata?
Quoted 33 lines
security/security.c +28
-0do_security_initcalls ();return 0 ; } +/* Save user chosen LSM */ +static int __init choose_lsm (char *str) +{ +strncpy (chosen_lsm, str,SECURITY_NAME_MAX ); +return 1 ; +} +__setup ("security=" , choose_lsm); + +/** +* security_module_enable - Load given security module on boot ? +* @ops: a pointer to the struct security_operations that is to be checked. +* +* Each LSM must pass this method before registering its own operations +* to avoid security registration races. +* +* Return true if: +* -The passed LSM is the one chosen by user at boot time, +* -or user didsn't specify a specific LSM and we're the first to ask +* for registeration permissoin. +* Otherwise, return false. +*/ +int security_module_enable (struct security_operations *ops) +{ +int rc =1 ; + +spin_lock (&chosen_lsm_lock); +if (!*chosen_lsm) +strncpy (chosen_lsm, ops->name,SECURITY_NAME_MAX );
security/security.c int __init security_init(void) · line 111
Quoted 10 lines
security/security.c +10
-0+else if (strncmp (ops->name, chosen_lsm,SECURITY_NAME_MAX )) + rc =0 ; +spin_unlock (&chosen_lsm_lock); + +if (rc) +printk (KERN_INFO "Security: Loading '%s' security module.\n" , + ops->name); + +return rc; +}
I believe this can be __init.
Quoted 6 lines
security/security.c +5
-0+if (!security_module_enable (&selinux_ops)) { + selinux_enabled =0 ; +return 0 ; + } +
security/security.c int __init security_init(void)
Quoted 10 lines
security/security.c +3
-0static __init int smack_init (void ) { +if (!security_module_enable (&smack_ops)) +return 0 ; +printk (KERN_INFO "Smack: Initializing.\n" );/*
hm. selinux has a global selinux_enabled knob, but smack seems to be able to get by without one. +1 for smack ;)
James Morris
maintainerRe: [PATCH -v5 -mm] LSM: Add security= boot parameter
Quoted 4 lines · Andrew Morton
include/linux/security.h line 46
Quoted 2 lines
include/linux/security.h +2
-0+/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10Is this long enough?
I almost flagged this earlier, but I don't think we've ever seen an LSM with a longer name, and it can be expanded if needed. 32 or something seems similarly arbitrary.
Quoted 4 lines
Please remove this and use compile-time initialisation with
DEFINE_SPINLOCK.Do we actually need the lock? This code is only called at boot-time if I understand it correctly?
Theoretically, security_module_enable() could be called at any time, although it does seem unlikely never to be called at boot, especially if multiple LSMs are compiled in.
In that case, perhaps mark the function as __init, and require it be called only at boot time.
Quoted 1 line
Can chosen_lsm[] be
__initdata?
With the above, yes.
Quoted 4 lines
security/security.c int __init security_init(void) · line 111
Quoted 2 lines
security/security.c +2
-0+int security_module_enable(struct security_operations *ops) +}I believe this can be
__init.
Indeed :-)
- James
Signature · 2 lines
James Morris <[email protected]>
Re: [PATCH -v5 -mm] LSM: Add security= boot parameter
In reply to Andrew MortonQuoted 3 lines · Andrew Morton
On Tue, 4 Mar 2008 05:04:07 +0200
"Ahmed S. Darwish" <[email protected]> wrote:
...
Quoted 7 lines
include/linux/security.h line 46
Quoted 4 lines
...
include/linux/security.h +2
-0+/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10Is this long enough?
I've judged from the four common applicants (selinux, smack, apparmor, tomoyo) that 10 would be enough. Anyway this will be easy to fix when something longer appears.
Quoted 11 lines
security/dummy.c static inline void dummy_audit_rule_free(void *lsmrule) · line 1025
Quoted 7 lines
struct
ctl_table;
structaudit_krule;...
security/dummy.c +1
-1-struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = {"dummy" };Please don't rely upon the layout of data structures in this manner. Use ".name = ".
Will do.
Quoted 20 lines
Quoted 20 lines
#define
set_to_dummy_if_null(ops, function)\(quoted diff) +0
-0do { \security/security.c +3
-0@@ -17,6 +17,9 @@#include <linux/kernel.h> #include <linux/security.h> +/* Boot-time LSM user choice */ +static spinlock_t chosen_lsm_lock; +static char chosen_lsm[SECURITY_NAME_MAX +1 ];/* things that live in dummy.c */ extern struct security_operations dummy_security_ops;@@ -62,18 +65,59 @@ int __init security_init(void) }
Quoted 5 lines
security/security.c int __init security_init(void) · line 68
Quoted 2 lines
security/security.c +1
-0security_ops = &dummy_security_ops; +spin_lock_init (&chosen_lsm_lock);Please remove this and use compile-time initialisation with
DEFINE_SPINLOCK.
Ooh I thought the dynamic one was better cause I remember I read it somewhere on LWN that this is nicer for the RT-patches. I'll modify it, no problem.
Quoted 3 lines
Do we actually need the lock? This code is only called at boot-time if I understand it correctly?
In the latest version (-v7b, in another thread, CCed), security_module_enable() is also used to let an LSM know if it's currently loaded or not. This was done to avoid using a `smack_enabled' global.
I'll resend the v7b for -mm once the LSM devs give their ACKs for the -rc3 one.
Quoted 2 lines
Can chosen_lsm[] be
__initdata?
You're the expert ;), I don't really understand the difference.
...
Quoted 25 lines
Quoted 25 lines
security/security.c +24
-0+/** +* security_module_enable - Load given security module on boot ? +* @ops: a pointer to the struct security_operations that is to be checked. +* +* Each LSM must pass this method before registering its own operations +* to avoid security registration races. +* +* Return true if: +* -The passed LSM is the one chosen by user at boot time, +* -or user didsn't specify a specific LSM and we're the first to ask +* for registeration permissoin. +* Otherwise, return false. +*/ +int security_module_enable (struct security_operations *ops) +{ +int rc =1 ; + +spin_lock (&chosen_lsm_lock); +if (!*chosen_lsm) +strncpy (chosen_lsm, ops->name,SECURITY_NAME_MAX ); +else if (strncmp (ops->name, chosen_lsm,SECURITY_NAME_MAX )) + rc =0 ; +spin_unlock (&chosen_lsm_lock); +
Quoted 9 lines
security/security.c int __init security_init(void) · line 111
Quoted 6 lines
security/security.c +6
-0+if (rc) +printk (KERN_INFO "Security: Loading '%s' security module.\n" , + ops->name); + +return rc; +}I believe this can be
__init.
Will do.
Quoted 15 lines
Quoted 15 lines
security/security.c +8
-0+if (!security_module_enable (&selinux_ops)) { + selinux_enabled =0 ; +return 0 ; + } +static __init int smack_init (void ) { +if (!security_module_enable (&smack_ops)) +return 0 ; +printk (KERN_INFO "Smack: Initializing.\n" );
Quoted 5 lines
Quoted 1 line
/*
hm. selinux has a global
selinux_enabledknob, but smack seems to be able to get by without one. +1 for smack ;)
Thanks to Linus ;).
I've sent a patch that added a similar global yesterday and it was knocked-down by Linus after exactly 2 minutes.
The situation is handled now without a global in v7/v7b.
Regards,
Signature · 5 lines
"Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com
Re: [PATCH -v5 -mm] LSM: Add security= boot parameter
Quoted 9 lines · Ahmed S. Darwish
Quoted 5 lines · Andrew Morton
On Tue, 4 Mar 2008 05:04:07 +0200
"Ahmed S. Darwish" <[email protected]> wrote:Can chosen_lsm[] be
__initdata?You're the expert ;), I don't really understand the difference.
After being a good citizen and reading the comments in init.h, I think yes it should be marked so. even though we use it from init_smk_fs since init_smk_fs is also marked as __init.
Thank you,
Signature · 5 lines
"Better to light a candle, than curse the darkness" Ahmed S. Darwish Homepage: http://darwish.07.googlepages.com Blog: http://darwish-07.blogspot.com