Re: [PATCH -v2 1/3] SECURITY: new capable_noaudit interface

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

 



On Mon, 2008-11-03 at 16:27 -0500, Eric Paris wrote:
> Add a new capable interface that will be used by systems that use audit to
> make an A or B type decision instead of a security decision.  Currently
> this is the case at least for filesystems when deciding if a process can use
> the reserved 'root' blocks and for the case of things like the oom
> algorithm determining if processes are root processes and should be less
> likely to be killed.  These types of security system requests should not be
> audited or logged since they are not really security decisions.  It would be
> possible to solve this problem like the vm_enough_memory security check did
> by creating a new LSM interface and moving all of the policy into that
> interface but proves the needlessly bloat the LSM and provide complex
> indirection.
> 
> This merely allows those decisions to be made where they belong and to not
> flood logs or printk with denials for thing that are not security decisions.
> 
> Signed-off-by: Eric Paris <eparis@xxxxxxxxxx>

You could further simplify the hooks where we already (before this
patch) split the capability check into separate secondary_ops->capable()
and avc_has_perm_noaudit() calls since you can now just call your new
_noaudit interface there.

But the patch appears to be correct.

Acked-by:  Stephen Smalley <sds@xxxxxxxxxxxxx>
> ---
> 
>  include/linux/capability.h |    3 +++
>  include/linux/security.h   |   16 +++++++++++++---
>  security/commoncap.c       |    8 ++++----
>  security/security.c        |    7 ++++++-
>  security/selinux/hooks.c   |   20 +++++++++++++-------
>  5 files changed, 39 insertions(+), 15 deletions(-)
> 
> diff --git a/include/linux/capability.h b/include/linux/capability.h
> index 9d1fe30..0a0379b 100644
> --- a/include/linux/capability.h
> +++ b/include/linux/capability.h
> @@ -503,6 +503,8 @@ extern const kernel_cap_t __cap_init_eff_set;
>  
>  kernel_cap_t cap_set_effective(const kernel_cap_t pE_new);
>  
> +extern int security_capable(struct task_struct *t, int cap);
> +extern int security_capable_noaudit(struct task_struct *t, int cap);
>  /**
>   * has_capability - Determine if a task has a superior capability available
>   * @t: The task in question
> @@ -514,6 +516,7 @@ kernel_cap_t cap_set_effective(const kernel_cap_t pE_new);
>   * Note that this does not set PF_SUPERPRIV on the task.
>   */
>  #define has_capability(t, cap) (security_capable((t), (cap)) == 0)
> +#define has_capability_noaudit(t, cap) (security_capable_noaudit((t), (cap)) == 0)
>  
>  extern int capable(int cap);
>  
> diff --git a/include/linux/security.h b/include/linux/security.h
> index c13f1ce..5fe28a6 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -37,6 +37,10 @@
>  /* Maximum number of letters for an LSM name string */
>  #define SECURITY_NAME_MAX	10
>  
> +/* If capable should audit the security request */
> +#define SECURITY_CAP_NOAUDIT 0
> +#define SECURITY_CAP_AUDIT 1
> +
>  struct ctl_table;
>  struct audit_krule;
>  
> @@ -44,7 +48,7 @@ struct audit_krule;
>   * These functions are in security/capability.c and are used
>   * as the default capabilities functions
>   */
> -extern int cap_capable(struct task_struct *tsk, int cap);
> +extern int cap_capable(struct task_struct *tsk, int cap, int audit);
>  extern int cap_settime(struct timespec *ts, struct timezone *tz);
>  extern int cap_ptrace_may_access(struct task_struct *child, unsigned int mode);
>  extern int cap_ptrace_traceme(struct task_struct *parent);
> @@ -1307,7 +1311,7 @@ struct security_operations {
>  			    kernel_cap_t *effective,
>  			    kernel_cap_t *inheritable,
>  			    kernel_cap_t *permitted);
> -	int (*capable) (struct task_struct *tsk, int cap);
> +	int (*capable) (struct task_struct *tsk, int cap, int audit);
>  	int (*acct) (struct file *file);
>  	int (*sysctl) (struct ctl_table *table, int op);
>  	int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
> @@ -1577,6 +1581,7 @@ void security_capset_set(struct task_struct *target,
>  			 kernel_cap_t *inheritable,
>  			 kernel_cap_t *permitted);
>  int security_capable(struct task_struct *tsk, int cap);
> +int security_capable_noaudit(struct task_struct *tsk, int cap);
>  int security_acct(struct file *file);
>  int security_sysctl(struct ctl_table *table, int op);
>  int security_quotactl(int cmds, int type, int id, struct super_block *sb);
> @@ -1782,7 +1787,12 @@ static inline void security_capset_set(struct task_struct *target,
>  
>  static inline int security_capable(struct task_struct *tsk, int cap)
>  {
> -	return cap_capable(tsk, cap);
> +	return cap_capable(tsk, cap, SECURITY_CAP_AUDIT);
> +}
> +
> +static inline int security_capable_noaudit(struct task_struct *tsk, int cap)
> +{
> +	return cap_capable(tsk, cap, SECURITY_CAP_NOAUDIT);
>  }
>  
>  static inline int security_acct(struct file *file)
> diff --git a/security/commoncap.c b/security/commoncap.c
> index 3976613..73999f6 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -48,7 +48,7 @@ EXPORT_SYMBOL(cap_netlink_recv);
>   * returns 0 when a task has a capability, but the kernel's capable()
>   * returns 1 for this case.
>   */
> -int cap_capable (struct task_struct *tsk, int cap)
> +int cap_capable(struct task_struct *tsk, int cap, int audit)
>  {
>  	/* Derived from include/linux/sched.h:capable. */
>  	if (cap_raised(tsk->cap_effective, cap))
> @@ -111,7 +111,7 @@ static inline int cap_inh_is_capped(void)
>  	 * to the old permitted set. That is, if the current task
>  	 * does *not* possess the CAP_SETPCAP capability.
>  	 */
> -	return (cap_capable(current, CAP_SETPCAP) != 0);
> +	return (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0);
>  }
>  
>  static inline int cap_limit_ptraced_target(void) { return 1; }
> @@ -640,7 +640,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
>  		    || ((current->securebits & SECURE_ALL_LOCKS
>  			 & ~arg2))                                    /*[2]*/
>  		    || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
> -		    || (cap_capable(current, CAP_SETPCAP) != 0)) {    /*[4]*/
> +		    || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0)) { /*[4]*/
>  			/*
>  			 * [1] no changing of bits that are locked
>  			 * [2] no unlocking of locks
> @@ -705,7 +705,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
>  {
>  	int cap_sys_admin = 0;
>  
> -	if (cap_capable(current, CAP_SYS_ADMIN) == 0)
> +	if (cap_capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT) == 0)
>  		cap_sys_admin = 1;
>  	return __vm_enough_memory(mm, pages, cap_sys_admin);
>  }
> diff --git a/security/security.c b/security/security.c
> index c0acfa7..346f21e 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -163,7 +163,12 @@ void security_capset_set(struct task_struct *target,
>  
>  int security_capable(struct task_struct *tsk, int cap)
>  {
> -	return security_ops->capable(tsk, cap);
> +	return security_ops->capable(tsk, cap, SECURITY_CAP_AUDIT);
> +}
> +
> +int security_capable_noaudit(struct task_struct *tsk, int cap)
> +{
> +	return security_ops->capable(tsk, cap, SECURITY_CAP_NOAUDIT);
>  }
>  
>  int security_acct(struct file *file)
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index f85597a..ee34fbf 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -1365,12 +1365,14 @@ static int task_has_perm(struct task_struct *tsk1,
>  
>  /* Check whether a task is allowed to use a capability. */
>  static int task_has_capability(struct task_struct *tsk,
> -			       int cap)
> +			       int cap, int audit)
>  {
>  	struct task_security_struct *tsec;
>  	struct avc_audit_data ad;
> +	struct av_decision avd;
>  	u16 sclass;
>  	u32 av = CAP_TO_MASK(cap);
> +	int rc;
>  
>  	tsec = tsk->security;
>  
> @@ -1390,7 +1392,11 @@ static int task_has_capability(struct task_struct *tsk,
>  		       "SELinux:  out of range capability %d\n", cap);
>  		BUG();
>  	}
> -	return avc_has_perm(tsec->sid, tsec->sid, sclass, av, &ad);
> +
> +	rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, sclass, av, 0, &avd);
> +	if (audit)
> +		avc_audit(tsec->sid, tsec->sid, sclass, av, &avd, rc, &ad);
> +	return rc;
>  }
>  
>  /* Check whether a task is allowed to use a system operation. */
> @@ -1801,15 +1807,15 @@ static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effecti
>  	secondary_ops->capset_set(target, effective, inheritable, permitted);
>  }
>  
> -static int selinux_capable(struct task_struct *tsk, int cap)
> +static int selinux_capable(struct task_struct *tsk, int cap, int audit)
>  {
>  	int rc;
>  
> -	rc = secondary_ops->capable(tsk, cap);
> +	rc = secondary_ops->capable(tsk, cap, audit);
>  	if (rc)
>  		return rc;
>  
> -	return task_has_capability(tsk, cap);
> +	return task_has_capability(tsk, cap, audit);
>  }
>  
>  static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
> @@ -1974,7 +1980,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
>  	int rc, cap_sys_admin = 0;
>  	struct task_security_struct *tsec = current->security;
>  
> -	rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
> +	rc = secondary_ops->capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT);
>  	if (rc == 0)
>  		rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
>  					  SECCLASS_CAPABILITY,
> @@ -2821,7 +2827,7 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
>  	 * and lack of permission just means that we fall back to the
>  	 * in-core context value, not a denial.
>  	 */
> -	error = secondary_ops->capable(current, CAP_MAC_ADMIN);
> +	error = secondary_ops->capable(current, CAP_MAC_ADMIN, SECURITY_CAP_NOAUDIT);
>  	if (!error)
>  		error = avc_has_perm_noaudit(tsec->sid, tsec->sid,
>  					     SECCLASS_CAPABILITY2,
-- 
Stephen Smalley
National Security Agency


--
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