Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7bdb545 authored by Darrel Goeddel's avatar Darrel Goeddel Committed by David S. Miller
Browse files

[NETLINK]: Encapsulate eff_cap usage within security framework.



This patch encapsulates the usage of eff_cap (in netlink_skb_params) within
the security framework by extending security_netlink_recv to include a required
capability parameter and converting all direct usage of eff_caps outside
of the lsm modules to use the interface.  It also updates the SELinux
implementation of the security_netlink_send and security_netlink_recv
hooks to take advantage of the sid in the netlink_skb_params struct.
This also enables SELinux to perform auditing of netlink capability checks.
Please apply, for 2.6.18 if possible.

Signed-off-by: default avatarDarrel Goeddel <dgoeddel@trustedcs.com>
Signed-off-by: default avatarStephen Smalley <sds@tycho.nsa.gov>
Acked-by: default avatarJames Morris <jmorris@namei.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 576a30eb
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ struct xfrm_state;
struct xfrm_user_sec_ctx;

extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
extern int cap_netlink_recv(struct sk_buff *skb);
extern int cap_netlink_recv(struct sk_buff *skb, int cap);

/*
 * Values used in the task_security_ops calls
@@ -656,6 +656,7 @@ struct swap_info_struct;
 *	Check permission before processing the received netlink message in
 *	@skb.
 *	@skb contains the sk_buff structure for the netlink message.
 *	@cap indicates the capability required
 *	Return 0 if permission is granted.
 *
 * Security hooks for Unix domain networking.
@@ -1266,7 +1267,7 @@ struct security_operations {
			  struct sembuf * sops, unsigned nsops, int alter);

	int (*netlink_send) (struct sock * sk, struct sk_buff * skb);
	int (*netlink_recv) (struct sk_buff * skb);
	int (*netlink_recv) (struct sk_buff * skb, int cap);

	/* allow module stacking */
	int (*register_security) (const char *name,
@@ -2032,9 +2033,9 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff * skb)
	return security_ops->netlink_send(sk, skb);
}

static inline int security_netlink_recv(struct sk_buff * skb)
static inline int security_netlink_recv(struct sk_buff * skb, int cap)
{
	return security_ops->netlink_recv(skb);
	return security_ops->netlink_recv(skb, cap);
}

/* prototypes */
@@ -2670,9 +2671,9 @@ static inline int security_netlink_send (struct sock *sk, struct sk_buff *skb)
	return cap_netlink_send (sk, skb);
}

static inline int security_netlink_recv (struct sk_buff *skb)
static inline int security_netlink_recv (struct sk_buff *skb, int cap)
{
	return cap_netlink_recv (skb);
	return cap_netlink_recv (skb, cap);
}

static inline struct dentry *securityfs_create_dir(const char *name,
+4 −4
Original line number Diff line number Diff line
@@ -445,7 +445,7 @@ void audit_send_reply(int pid, int seq, int type, int done, int multi,
 * Check for appropriate CAP_AUDIT_ capabilities on incoming audit
 * control messages.
 */
static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
{
	int err = 0;

@@ -459,13 +459,13 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
	case AUDIT_DEL:
	case AUDIT_DEL_RULE:
	case AUDIT_SIGNAL_INFO:
		if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
		if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
			err = -EPERM;
		break;
	case AUDIT_USER:
	case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
	case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:
		if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))
		if (security_netlink_recv(skb, CAP_AUDIT_WRITE))
			err = -EPERM;
		break;
	default:  /* bad msg */
@@ -488,7 +488,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
	char			*ctx;
	u32			len;

	err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
	err = audit_netlink_ok(skb, msg_type);
	if (err)
		return err;

+1 −1
Original line number Diff line number Diff line
@@ -663,7 +663,7 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
	sz_idx = type>>2;
	kind = type&3;

	if (kind != 2 && security_netlink_recv(skb)) {
	if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN)) {
		*errp = -EPERM;
		return -1;
	}
+1 −1
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
	if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
		return;

	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
	if (security_netlink_recv(skb, CAP_NET_ADMIN))
		RCV_SKB_FAIL(-EPERM);

	/* Eventually we might send routing messages too */
+1 −1
Original line number Diff line number Diff line
@@ -515,7 +515,7 @@ ipq_rcv_skb(struct sk_buff *skb)
	if (type <= IPQM_BASE)
		return;
		
	if (security_netlink_recv(skb))
	if (security_netlink_recv(skb, CAP_NET_ADMIN))
		RCV_SKB_FAIL(-EPERM);
	
	write_lock_bh(&queue_lock);
Loading