aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-03-11 21:53:14 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-11 21:55:28 -0400
commit33cf7c90fe2f97afb1cadaa0cfb782cb9d1b9ee2 (patch)
tree7a0c80d0b2bb618919d966ce5b827c7eb8f843f6 /net/core
parent654eff45166c7e89d18fc476325c975768b2e347 (diff)
net: add real socket cookies
A long standing problem in netlink socket dumps is the use of kernel socket addresses as cookies. 1) It is a security concern. 2) Sockets can be reused quite quickly, so there is no guarantee a cookie is used once and identify a flow. 3) request sock, establish sock, and timewait socks for a given flow have different cookies. Part of our effort to bring better TCP statistics requires to switch to a different allocator. In this patch, I chose to use a per network namespace 64bit generator, and to use it only in the case a socket needs to be dumped to netlink. (This might be refined later if needed) Note that I tried to carry cookies from request sock, to establish sock, then timewait sockets. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Eric Salo <salo@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/sock.c1
-rw-r--r--net/core/sock_diag.c37
2 files changed, 28 insertions, 10 deletions
diff --git a/net/core/sock.c b/net/core/sock.c
index 726e1f99aa8d..a9a9c2ff9260 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1538,6 +1538,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
1538 newsk->sk_err = 0; 1538 newsk->sk_err = 0;
1539 newsk->sk_priority = 0; 1539 newsk->sk_priority = 0;
1540 newsk->sk_incoming_cpu = raw_smp_processor_id(); 1540 newsk->sk_incoming_cpu = raw_smp_processor_id();
1541 atomic64_set(&newsk->sk_cookie, 0);
1541 /* 1542 /*
1542 * Before updating sk_refcnt, we must commit prior changes to memory 1543 * Before updating sk_refcnt, we must commit prior changes to memory
1543 * (Documentation/RCU/rculist_nulls.txt for details) 1544 * (Documentation/RCU/rculist_nulls.txt for details)
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index 96e70ee05a8d..74dddf84adcd 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -13,22 +13,39 @@ static const struct sock_diag_handler *sock_diag_handlers[AF_MAX];
13static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh); 13static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh);
14static DEFINE_MUTEX(sock_diag_table_mutex); 14static DEFINE_MUTEX(sock_diag_table_mutex);
15 15
16int sock_diag_check_cookie(void *sk, const __u32 *cookie) 16static u64 sock_gen_cookie(struct sock *sk)
17{ 17{
18 if ((cookie[0] != INET_DIAG_NOCOOKIE || 18 while (1) {
19 cookie[1] != INET_DIAG_NOCOOKIE) && 19 u64 res = atomic64_read(&sk->sk_cookie);
20 ((u32)(unsigned long)sk != cookie[0] || 20
21 (u32)((((unsigned long)sk) >> 31) >> 1) != cookie[1])) 21 if (res)
22 return -ESTALE; 22 return res;
23 else 23 res = atomic64_inc_return(&sock_net(sk)->cookie_gen);
24 atomic64_cmpxchg(&sk->sk_cookie, 0, res);
25 }
26}
27
28int sock_diag_check_cookie(struct sock *sk, const __u32 *cookie)
29{
30 u64 res;
31
32 if (cookie[0] == INET_DIAG_NOCOOKIE && cookie[1] == INET_DIAG_NOCOOKIE)
24 return 0; 33 return 0;
34
35 res = sock_gen_cookie(sk);
36 if ((u32)res != cookie[0] || (u32)(res >> 32) != cookie[1])
37 return -ESTALE;
38
39 return 0;
25} 40}
26EXPORT_SYMBOL_GPL(sock_diag_check_cookie); 41EXPORT_SYMBOL_GPL(sock_diag_check_cookie);
27 42
28void sock_diag_save_cookie(void *sk, __u32 *cookie) 43void sock_diag_save_cookie(struct sock *sk, __u32 *cookie)
29{ 44{
30 cookie[0] = (u32)(unsigned long)sk; 45 u64 res = sock_gen_cookie(sk);
31 cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1); 46
47 cookie[0] = (u32)res;
48 cookie[1] = (u32)(res >> 32);
32} 49}
33EXPORT_SYMBOL_GPL(sock_diag_save_cookie); 50EXPORT_SYMBOL_GPL(sock_diag_save_cookie);
34 51