Here's my first cut at diffs to owlsm to better support stacking. The main change here is that, when stacked, owlsm doesn't try to invoke capability or dummy with any action; instead, it lets the primary module determine when or if to do that. Obviously, any primary module that presumes that owlsm _does_ invoke capability or dummy will need to be modified to eliminate that assumption. Most of this code is to work around something I hadn't realized: the "fill in unstated functions" code presumes that the module is a primary module - for stacked modules, the defaults need to be slightly different. I'll explain that in more detail in a separate email. It can be worked around, but I think it'd be better if the defaults for stacking allowed arbitrary stacking as well, and it won't be hard to do. I would claim that it's a bugfix, so it should still be acceptable as a patch for the mainline. diff -u security.orig/owlsm.c security/owlsm.c --- security.orig/owlsm.c Thu Dec 19 23:27:22 2002 +++ security/owlsm.c Fri Dec 20 14:52:22 2002 @@ -13,6 +13,7 @@ * Copyright (C) 2001 Emily Ratliff <ratliffat_private> * Copyright (C) 2001 Nick Bellinger, Esquire <nickbat_private> * Copyright (C) 2001 Chris Wright <chrisat_private> + * Copyright (C) 2002 David A. Wheeler <dwheelerat_private> * * The fd 0-2 code is based off of code Copyright (C) Pavel Kankovsky * @@ -79,17 +80,60 @@ static int owlsm_decode_options (struct sk_buff *skb, const char *optptr, unsigned char **pp_ptr) { - /* from dummy.c */ - if (!skb && !capable (CAP_NET_RAW)) { - (const unsigned char *) *pp_ptr = optptr; - return -EPERM; + if (!secondary) { + /* from dummy.c */ + if (!skb && !capable (CAP_NET_RAW)) { + (const unsigned char *) *pp_ptr = optptr; + return -EPERM; + } } return 0; } + +/* No-ops, used when owlsm is loaded as a secondary module */ + +static int noop_capget (struct task_struct *target, kernel_cap_t * effective, + kernel_cap_t * inheritable, kernel_cap_t * permitted) +{ + return 0; +} + +static int noop_capset_check (struct task_struct *target, + kernel_cap_t * effective, + kernel_cap_t * inheritable, + kernel_cap_t * permitted) +{ + return 0; +} + +static int noop_capable (struct task_struct *tsk, int cap) +{ + /* capability denied; this is different than the other noop hooks + * because capable() is authoritative. */ + return -EPERM; +} + +static int noop_netlink_send (struct sk_buff *skb) +{ + return 0; +} + +static int noop_netlink_recv (struct sk_buff *skb) +{ + return 0; +} + +static void noop_task_reparent_to_init (struct task_struct *p) +{ + return; +} + + static struct security_operations owlsm_ops = { - /* Use the capability functions for some of the hooks */ + /* When used as a primary, use the capability functions for some + * of the hooks */ .ptrace = cap_ptrace, .capget = cap_capget, .capset_check = cap_capset_check, @@ -111,6 +155,33 @@ .ip_decode_options = owlsm_decode_options, }; +static struct security_operations owlsm_ops_secondary = { + /* When used as a secondary module, don't call either the capability + * functions or the dummy functions that do anything. That way, + * the primary module has complete freedom over how to combine the + * secondary's security policies. + * A secondary must always override the dummy functions that do + * anything: capget, capset_check, capable, netlink_send, + * netlink_recv, task_reparent_to_init, and ip_decode_options: */ + .capget = noop_capget, + .capset_check = noop_capset_check, + .capable = noop_capable, + .netlink_send = noop_netlink_send, + .netlink_recv = noop_netlink_recv, + .task_reparent_to_init = noop_task_reparent_to_init, + + .bprm_alloc_security = owlsm_binprm_alloc_security, + .bprm_free_security = owlsm_binprm_free_security, + .bprm_compute_creds = owlsm_binprm_compute_creds, + .bprm_set_security = owlsm_binprm_set_security, + + .inode_link = owlsm_inode_link, + .inode_follow_link = owlsm_inode_follow_link, + + .ip_decode_options = owlsm_decode_options, + +}; + #if defined(CONFIG_SECURITY_owlsm_MODULE) #define MY_NAME THIS_MODULE->name #else @@ -123,13 +194,15 @@ if (register_security (&owlsm_ops)) { printk (KERN_INFO "Failure registering owlsm module with the kernel\n"); - /* try registering with primary module */ - if (mod_reg_security (MY_NAME, &owlsm_ops)) { + /* Try registering with primary module. + * Set secondary before calling mod_reg_security; + doing it afterwards would cause a race. */ + secondary = 1; + if (mod_reg_security (MY_NAME, &owlsm_ops_secondary)) { printk (KERN_INFO "Failure registering owlsm module " "with primary security module.\n"); return -EINVAL; } - secondary = 1; } printk(KERN_INFO "owlsm LSM initialized\n"); return 0; @@ -139,7 +212,7 @@ { /* remove ourselves from the security framework */ if (secondary) { - if (mod_unreg_security (MY_NAME, &owlsm_ops)) + if (mod_unreg_security (MY_NAME, &owlsm_ops_secondary)) printk (KERN_INFO "Failure unregistering owlsm module " "with primary module.\n"); return; diff -u security.orig/owlsm.h security/owlsm.h --- security.orig/owlsm.h Thu Dec 19 23:27:22 2002 +++ security/owlsm.h Fri Dec 20 14:17:31 2002 @@ -277,12 +277,20 @@ static inline int do_owlsm_sfd_set (struct linux_binprm *bprm) { - return cap_bprm_set_security(bprm); + if (secondary) { + return 0; + } else { + return cap_bprm_set_security(bprm); + } } static inline void do_owlsm_sfd_compute (struct linux_binprm *bprm) { - return cap_bprm_compute_creds(bprm); + if (secondary) { + return; + } else { + return cap_bprm_compute_creds(bprm); + } } #endif /* CONFIG_OWLSM_FD */ _______________________________________________ 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 : Fri Dec 20 2002 - 19:58:53 PST