[PATCH] Hooks for capget, capset

From: Stephen Smalley (sdsat_private)
Date: Tue Aug 14 2001 - 07:45:43 PDT

  • Next message: Stephen Smalley: "Re: USENIX Security LSM BOF topics"

    The attached patch (relative to my previous patch that fixed
    some bugs in the security_ops->capable/cap_capable calls) implements
    hooks for the capget and capset calls.  I left as much as possible of the
    functional logic in those calls untouched, only moving code that
    examines or modifies the capability bits and code that performs
    capability-specific authorization checks.  Two hooks were
    defined for capset - the capset_check hook replaces the 
    authorization checks, and the capset_set hook performs the
    actual setting of the capability bits for a particular task.
    
    This patch does not address moving the capability bits from the kernel
    data structures (task_struct, linux_binprm, netlink_skb_parms) into the
    security objects, nor does it move all code that examines or modifies
    capability bits.  Here are some functions that I know examine or modify
    capability bits and would need to be modified if we were to move
    the bits into the security objects:
    fs/open.c:sys_access()
    fs/lockd/host.c:nlm_bind_host()
    fs/nfsd/auth.c:nfsd_setuser()
    fs/proc/array.c:task_cap()
    mm/oom_kill.c:badness(),oom_kill()
    net/netlink/af_netlink.c:netlink_sendmsg()
    net/core/rtnetlink.c:rtnetlink_rcv_msg()
    net/ipv4/netfilter/ip_queue.c:netlink_receive_user_skb()
    
    --
    Stephen D. Smalley, NAI Labs
    ssmalleyat_private
    
    
    
    
    Index: lsm/include/linux/security.h
    diff -u lsm/include/linux/security.h:1.38 lsm/include/linux/security.h:1.39
    --- lsm/include/linux/security.h:1.38	Mon Aug 13 09:54:37 2001
    +++ lsm/include/linux/security.h	Tue Aug 14 10:15:51 2001
    @@ -243,7 +243,9 @@
     	int  (* ioperm)			(unsigned long from, unsigned long num, int turn_on);
     	int  (* iopl)			(unsigned int old, unsigned int level);		
     	int  (* ptrace)			(struct task_struct *parent, struct task_struct *child);		
    -	int  (* setcapability)		(void);		
    +	int  (*capget)                  (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
    +	int  (*capset_check)            (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
    +	void  (*capset_set)            (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
     	int  (* acct)			(struct file *file);
     	int  (* sysctl)			(ctl_table * table, int op);
     	int  (* capable)	        (struct task_struct *tsk, int cap); 
    Index: lsm/security/security.c
    diff -u lsm/security/security.c:1.36 lsm/security/security.c:1.37
    --- lsm/security/security.c:1.36	Mon Aug 13 08:18:38 2001
    +++ lsm/security/security.c	Tue Aug 14 10:15:51 2001
    @@ -50,7 +50,9 @@
     static int dummy_ioperm	(unsigned long from, unsigned long num, int turn_on)	{return 0;}
     static int dummy_iopl	(unsigned int old, unsigned int level)	{return 0;}
     static int dummy_ptrace		(struct task_struct *parent, struct task_struct *child)	{return 0;}
    -static int dummy_setcapablity	(void)	{return 0;}
    +static int dummy_capget            (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { return 0; }
    +static int dummy_capset_check            (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { return 0; }
    +static void dummy_capset_set            (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { return; }
     static int dummy_acct		(struct file *file)	{return 0;}
     
     static int dummy_capable(struct task_struct *tsk, int cap)
    @@ -408,7 +410,9 @@
     	ioperm:			dummy_ioperm,
     	iopl:			dummy_iopl,
     	ptrace:			dummy_ptrace,
    -	setcapability:		dummy_setcapablity,
    +	capget:		        dummy_capget,
    +	capset_check:	        dummy_capset_check,
    +	capset_set:	        dummy_capset_set,
     	acct:			dummy_acct,
     	capable:		dummy_capable,
     	sysctl:			dummy_sysctl,
    @@ -482,7 +486,9 @@
     	    !ops->ioperm ||
     	    !ops->iopl ||
     	    !ops->ptrace ||
    -	    !ops->setcapability ||
    +	    !ops->capget ||
    +	    !ops->capset_check ||
    +	    !ops->capset_set ||
     	    !ops->acct ||
     	    !ops->capable ||
     	    !ops->sysctl ||
    Index: lsm/kernel/capability.c
    diff -u lsm/kernel/capability.c:1.1 lsm/kernel/capability.c:1.2
    --- lsm/kernel/capability.c:1.1	Mon Jun 11 14:19:57 2001
    +++ lsm/kernel/capability.c	Tue Aug 14 10:15:51 2001
    @@ -57,9 +57,7 @@
          }
     
          if (!error) { 
    -	     data.permitted = cap_t(target->cap_permitted);
    -	     data.inheritable = cap_t(target->cap_inheritable); 
    -	     data.effective = cap_t(target->cap_effective);
    +	     error = security_ops->capget(target, &data.effective, &data.inheritable, &data.permitted);
          }
     
          if (target != current)
    @@ -88,9 +86,7 @@
          for_each_task(target) {
                  if (target->pgrp != pgrp)
                          continue;
    -             target->cap_effective   = *effective;
    -             target->cap_inheritable = *inheritable;
    -             target->cap_permitted   = *permitted;
    +	     security_ops->capset_set(target, effective, inheritable, permitted);
          }
          read_unlock(&tasklist_lock);
     }
    @@ -109,9 +105,7 @@
          for_each_task(target) {
                  if (target == current || target->pid == 1)
                          continue;
    -             target->cap_effective   = *effective;
    -             target->cap_inheritable = *inheritable;
    -             target->cap_permitted   = *permitted;
    +	     security_ops->capset_set(target, effective, inheritable, permitted);
          }
          read_unlock(&tasklist_lock);
     }
    @@ -168,28 +162,10 @@
                  target = current;
          }
     
    +     error = security_ops->capset_check(target, &effective, &inheritable, &permitted);
    +     if (error)
    +	     goto out;
     
    -     /* verify restrictions on target's new Inheritable set */
    -     if (!cap_issubset(inheritable,
    -                       cap_combine(target->cap_inheritable,
    -                                   current->cap_permitted))) {
    -             goto out;
    -     }
    -
    -     /* verify restrictions on target's new Permitted set */
    -     if (!cap_issubset(permitted,
    -                       cap_combine(target->cap_permitted,
    -                                   current->cap_permitted))) {
    -             goto out;
    -     }
    -
    -     /* verify the _new_Effective_ is a subset of the _new_Permitted_ */
    -     if (!cap_issubset(effective, permitted)) {
    -             goto out;
    -     }
    -
    -     /* having verified that the proposed changes are legal,
    -           we now put them into effect. */
          error = 0;
     
          if (pid < 0) {
    @@ -200,10 +176,7 @@
                          cap_set_pg(-pid, &effective, &inheritable, &permitted);
                  goto spin_out;
          } else {
    -             /* FIXME: do we need to have a write lock here..? */
    -             target->cap_effective   = effective;
    -             target->cap_inheritable = inheritable;
    -             target->cap_permitted   = permitted;
    +	     security_ops->capset_set(target, &effective, &inheritable, &permitted);
          }
     
     out:
    Index: lsm/security/capability_plug.c
    diff -u lsm/security/capability_plug.c:1.22 lsm/security/capability_plug.c:1.23
    --- lsm/security/capability_plug.c:1.22	Tue Aug 14 08:17:00 2001
    +++ lsm/security/capability_plug.c	Tue Aug 14 10:15:51 2001
    @@ -60,7 +60,47 @@
     		return 0;
     }
     
    -static int cap_setcapablity	(void)	{return 0;}
    +static int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted)	
    +{
    +	/* Derived from kernel/capability.c:sys_capget. */
    +	*effective = cap_t(target->cap_effective);	
    +	*inheritable = cap_t(target->cap_inheritable); 
    +	*permitted = cap_t(target->cap_permitted);
    +	return 0;
    +}
    +
    +static int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted)	
    +{
    +	/* Derived from kernel/capability.c:sys_capset. */
    +	/* verify restrictions on target's new Inheritable set */
    +	if (!cap_issubset(*inheritable,
    +			  cap_combine(target->cap_inheritable,
    +				      current->cap_permitted))) {
    +		return -EPERM;
    +	}
    +
    +	/* verify restrictions on target's new Permitted set */
    +	if (!cap_issubset(*permitted,
    +			  cap_combine(target->cap_permitted,
    +				      current->cap_permitted))) {
    +		return -EPERM;
    +	}
    +
    +	/* verify the _new_Effective_ is a subset of the _new_Permitted_ */
    +	if (!cap_issubset(*effective, *permitted)) {
    +		return -EPERM;
    +	}
    +	
    +	return 0;
    +}
    +
    +static void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) 
    +{
    +	target->cap_effective   = *effective;
    +	target->cap_inheritable = *inheritable;
    +	target->cap_permitted   = *permitted;
    +}
    +
     static int cap_acct		(struct file *file) {return 0;}
     static int cap_sysctl		(ctl_table * table, int op) {return 0;}
     
    @@ -574,7 +614,9 @@
     	ioperm:			cap_ioperm,
     	iopl:			cap_iopl,
     	ptrace:			cap_ptrace,
    -	setcapability:		cap_setcapablity,
    +	capget:		        cap_capget,
    +	capset_check:	        cap_capset_check,
    +	capset_set:	        cap_capset_set,
     	acct:			cap_acct,
     	sysctl:			cap_sysctl,
     	capable:		cap_capable,
    
    _______________________________________________
    linux-security-module mailing list
    linux-security-moduleat_private
    http://mail.wirex.com/mailman/listinfo/linux-security-module
    



    This archive was generated by hypermail 2b30 : Tue Aug 14 2001 - 07:48:10 PDT