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