diff mbox

[1/3] selinux: Implement LSM notification system

Message ID 1493218936-18522-1-git-send-email-sbuisson@ddn.com (mailing list archive)
State Superseded
Headers show

Commit Message

Sebastien Buisson April 26, 2017, 3:02 p.m. UTC
From: Daniel Jurgens <danielj@mellanox.com>

Add a generic notification mechanism in the LSM. Interested consumers
can register a callback with the LSM and security modules can produce
events.

Add a call to the notification mechanism from SELinux when the AVC
cache changes.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
---
 include/linux/security.h | 23 +++++++++++++++++++++++
 security/security.c      | 20 ++++++++++++++++++++
 security/selinux/hooks.c | 12 ++++++++++++
 3 files changed, 55 insertions(+)

Comments

Casey Schaufler April 26, 2017, 3:38 p.m. UTC | #1
On 4/26/2017 8:02 AM, Sebastien Buisson wrote:
> From: Daniel Jurgens <danielj@mellanox.com>
>
> Add a generic notification mechanism in the LSM. Interested consumers
> can register a callback with the LSM and security modules can produce
> events.

Why is this a generic mechanism? Do you ever see anyone
other than SELinux using it?

> Add a call to the notification mechanism from SELinux when the AVC
> cache changes.

This seems like a whole lot of mechanism for
something you could accomplish with a log message.
What am I missing?

>
> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
> ---
>  include/linux/security.h | 23 +++++++++++++++++++++++
>  security/security.c      | 20 ++++++++++++++++++++
>  security/selinux/hooks.c | 12 ++++++++++++
>  3 files changed, 55 insertions(+)
>
> diff --git a/include/linux/security.h b/include/linux/security.h
> index af675b5..73a9c93 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -68,6 +68,10 @@
>  struct user_namespace;
>  struct timezone;
>  
> +enum lsm_event {
> +	LSM_POLICY_CHANGE,
> +};
> +
>  /* These functions are in security/commoncap.c */
>  extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
>  		       int cap, int audit);
> @@ -163,6 +167,10 @@ struct security_mnt_opts {
>  	int num_mnt_opts;
>  };
>  
> +int call_lsm_notifier(enum lsm_event event, void *data);
> +int register_lsm_notifier(struct notifier_block *nb);
> +int unregister_lsm_notifier(struct notifier_block *nb);
> +
>  static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
>  {
>  	opts->mnt_opts = NULL;
> @@ -381,6 +389,21 @@ int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
>  struct security_mnt_opts {
>  };
>  
> +static inline int call_lsm_notifier(enum lsm_event event, void *data)
> +{
> +	return 0;
> +}
> +
> +static inline int register_lsm_notifier(struct notifier_block *nb)
> +{
> +	return 0;
> +}
> +
> +static inline  int unregister_lsm_notifier(struct notifier_block *nb)
> +{
> +	return 0;
> +}
> +
>  static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
>  {
>  }
> diff --git a/security/security.c b/security/security.c
> index b9fea39..ef9d9e1 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -32,6 +32,8 @@
>  /* Maximum number of letters for an LSM name string */
>  #define SECURITY_NAME_MAX	10
>  
> +static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
> +
>  struct security_hook_heads security_hook_heads __lsm_ro_after_init;
>  char *lsm_names;
>  /* Boot-time LSM user choice */
> @@ -146,6 +148,24 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
>  		panic("%s - Cannot get early memory.\n", __func__);
>  }
>  
> +int call_lsm_notifier(enum lsm_event event, void *data)
> +{
> +	return atomic_notifier_call_chain(&lsm_notifier_chain, event, data);
> +}
> +EXPORT_SYMBOL(call_lsm_notifier);
> +
> +int register_lsm_notifier(struct notifier_block *nb)
> +{
> +	return atomic_notifier_chain_register(&lsm_notifier_chain, nb);
> +}
> +EXPORT_SYMBOL(register_lsm_notifier);
> +
> +int unregister_lsm_notifier(struct notifier_block *nb)
> +{
> +	return atomic_notifier_chain_unregister(&lsm_notifier_chain, nb);
> +}
> +EXPORT_SYMBOL(unregister_lsm_notifier);
> +
>  /*
>   * Hook list operation macros.
>   *
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index e67a526..a4d36f8 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -171,6 +171,14 @@ static int selinux_netcache_avc_callback(u32 event)
>  	return 0;
>  }
>  
> +static int selinux_lsm_notifier_avc_callback(u32 event)
> +{
> +	if (event == AVC_CALLBACK_RESET)
> +		call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
> +
> +	return 0;
> +}
> +
>  /*
>   * initialise the security for the init task
>   */
> @@ -6379,6 +6387,10 @@ static __init int selinux_init(void)
>  	if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
>  		panic("SELinux: Unable to register AVC netcache callback\n");
>  
> +	if (avc_add_callback(selinux_lsm_notifier_avc_callback,
> +			     AVC_CALLBACK_RESET))
> +		panic("SELinux: Unable to register AVC LSM notifier callback\n");
> +
>  	if (selinux_enforcing)
>  		printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");
>  	else
Daniel Jurgens April 26, 2017, 3:48 p.m. UTC | #2
On 4/26/2017 10:38 AM, Casey Schaufler wrote:
> On 4/26/2017 8:02 AM, Sebastien Buisson wrote:
>> From: Daniel Jurgens <danielj@mellanox.com>
>>
>> Add a generic notification mechanism in the LSM. Interested consumers
>> can register a callback with the LSM and security modules can produce
>> events.
> Why is this a generic mechanism? Do you ever see anyone
> other than SELinux using it?
I had created an SELinux specific mechanism, Paul Moore requested I make it generic.
>> Add a call to the notification mechanism from SELinux when the AVC
>> cache changes.
> This seems like a whole lot of mechanism for
> something you could accomplish with a log message.
> What am I missing?
This was part of a larger patch set that hasn't been accepted yet.  SELinux support for Inifiniband.  Subsequent patches in that patch set will use it as well.
>> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
>> Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
>> ---
>>  include/linux/security.h | 23 +++++++++++++++++++++++
>>  security/security.c      | 20 ++++++++++++++++++++
>>  security/selinux/hooks.c | 12 ++++++++++++
>>  3 files changed, 55 insertions(+)
>>
>> diff --git a/include/linux/security.h b/include/linux/security.h
>> index af675b5..73a9c93 100644
>> --- a/include/linux/security.h
>> +++ b/include/linux/security.h
>> @@ -68,6 +68,10 @@
>>  struct user_namespace;
>>  struct timezone;
>>  
>> +enum lsm_event {
>> +	LSM_POLICY_CHANGE,
>> +};
>> +
>>  /* These functions are in security/commoncap.c */
>>  extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
>>  		       int cap, int audit);
>> @@ -163,6 +167,10 @@ struct security_mnt_opts {
>>  	int num_mnt_opts;
>>  };
>>  
>> +int call_lsm_notifier(enum lsm_event event, void *data);
>> +int register_lsm_notifier(struct notifier_block *nb);
>> +int unregister_lsm_notifier(struct notifier_block *nb);
>> +
>>  static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
>>  {
>>  	opts->mnt_opts = NULL;
>> @@ -381,6 +389,21 @@ int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
>>  struct security_mnt_opts {
>>  };
>>  
>> +static inline int call_lsm_notifier(enum lsm_event event, void *data)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int register_lsm_notifier(struct notifier_block *nb)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline  int unregister_lsm_notifier(struct notifier_block *nb)
>> +{
>> +	return 0;
>> +}
>> +
>>  static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
>>  {
>>  }
>> diff --git a/security/security.c b/security/security.c
>> index b9fea39..ef9d9e1 100644
>> --- a/security/security.c
>> +++ b/security/security.c
>> @@ -32,6 +32,8 @@
>>  /* Maximum number of letters for an LSM name string */
>>  #define SECURITY_NAME_MAX	10
>>  
>> +static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
>> +
>>  struct security_hook_heads security_hook_heads __lsm_ro_after_init;
>>  char *lsm_names;
>>  /* Boot-time LSM user choice */
>> @@ -146,6 +148,24 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
>>  		panic("%s - Cannot get early memory.\n", __func__);
>>  }
>>  
>> +int call_lsm_notifier(enum lsm_event event, void *data)
>> +{
>> +	return atomic_notifier_call_chain(&lsm_notifier_chain, event, data);
>> +}
>> +EXPORT_SYMBOL(call_lsm_notifier);
>> +
>> +int register_lsm_notifier(struct notifier_block *nb)
>> +{
>> +	return atomic_notifier_chain_register(&lsm_notifier_chain, nb);
>> +}
>> +EXPORT_SYMBOL(register_lsm_notifier);
>> +
>> +int unregister_lsm_notifier(struct notifier_block *nb)
>> +{
>> +	return atomic_notifier_chain_unregister(&lsm_notifier_chain, nb);
>> +}
>> +EXPORT_SYMBOL(unregister_lsm_notifier);
>> +
>>  /*
>>   * Hook list operation macros.
>>   *
>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>> index e67a526..a4d36f8 100644
>> --- a/security/selinux/hooks.c
>> +++ b/security/selinux/hooks.c
>> @@ -171,6 +171,14 @@ static int selinux_netcache_avc_callback(u32 event)
>>  	return 0;
>>  }
>>  
>> +static int selinux_lsm_notifier_avc_callback(u32 event)
>> +{
>> +	if (event == AVC_CALLBACK_RESET)
>> +		call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
>> +
>> +	return 0;
>> +}
>> +
>>  /*
>>   * initialise the security for the init task
>>   */
>> @@ -6379,6 +6387,10 @@ static __init int selinux_init(void)
>>  	if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
>>  		panic("SELinux: Unable to register AVC netcache callback\n");
>>  
>> +	if (avc_add_callback(selinux_lsm_notifier_avc_callback,
>> +			     AVC_CALLBACK_RESET))
>> +		panic("SELinux: Unable to register AVC LSM notifier callback\n");
>> +
>>  	if (selinux_enforcing)
>>  		printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");
>>  	else
>
Sebastien Buisson April 26, 2017, 3:57 p.m. UTC | #3
2017-04-26 17:48 GMT+02:00 Daniel Jurgens <danielj@mellanox.com>:
> This was part of a larger patch set that hasn't been accepted yet.  SELinux support for Inifiniband.  Subsequent patches in that patch set will use it as well.

I revived this patch following Stephen Smalley's suggestion to base
the policy checksum computation and change notification on the work
you had done on LSM notification callbacks.
Casey Schaufler April 26, 2017, 4:11 p.m. UTC | #4
On 4/26/2017 8:48 AM, Daniel Jurgens wrote:
> On 4/26/2017 10:38 AM, Casey Schaufler wrote:
>> On 4/26/2017 8:02 AM, Sebastien Buisson wrote:
>>> From: Daniel Jurgens <danielj@mellanox.com>
>>>
>>> Add a generic notification mechanism in the LSM. Interested consumers
>>> can register a callback with the LSM and security modules can produce
>>> events.
>> Why is this a generic mechanism? Do you ever see anyone
>> other than SELinux using it?
> I had created an SELinux specific mechanism, Paul Moore requested I make it generic.
>>> Add a call to the notification mechanism from SELinux when the AVC
>>> cache changes.
>> This seems like a whole lot of mechanism for
>> something you could accomplish with a log message.
>> What am I missing?
> This was part of a larger patch set that hasn't been accepted yet.  SELinux support for Inifiniband.  Subsequent patches in that patch set will use it as well.

You should include this information in a 0/3 message.
Without the context the patch set is curious, but not
compelling.

>>> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
>>> Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
>>> ---
>>>  include/linux/security.h | 23 +++++++++++++++++++++++
>>>  security/security.c      | 20 ++++++++++++++++++++
>>>  security/selinux/hooks.c | 12 ++++++++++++
>>>  3 files changed, 55 insertions(+)
>>>
>>> diff --git a/include/linux/security.h b/include/linux/security.h
>>> index af675b5..73a9c93 100644
>>> --- a/include/linux/security.h
>>> +++ b/include/linux/security.h
>>> @@ -68,6 +68,10 @@
>>>  struct user_namespace;
>>>  struct timezone;
>>>  
>>> +enum lsm_event {
>>> +	LSM_POLICY_CHANGE,
>>> +};
>>> +
>>>  /* These functions are in security/commoncap.c */
>>>  extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
>>>  		       int cap, int audit);
>>> @@ -163,6 +167,10 @@ struct security_mnt_opts {
>>>  	int num_mnt_opts;
>>>  };
>>>  
>>> +int call_lsm_notifier(enum lsm_event event, void *data);
>>> +int register_lsm_notifier(struct notifier_block *nb);
>>> +int unregister_lsm_notifier(struct notifier_block *nb);
>>> +
>>>  static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
>>>  {
>>>  	opts->mnt_opts = NULL;
>>> @@ -381,6 +389,21 @@ int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
>>>  struct security_mnt_opts {
>>>  };
>>>  
>>> +static inline int call_lsm_notifier(enum lsm_event event, void *data)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static inline int register_lsm_notifier(struct notifier_block *nb)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static inline  int unregister_lsm_notifier(struct notifier_block *nb)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>>  static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
>>>  {
>>>  }
>>> diff --git a/security/security.c b/security/security.c
>>> index b9fea39..ef9d9e1 100644
>>> --- a/security/security.c
>>> +++ b/security/security.c
>>> @@ -32,6 +32,8 @@
>>>  /* Maximum number of letters for an LSM name string */
>>>  #define SECURITY_NAME_MAX	10
>>>  
>>> +static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
>>> +
>>>  struct security_hook_heads security_hook_heads __lsm_ro_after_init;
>>>  char *lsm_names;
>>>  /* Boot-time LSM user choice */
>>> @@ -146,6 +148,24 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
>>>  		panic("%s - Cannot get early memory.\n", __func__);
>>>  }
>>>  
>>> +int call_lsm_notifier(enum lsm_event event, void *data)
>>> +{
>>> +	return atomic_notifier_call_chain(&lsm_notifier_chain, event, data);
>>> +}
>>> +EXPORT_SYMBOL(call_lsm_notifier);
>>> +
>>> +int register_lsm_notifier(struct notifier_block *nb)
>>> +{
>>> +	return atomic_notifier_chain_register(&lsm_notifier_chain, nb);
>>> +}
>>> +EXPORT_SYMBOL(register_lsm_notifier);
>>> +
>>> +int unregister_lsm_notifier(struct notifier_block *nb)
>>> +{
>>> +	return atomic_notifier_chain_unregister(&lsm_notifier_chain, nb);
>>> +}
>>> +EXPORT_SYMBOL(unregister_lsm_notifier);
>>> +
>>>  /*
>>>   * Hook list operation macros.
>>>   *
>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>>> index e67a526..a4d36f8 100644
>>> --- a/security/selinux/hooks.c
>>> +++ b/security/selinux/hooks.c
>>> @@ -171,6 +171,14 @@ static int selinux_netcache_avc_callback(u32 event)
>>>  	return 0;
>>>  }
>>>  
>>> +static int selinux_lsm_notifier_avc_callback(u32 event)
>>> +{
>>> +	if (event == AVC_CALLBACK_RESET)
>>> +		call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  /*
>>>   * initialise the security for the init task
>>>   */
>>> @@ -6379,6 +6387,10 @@ static __init int selinux_init(void)
>>>  	if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
>>>  		panic("SELinux: Unable to register AVC netcache callback\n");
>>>  
>>> +	if (avc_add_callback(selinux_lsm_notifier_avc_callback,
>>> +			     AVC_CALLBACK_RESET))
>>> +		panic("SELinux: Unable to register AVC LSM notifier callback\n");
>>> +
>>>  	if (selinux_enforcing)
>>>  		printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");
>>>  	else
>
Stephen Smalley April 26, 2017, 5:36 p.m. UTC | #5
On Wed, 2017-04-26 at 08:38 -0700, Casey Schaufler wrote:
> On 4/26/2017 8:02 AM, Sebastien Buisson wrote:
> > From: Daniel Jurgens <danielj@mellanox.com>
> > 
> > Add a generic notification mechanism in the LSM. Interested
> > consumers
> > can register a callback with the LSM and security modules can
> > produce
> > events.
> 
> Why is this a generic mechanism? Do you ever see anyone
> other than SELinux using it?

I do - any security module that wants to support access control over
Lustre filesystems or Infiniband. Seems ironic for you to be arguing
for a SELinux-specific interface rather than a LSM interface.

> 
> > Add a call to the notification mechanism from SELinux when the AVC
> > cache changes.
> 
> This seems like a whole lot of mechanism for
> something you could accomplish with a log message.
> What am I missing?

It's a notification to a kernel subsystem that policy has changed so
that the subsystem can update any cached state.

> 
> > 
> > Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
> > Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
> > ---
> >  include/linux/security.h | 23 +++++++++++++++++++++++
> >  security/security.c      | 20 ++++++++++++++++++++
> >  security/selinux/hooks.c | 12 ++++++++++++
> >  3 files changed, 55 insertions(+)
> > 
> > diff --git a/include/linux/security.h b/include/linux/security.h
> > index af675b5..73a9c93 100644
> > --- a/include/linux/security.h
> > +++ b/include/linux/security.h
> > @@ -68,6 +68,10 @@
> >  struct user_namespace;
> >  struct timezone;
> >  
> > +enum lsm_event {
> > +	LSM_POLICY_CHANGE,
> > +};
> > +
> >  /* These functions are in security/commoncap.c */
> >  extern int cap_capable(const struct cred *cred, struct
> > user_namespace *ns,
> >  		       int cap, int audit);
> > @@ -163,6 +167,10 @@ struct security_mnt_opts {
> >  	int num_mnt_opts;
> >  };
> >  
> > +int call_lsm_notifier(enum lsm_event event, void *data);
> > +int register_lsm_notifier(struct notifier_block *nb);
> > +int unregister_lsm_notifier(struct notifier_block *nb);
> > +
> >  static inline void security_init_mnt_opts(struct security_mnt_opts
> > *opts)
> >  {
> >  	opts->mnt_opts = NULL;
> > @@ -381,6 +389,21 @@ int security_sem_semop(struct sem_array *sma,
> > struct sembuf *sops,
> >  struct security_mnt_opts {
> >  };
> >  
> > +static inline int call_lsm_notifier(enum lsm_event event, void
> > *data)
> > +{
> > +	return 0;
> > +}
> > +
> > +static inline int register_lsm_notifier(struct notifier_block *nb)
> > +{
> > +	return 0;
> > +}
> > +
> > +static inline  int unregister_lsm_notifier(struct notifier_block
> > *nb)
> > +{
> > +	return 0;
> > +}
> > +
> >  static inline void security_init_mnt_opts(struct security_mnt_opts
> > *opts)
> >  {
> >  }
> > diff --git a/security/security.c b/security/security.c
> > index b9fea39..ef9d9e1 100644
> > --- a/security/security.c
> > +++ b/security/security.c
> > @@ -32,6 +32,8 @@
> >  /* Maximum number of letters for an LSM name string */
> >  #define SECURITY_NAME_MAX	10
> >  
> > +static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
> > +
> >  struct security_hook_heads security_hook_heads
> > __lsm_ro_after_init;
> >  char *lsm_names;
> >  /* Boot-time LSM user choice */
> > @@ -146,6 +148,24 @@ void __init security_add_hooks(struct
> > security_hook_list *hooks, int count,
> >  		panic("%s - Cannot get early memory.\n",
> > __func__);
> >  }
> >  
> > +int call_lsm_notifier(enum lsm_event event, void *data)
> > +{
> > +	return atomic_notifier_call_chain(&lsm_notifier_chain,
> > event, data);
> > +}
> > +EXPORT_SYMBOL(call_lsm_notifier);
> > +
> > +int register_lsm_notifier(struct notifier_block *nb)
> > +{
> > +	return atomic_notifier_chain_register(&lsm_notifier_chain,
> > nb);
> > +}
> > +EXPORT_SYMBOL(register_lsm_notifier);
> > +
> > +int unregister_lsm_notifier(struct notifier_block *nb)
> > +{
> > +	return
> > atomic_notifier_chain_unregister(&lsm_notifier_chain, nb);
> > +}
> > +EXPORT_SYMBOL(unregister_lsm_notifier);
> > +
> >  /*
> >   * Hook list operation macros.
> >   *
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index e67a526..a4d36f8 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -171,6 +171,14 @@ static int selinux_netcache_avc_callback(u32
> > event)
> >  	return 0;
> >  }
> >  
> > +static int selinux_lsm_notifier_avc_callback(u32 event)
> > +{
> > +	if (event == AVC_CALLBACK_RESET)
> > +		call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
> > +
> > +	return 0;
> > +}
> > +
> >  /*
> >   * initialise the security for the init task
> >   */
> > @@ -6379,6 +6387,10 @@ static __init int selinux_init(void)
> >  	if (avc_add_callback(selinux_netcache_avc_callback,
> > AVC_CALLBACK_RESET))
> >  		panic("SELinux: Unable to register AVC netcache
> > callback\n");
> >  
> > +	if (avc_add_callback(selinux_lsm_notifier_avc_callback,
> > +			     AVC_CALLBACK_RESET))
> > +		panic("SELinux: Unable to register AVC LSM
> > notifier callback\n");
> > +
> >  	if (selinux_enforcing)
> >  		printk(KERN_DEBUG "SELinux:  Starting in enforcing
> > mode\n");
> >  	else
Casey Schaufler April 26, 2017, 5:47 p.m. UTC | #6
On 4/26/2017 10:36 AM, Stephen Smalley wrote:
> On Wed, 2017-04-26 at 08:38 -0700, Casey Schaufler wrote:
>> On 4/26/2017 8:02 AM, Sebastien Buisson wrote:
>>> From: Daniel Jurgens <danielj@mellanox.com>
>>>
>>> Add a generic notification mechanism in the LSM. Interested
>>> consumers
>>> can register a callback with the LSM and security modules can
>>> produce
>>> events.
>> Why is this a generic mechanism? Do you ever see anyone
>> other than SELinux using it?
> I do - any security module that wants to support access control over
> Lustre filesystems or Infiniband. Seems ironic for you to be arguing
> for a SELinux-specific interface rather than a LSM interface.

I lost the connection between this mechanism and
Lustre and Infiniband, neither of which are mentioned
in the patchset. And I *did* pose it as a question.
I am all in favor of general mechanisms where they
are generally useful. I am also adverse to special
purpose clutter.

>
>>> Add a call to the notification mechanism from SELinux when the AVC
>>> cache changes.
>> This seems like a whole lot of mechanism for
>> something you could accomplish with a log message.
>> What am I missing?
> It's a notification to a kernel subsystem that policy has changed so
> that the subsystem can update any cached state.
>
>>> Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
>>> Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
>>> ---
>>>  include/linux/security.h | 23 +++++++++++++++++++++++
>>>  security/security.c      | 20 ++++++++++++++++++++
>>>  security/selinux/hooks.c | 12 ++++++++++++
>>>  3 files changed, 55 insertions(+)
>>>
>>> diff --git a/include/linux/security.h b/include/linux/security.h
>>> index af675b5..73a9c93 100644
>>> --- a/include/linux/security.h
>>> +++ b/include/linux/security.h
>>> @@ -68,6 +68,10 @@
>>>  struct user_namespace;
>>>  struct timezone;
>>>  
>>> +enum lsm_event {
>>> +	LSM_POLICY_CHANGE,
>>> +};
>>> +
>>>  /* These functions are in security/commoncap.c */
>>>  extern int cap_capable(const struct cred *cred, struct
>>> user_namespace *ns,
>>>  		       int cap, int audit);
>>> @@ -163,6 +167,10 @@ struct security_mnt_opts {
>>>  	int num_mnt_opts;
>>>  };
>>>  
>>> +int call_lsm_notifier(enum lsm_event event, void *data);
>>> +int register_lsm_notifier(struct notifier_block *nb);
>>> +int unregister_lsm_notifier(struct notifier_block *nb);
>>> +
>>>  static inline void security_init_mnt_opts(struct security_mnt_opts
>>> *opts)
>>>  {
>>>  	opts->mnt_opts = NULL;
>>> @@ -381,6 +389,21 @@ int security_sem_semop(struct sem_array *sma,
>>> struct sembuf *sops,
>>>  struct security_mnt_opts {
>>>  };
>>>  
>>> +static inline int call_lsm_notifier(enum lsm_event event, void
>>> *data)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static inline int register_lsm_notifier(struct notifier_block *nb)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static inline  int unregister_lsm_notifier(struct notifier_block
>>> *nb)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>>  static inline void security_init_mnt_opts(struct security_mnt_opts
>>> *opts)
>>>  {
>>>  }
>>> diff --git a/security/security.c b/security/security.c
>>> index b9fea39..ef9d9e1 100644
>>> --- a/security/security.c
>>> +++ b/security/security.c
>>> @@ -32,6 +32,8 @@
>>>  /* Maximum number of letters for an LSM name string */
>>>  #define SECURITY_NAME_MAX	10
>>>  
>>> +static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
>>> +
>>>  struct security_hook_heads security_hook_heads
>>> __lsm_ro_after_init;
>>>  char *lsm_names;
>>>  /* Boot-time LSM user choice */
>>> @@ -146,6 +148,24 @@ void __init security_add_hooks(struct
>>> security_hook_list *hooks, int count,
>>>  		panic("%s - Cannot get early memory.\n",
>>> __func__);
>>>  }
>>>  
>>> +int call_lsm_notifier(enum lsm_event event, void *data)
>>> +{
>>> +	return atomic_notifier_call_chain(&lsm_notifier_chain,
>>> event, data);
>>> +}
>>> +EXPORT_SYMBOL(call_lsm_notifier);
>>> +
>>> +int register_lsm_notifier(struct notifier_block *nb)
>>> +{
>>> +	return atomic_notifier_chain_register(&lsm_notifier_chain,
>>> nb);
>>> +}
>>> +EXPORT_SYMBOL(register_lsm_notifier);
>>> +
>>> +int unregister_lsm_notifier(struct notifier_block *nb)
>>> +{
>>> +	return
>>> atomic_notifier_chain_unregister(&lsm_notifier_chain, nb);
>>> +}
>>> +EXPORT_SYMBOL(unregister_lsm_notifier);
>>> +
>>>  /*
>>>   * Hook list operation macros.
>>>   *
>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>>> index e67a526..a4d36f8 100644
>>> --- a/security/selinux/hooks.c
>>> +++ b/security/selinux/hooks.c
>>> @@ -171,6 +171,14 @@ static int selinux_netcache_avc_callback(u32
>>> event)
>>>  	return 0;
>>>  }
>>>  
>>> +static int selinux_lsm_notifier_avc_callback(u32 event)
>>> +{
>>> +	if (event == AVC_CALLBACK_RESET)
>>> +		call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  /*
>>>   * initialise the security for the init task
>>>   */
>>> @@ -6379,6 +6387,10 @@ static __init int selinux_init(void)
>>>  	if (avc_add_callback(selinux_netcache_avc_callback,
>>> AVC_CALLBACK_RESET))
>>>  		panic("SELinux: Unable to register AVC netcache
>>> callback\n");
>>>  
>>> +	if (avc_add_callback(selinux_lsm_notifier_avc_callback,
>>> +			     AVC_CALLBACK_RESET))
>>> +		panic("SELinux: Unable to register AVC LSM
>>> notifier callback\n");
>>> +
>>>  	if (selinux_enforcing)
>>>  		printk(KERN_DEBUG "SELinux:  Starting in enforcing
>>> mode\n");
>>>  	else
diff mbox

Patch

diff --git a/include/linux/security.h b/include/linux/security.h
index af675b5..73a9c93 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -68,6 +68,10 @@ 
 struct user_namespace;
 struct timezone;
 
+enum lsm_event {
+	LSM_POLICY_CHANGE,
+};
+
 /* These functions are in security/commoncap.c */
 extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
 		       int cap, int audit);
@@ -163,6 +167,10 @@  struct security_mnt_opts {
 	int num_mnt_opts;
 };
 
+int call_lsm_notifier(enum lsm_event event, void *data);
+int register_lsm_notifier(struct notifier_block *nb);
+int unregister_lsm_notifier(struct notifier_block *nb);
+
 static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
 {
 	opts->mnt_opts = NULL;
@@ -381,6 +389,21 @@  int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
 struct security_mnt_opts {
 };
 
+static inline int call_lsm_notifier(enum lsm_event event, void *data)
+{
+	return 0;
+}
+
+static inline int register_lsm_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+
+static inline  int unregister_lsm_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+
 static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
 {
 }
diff --git a/security/security.c b/security/security.c
index b9fea39..ef9d9e1 100644
--- a/security/security.c
+++ b/security/security.c
@@ -32,6 +32,8 @@ 
 /* Maximum number of letters for an LSM name string */
 #define SECURITY_NAME_MAX	10
 
+static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
+
 struct security_hook_heads security_hook_heads __lsm_ro_after_init;
 char *lsm_names;
 /* Boot-time LSM user choice */
@@ -146,6 +148,24 @@  void __init security_add_hooks(struct security_hook_list *hooks, int count,
 		panic("%s - Cannot get early memory.\n", __func__);
 }
 
+int call_lsm_notifier(enum lsm_event event, void *data)
+{
+	return atomic_notifier_call_chain(&lsm_notifier_chain, event, data);
+}
+EXPORT_SYMBOL(call_lsm_notifier);
+
+int register_lsm_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&lsm_notifier_chain, nb);
+}
+EXPORT_SYMBOL(register_lsm_notifier);
+
+int unregister_lsm_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&lsm_notifier_chain, nb);
+}
+EXPORT_SYMBOL(unregister_lsm_notifier);
+
 /*
  * Hook list operation macros.
  *
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e67a526..a4d36f8 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -171,6 +171,14 @@  static int selinux_netcache_avc_callback(u32 event)
 	return 0;
 }
 
+static int selinux_lsm_notifier_avc_callback(u32 event)
+{
+	if (event == AVC_CALLBACK_RESET)
+		call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
+
+	return 0;
+}
+
 /*
  * initialise the security for the init task
  */
@@ -6379,6 +6387,10 @@  static __init int selinux_init(void)
 	if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
 		panic("SELinux: Unable to register AVC netcache callback\n");
 
+	if (avc_add_callback(selinux_lsm_notifier_avc_callback,
+			     AVC_CALLBACK_RESET))
+		panic("SELinux: Unable to register AVC LSM notifier callback\n");
+
 	if (selinux_enforcing)
 		printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");
 	else