Re: Capability tests in netlink and oom_kill

From: Stephen Smalley (sdsat_private)
Date: Tue Aug 21 2001 - 11:02:54 PDT

  • Next message: Evan Sarmiento: "Re: FreeBSD hooks"

    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