After further thought, it seems that it would be sufficient to apply the attached patch to solve the problem with the netlink socket code. This patch defines two hooks in security_ops, netlink_send and netlink_recv, that merely pass the sk_buff. The netlink_send hook is called by netlink_sendmsg in place of the old code that directly set the eff_cap field. The dummy plug and capability plug merely use the existing eff_cap field in the netlink_skb_parms struct to save the necessary information. The dummy_netlink_send hook function sets eff_cap to CAP_NET_ADMIN if the sending process has a superuser euid or to 0 otherwise. The cap_netlink_send hook function sets eff_cap to current->cap_effective, as in the original kernel logic. The netlink_recv hook is called by rtnetlink_rcv_msg and netlink_receive_user_skb in place of the old cap_raised tests. The dummy_netlink_recv and cap_netlink_recv hook functions merely perform the cap_raised test on the eff_cap field. Other modules are free to use the skb security field if they wish to store other information, but there is no requirement to do so. Modules can follow the same approach as the dummy module (i.e. check the sending process's attributes in netlink_send and only set CAP_NET_ADMIN in eff_cap if the process is authorized). This avoids any dependency on the skb security field for this change. -- Stephen D. Smalley, NAI Labs ssmalleyat_private diff -X /home/sds/dontdiff -ru lsm-wirex/include/linux/security.h lsm/include/linux/security.h --- lsm-wirex/include/linux/security.h Tue Aug 21 11:34:19 2001 +++ lsm/include/linux/security.h Tue Aug 21 13:48:18 2001 @@ -263,6 +263,9 @@ int (* swapoff) (struct dentry *dentry); int (* nfsservctl) (int cmd, struct nfsctl_arg *arg); + int (* netlink_send) (struct sk_buff *skb); + int (* netlink_recv) (struct sk_buff *skb); + struct binprm_security_ops * bprm_ops; struct super_block_security_ops * sb_ops; struct inode_security_ops * inode_ops; diff -X /home/sds/dontdiff -ru lsm-wirex/net/core/rtnetlink.c lsm/net/core/rtnetlink.c --- lsm-wirex/net/core/rtnetlink.c Mon Aug 13 08:19:49 2001 +++ lsm/net/core/rtnetlink.c Tue Aug 21 13:35:36 2001 @@ -322,7 +322,7 @@ sz_idx = type>>2; kind = type&3; - if (kind != 2 && !cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) { + if (kind != 2 && security_ops->netlink_recv(skb)) { *errp = -EPERM; return -1; } diff -X /home/sds/dontdiff -ru lsm-wirex/net/ipv4/netfilter/ip_queue.c lsm/net/ipv4/netfilter/ip_queue.c --- lsm-wirex/net/ipv4/netfilter/ip_queue.c Wed Aug 8 08:29:29 2001 +++ lsm/net/ipv4/netfilter/ip_queue.c Tue Aug 21 13:35:57 2001 @@ -516,7 +516,7 @@ RCV_SKB_FAIL(-EINVAL); if (type <= IPQM_BASE) return; - if(!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) + if (security_ops->netlink_recv(skb)) { RCV_SKB_FAIL(-EPERM); if (nlq->peer.pid && !nlq->peer.died && (nlq->peer.pid != nlh->nlmsg_pid)) { diff -X /home/sds/dontdiff -ru lsm-wirex/net/netlink/af_netlink.c lsm/net/netlink/af_netlink.c --- lsm-wirex/net/netlink/af_netlink.c Wed Aug 8 08:29:29 2001 +++ lsm/net/netlink/af_netlink.c Tue Aug 21 13:28:15 2001 @@ -599,7 +599,12 @@ check them, when this message will be delivered to corresponding kernel module. --ANK (980802) */ - NETLINK_CB(skb).eff_cap = current->cap_effective; + + err = security_ops->netlink_send(skb); + if (err) { + kfree_skb(skb); + goto out; + } err = -EFAULT; if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) { diff -X /home/sds/dontdiff -ru lsm-wirex/security/capability_plug.c lsm/security/capability_plug.c --- lsm-wirex/security/capability_plug.c Tue Aug 21 11:34:19 2001 +++ lsm/security/capability_plug.c Tue Aug 21 13:45:21 2001 @@ -20,6 +20,7 @@ #include <linux/smp_lock.h> #include <linux/netfilter.h> #include <linux/netdevice.h> +#include <linux/netlink.h> #include <asm/uaccess.h> @@ -53,6 +54,19 @@ static int cap_swapoff (struct dentry *dentry) {return 0;} static int cap_nfsservctl (int cmd, struct nfsctl_arg *arg) {return 0;} +static int cap_netlink_send (struct sk_buff *skb) +{ + NETLINK_CB(skb).eff_cap = current->cap_effective; + return 0; +} + +static int cap_netlink_recv (struct sk_buff *skb) +{ + if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) + return -EPERM; + return 0; +} + static int cap_ptrace(struct task_struct *parent, struct task_struct *child) { /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ @@ -629,6 +643,8 @@ swapon: cap_swapon, swapoff: cap_swapoff, nfsservctl: cap_nfsservctl, + netlink_send: cap_netlink_send, + netlink_recv: cap_netlink_recv, bprm_ops: &cap_binprm_ops, sb_ops: &cap_sb_ops, diff -X /home/sds/dontdiff -ru lsm-wirex/security/security.c lsm/security/security.c --- lsm-wirex/security/security.c Tue Aug 21 11:34:19 2001 +++ lsm/security/security.c Tue Aug 21 13:45:14 2001 @@ -33,6 +33,7 @@ #include <linux/sysctl.h> #include <linux/netfilter.h> #include <linux/netdevice.h> +#include <linux/netlink.h> struct security_operations *security_ops; /* Initialized to NULL */ @@ -73,6 +74,22 @@ static int dummy_swapoff (struct dentry *dentry) {return 0;} static int dummy_nfsservctl (int cmd, struct nfsctl_arg *arg) {return 0;} +static int dummy_netlink_send (struct sk_buff *skb) +{ + if (current->euid == 0) + NETLINK_CB(skb).eff_cap = CAP_NET_ADMIN; + else + NETLINK_CB(skb).eff_cap = 0; + return 0; +} + +static int dummy_netlink_recv (struct sk_buff *skb) +{ + if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) + return -EPERM; + return 0; +} + static int dummy_binprm_alloc_security (struct linux_binprm *bprm) {return 0;} static void dummy_binprm_free_security (struct linux_binprm *bprm) {return;} static void dummy_binprm_compute_creds (struct linux_binprm *bprm) {return;} @@ -425,6 +442,8 @@ swapon: dummy_swapon, swapoff: dummy_swapoff, nfsservctl: dummy_nfsservctl, + netlink_send: dummy_netlink_send, + netlink_recv: dummy_netlink_recv, bprm_ops: &dummy_binprm_ops, sb_ops: &dummy_sb_ops, @@ -504,6 +523,8 @@ !ops->swapon || !ops->swapoff || !ops->nfsservctl || + !ops->netlink_send || + !ops->netlink_recv || !ops->bprm_ops || !ops->sb_ops || !ops->inode_ops || _______________________________________________ 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 21 2001 - 11:05:27 PDT