Re: [PATCH v12 3/9] LSM: Multiple concurrent LSMs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 1/21/2013 4:42 AM, Tetsuo Handa wrote:
> Casey Schaufler wrote:
>>> Casey Schaufler wrote:
>>>> -	security_ops = ops;
>>>> +	if (lsm_count >= COMPOSER_MAX) {
>>>> +		pr_warn("Too many security modules. %s not loaded.\n",
>>>> +				ops->name);
>>>> +		return 0;
>>>> +	}
>>>>  
>>>> -	return 0;
>>>> +	if (specified_lsms[0][0] != '\0') {
>>> We can do "specified_lsms[0][0] = '\0';" after "do_security_initcalls();" so
>>> that LKM-based LSMs can be loaded without depending on security= argument?
>> You are going to have to introduce more mechanism if you want to
>> provide for LKM-based LSMs. How about we consider a change here until
>> you can propose that mechanism in its entirety.
>>
> Below is what I think we need for "current v12 patchset" + "LKM-based LSM
> support" + "Require a valid ->order value to all LSM" approach.
> What other mechanism we are missing?

The big trouble is cleaning up blobs that an LSM has allocated
at the time an LSM is unloaded. I am only including the ability
to unregister via reset_security_ops (which I plan to rename,
more on that later) because SELinux depends on it.

> diff --git a/include/linux/security.h b/include/linux/security.h
> index 535a967..615c957 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1876,10 +1876,7 @@ extern struct security_operations *lsm_present;
>  /* prototypes */
>  extern int security_init(void);
>  extern int security_module_enable(struct security_operations *ops);
> -
> -#ifdef CONFIG_SECURITY_SELINUX_DISABLE
> -extern int reset_security_ops(struct security_operations *ops);
> -#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
> +extern void reset_security_ops(struct security_operations *ops);

Making this a void is the right thing to do. At one point in the
development of this patch this function could fail, but that's
no longer the case.

I'm renaming reset_security_ops to security_module_disable to match
up with security_module_enable. I know it's unnecessary, but I think
it's the right thing to do.

>  
>  /* Security operations */
>  int security_ptrace_access_check(struct task_struct *child, unsigned int mode);
> diff --git a/security/security.c b/security/security.c
> index 72bf9dc..9ec72a8 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -34,11 +34,11 @@
>  
>  /* Boot-time LSM user choice */
>  
> -static __initdata char specified_lsms[COMPOSER_MAX][SECURITY_NAME_MAX + 1];
> +static char specified_lsms[COMPOSER_MAX][SECURITY_NAME_MAX + 1];
>  static __initdata char allowed_lsms[COMPOSER_NAMES_MAX];
> -static __initdata char present_lsm[SECURITY_NAME_MAX + 1] =
> -	CONFIG_PRESENT_SECURITY;
> +static char present_lsm[SECURITY_NAME_MAX + 1] = CONFIG_PRESENT_SECURITY;
>  
> +static DEFINE_SPINLOCK(lsm_registration_lock);
>  struct list_head lsm_hooks[LSM_MAX_HOOKS];
>  struct security_operations *lsm_present;
>  
> @@ -57,9 +57,8 @@ static int lsm_count;
>   * The "interesting" logic is included here rather than in the
>   * caller to reduce the volume of the calling code.
>   */
> -static void __init lsm_enlist(struct security_operations *ops,
> -				const enum lsm_hooks_index index,
> -				void *interesting)
> +static void lsm_enlist(struct security_operations *ops,
> +		       const enum lsm_hooks_index index, void *interesting)
>  {
>  	struct security_operations *sop;
>  
> @@ -85,7 +84,7 @@ static void __init lsm_enlist(struct security_operations *ops,
>  	}
>  }
>  
> -static void __init lsm_enlist_ops(struct security_operations *sop)
> +static void lsm_enlist_ops(struct security_operations *sop)
>  {
>  	lsm_enlist(sop, lsm_ptrace_access_check, sop->ptrace_access_check);
>  	lsm_enlist(sop, lsm_ptrace_traceme, sop->ptrace_traceme);
> @@ -328,15 +327,12 @@ int __init security_init(void)
>  	pr_info("Security Framework initialized\n");
>  
>  	do_security_initcalls();
> +	/* LKM-based LSM modules do not depend on security= argument. */
> +	specified_lsms[0][0] = '\0';
>  
>  	return 0;
>  }
>  
> -/*
> - * Only SELinux calls reset_security_ops.
> - */
> -#ifdef CONFIG_SECURITY_SELINUX_DISABLE
> -
>  static void lsm_delist_ops(struct security_operations *sop)
>  {
>  	enum lsm_hooks_index i;
> @@ -347,7 +343,16 @@ static void lsm_delist_ops(struct security_operations *sop)
>  	return;
>  }
>  
> -int reset_security_ops(struct security_operations *ops)
> +/**
> + * reset_security_ops - Unregister given security module.
> + *
> + * @ops: a pointer to the struct security_operations.
> + *
> + * Note that this is for unregistering but not for unloading, for LSM
> + * infrastracture does not provide a mechanism for determining whether it is
> + * safe to unload the given module.
> + */
> +void reset_security_ops(struct security_operations *ops)
>  {
>  	/*
>  	 * This LSM is configured to own /proc/.../attr.
> @@ -355,12 +360,11 @@ int reset_security_ops(struct security_operations *ops)
>  	if (lsm_present == ops)
>  		lsm_present = NULL;
>  
> +	spin_lock(&lsm_registration_lock);
>  	lsm_delist_ops(ops);
> -
> -	return 0;
> +	spin_unlock(&lsm_registration_lock);
>  }
> -
> -#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
> +EXPORT_SYMBOL_GPL(reset_security_ops);
>  
>  /* Save user chosen LSM(s) */
>  static int __init choose_lsm(char *str)
> @@ -402,11 +406,12 @@ __setup("security=", choose_lsm);
>   *	-or no boot list was specified.
>   * Otherwise, return false.
>   */
> -int __init security_module_enable(struct security_operations *ops)
> +int security_module_enable(struct security_operations *ops)
>  {
>  	struct security_operations *sop;
>  	int i;
>  
> +	spin_lock(&lsm_registration_lock);
>  	/*
>  	 * Set up the operation vector early, but only once.
>  	 * This allows LSM specific file systems to check to see if they
> @@ -415,14 +420,14 @@ int __init security_module_enable(struct security_operations *ops)
>  	if (ops == NULL) {
>  		pr_debug("%s could not verify security_operations.\n",
>  				__func__);
> -		return 0;
> +		goto fail;
>  	}
>  	/*
>  	 * Return success if the LSM is already resistered
>  	 */
>  	for_each_hook(sop, name)
>  		if (sop == ops)
> -			return 1;
> +			goto ok;
>  
>  	/*
>  	 * This LSM has not yet been ordered.
> @@ -432,7 +437,7 @@ int __init security_module_enable(struct security_operations *ops)
>  	if (lsm_count >= COMPOSER_MAX) {
>  		pr_warn("Too many security modules. %s not loaded.\n",
>  				ops->name);
> -		return 0;
> +		goto fail;
>  	}
>  
>  	if (specified_lsms[0][0] != '\0') {
> @@ -445,7 +450,7 @@ int __init security_module_enable(struct security_operations *ops)
>  		if (ops->order == -1) {
>  			pr_notice("LSM %s declined by boot options.\n",
>  					ops->name);
> -			return 0;
> +			goto fail;
>  		}
>  	}
>  	/*
> @@ -456,14 +461,14 @@ int __init security_module_enable(struct security_operations *ops)
>  	    !list_empty(&lsm_hooks[lsm_xfrm_policy_alloc_security])) {
>  		pr_warn("LSM conflict on %s. %s not loaded.\n",
>  				"xfrm_policy_alloc_security", ops->name);
> -		return 0;
> +		goto fail;
>  	}
>  #endif
>  	if (ops->secid_to_secctx &&
>  	    !list_empty(&lsm_hooks[lsm_secid_to_secctx])) {
>  		pr_warn("LSM conflict on %s. %s not loaded.\n",
>  			"secid_to_secctx", ops->name);
> -		return 0;
> +		goto fail;
>  	}
>  
>  	/*
> @@ -499,9 +504,14 @@ int __init security_module_enable(struct security_operations *ops)
>  	 * Return success after registering the LSM.
>  	 */
>  	lsm_enlist_ops(ops);
> -
> +ok:
> +	spin_unlock(&lsm_registration_lock);
>  	return 1;
> +fail:
> +	spin_unlock(&lsm_registration_lock);
> +	return 0;
>  }
> +EXPORT_SYMBOL_GPL(security_module_enable);

I am disinclined to put in what might appear to be support
for dynamic security modules when I'm not yet willing to
sign up for that.

>  
>  /* Security operations */
>  
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 8ec7ea0..9bdea1e 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -5814,8 +5814,6 @@ static int selinux_disabled;
>  
>  int selinux_disable(void)
>  {
> -	int rc;
> -
>  	if (ss_initialized) {
>  		/* Not permitted after initial policy load. */
>  		return -EINVAL;
> @@ -5826,11 +5824,7 @@ int selinux_disable(void)
>  		return -EINVAL;
>  	}
>  
> -	rc = reset_security_ops(&selinux_ops);
> -	if (rc) {
> -		pr_info("SELinux:  Runtime disable disallowed.\n");
> -		return rc;
> -	}
> +	reset_security_ops(&selinux_ops);
>  
>  	printk(KERN_INFO "SELinux:  Disabled at runtime.\n");
>  
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.


[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux