Skip to content

Commit

Permalink
selinux: add a skb_owned_by() hook
Browse files Browse the repository at this point in the history
Commit 90ba9b1 (tcp: tcp_make_synack() can use alloc_skb())
broke certain SELinux/NetLabel configurations by no longer correctly
assigning the sock to the outgoing SYNACK packet.

Cost of atomic operations on the LISTEN socket is quite big,
and we would like it to happen only if really needed.

This patch introduces a new security_ops->skb_owned_by() method,
that is a void operation unless selinux is active.

Reported-by: Miroslav Vadkerti <[email protected]>
Diagnosed-by: Paul Moore <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: [email protected]
Acked-by: James Morris <[email protected]>
Tested-by: Paul Moore <[email protected]>
Acked-by: Paul Moore <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Eric Dumazet authored and davem330 committed Apr 9, 2013
1 parent c802d75 commit ca10b9e
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 0 deletions.
8 changes: 8 additions & 0 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,7 @@ struct security_operations {
int (*tun_dev_attach_queue) (void *security);
int (*tun_dev_attach) (struct sock *sk, void *security);
int (*tun_dev_open) (void *security);
void (*skb_owned_by) (struct sk_buff *skb, struct sock *sk);
#endif /* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down Expand Up @@ -2588,6 +2589,8 @@ int security_tun_dev_attach_queue(void *security);
int security_tun_dev_attach(struct sock *sk, void *security);
int security_tun_dev_open(void *security);

void security_skb_owned_by(struct sk_buff *skb, struct sock *sk);

#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct sock *sock,
struct sock *other,
Expand Down Expand Up @@ -2779,6 +2782,11 @@ static inline int security_tun_dev_open(void *security)
{
return 0;
}

static inline void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
{
}

#endif /* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down
1 change: 1 addition & 0 deletions net/ipv4/tcp_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -2709,6 +2709,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
skb_reserve(skb, MAX_TCP_HEADER);

skb_dst_set(skb, dst);
security_skb_owned_by(skb, sk);

mss = dst_metric_advmss(dst);
if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss)
Expand Down
6 changes: 6 additions & 0 deletions security/capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,11 @@ static int cap_tun_dev_open(void *security)
{
return 0;
}

static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk)
{
}

#endif /* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down Expand Up @@ -1071,6 +1076,7 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null(ops, tun_dev_open);
set_to_cap_if_null(ops, tun_dev_attach_queue);
set_to_cap_if_null(ops, tun_dev_attach);
set_to_cap_if_null(ops, skb_owned_by);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
set_to_cap_if_null(ops, xfrm_policy_alloc_security);
Expand Down
5 changes: 5 additions & 0 deletions security/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,11 @@ int security_tun_dev_open(void *security)
}
EXPORT_SYMBOL(security_tun_dev_open);

void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
{
security_ops->skb_owned_by(skb, sk);
}

#endif /* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down
7 changes: 7 additions & 0 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include <linux/tty.h>
#include <net/icmp.h>
#include <net/ip.h> /* for local_port_range[] */
#include <net/sock.h>
#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
#include <net/net_namespace.h>
#include <net/netlabel.h>
Expand Down Expand Up @@ -4363,6 +4364,11 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
}

static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
{
skb_set_owner_w(skb, sk);
}

static int selinux_secmark_relabel_packet(u32 sid)
{
const struct task_security_struct *__tsec;
Expand Down Expand Up @@ -5664,6 +5670,7 @@ static struct security_operations selinux_ops = {
.tun_dev_attach_queue = selinux_tun_dev_attach_queue,
.tun_dev_attach = selinux_tun_dev_attach,
.tun_dev_open = selinux_tun_dev_open,
.skb_owned_by = selinux_skb_owned_by,

#ifdef CONFIG_SECURITY_NETWORK_XFRM
.xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
Expand Down

0 comments on commit ca10b9e

Please sign in to comment.