diff options
author | Eric Dumazet <edumazet@google.com> | 2015-03-11 21:53:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-11 21:55:28 -0400 |
commit | 33cf7c90fe2f97afb1cadaa0cfb782cb9d1b9ee2 (patch) | |
tree | 7a0c80d0b2bb618919d966ce5b827c7eb8f843f6 /net/ipv4/inet_diag.c | |
parent | 654eff45166c7e89d18fc476325c975768b2e347 (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/ipv4/inet_diag.c')
-rw-r--r-- | net/ipv4/inet_diag.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index ac3bfb458afd..29317ff4a007 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -221,12 +221,13 @@ static int inet_csk_diag_fill(struct sock *sk, | |||
221 | user_ns, portid, seq, nlmsg_flags, unlh); | 221 | user_ns, portid, seq, nlmsg_flags, unlh); |
222 | } | 222 | } |
223 | 223 | ||
224 | static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, | 224 | static int inet_twsk_diag_fill(struct sock *sk, |
225 | struct sk_buff *skb, | 225 | struct sk_buff *skb, |
226 | const struct inet_diag_req_v2 *req, | 226 | const struct inet_diag_req_v2 *req, |
227 | u32 portid, u32 seq, u16 nlmsg_flags, | 227 | u32 portid, u32 seq, u16 nlmsg_flags, |
228 | const struct nlmsghdr *unlh) | 228 | const struct nlmsghdr *unlh) |
229 | { | 229 | { |
230 | struct inet_timewait_sock *tw = inet_twsk(sk); | ||
230 | struct inet_diag_msg *r; | 231 | struct inet_diag_msg *r; |
231 | struct nlmsghdr *nlh; | 232 | struct nlmsghdr *nlh; |
232 | s32 tmo; | 233 | s32 tmo; |
@@ -247,7 +248,7 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, | |||
247 | r->idiag_retrans = 0; | 248 | r->idiag_retrans = 0; |
248 | 249 | ||
249 | r->id.idiag_if = tw->tw_bound_dev_if; | 250 | r->id.idiag_if = tw->tw_bound_dev_if; |
250 | sock_diag_save_cookie(tw, r->id.idiag_cookie); | 251 | sock_diag_save_cookie(sk, r->id.idiag_cookie); |
251 | 252 | ||
252 | r->id.idiag_sport = tw->tw_sport; | 253 | r->id.idiag_sport = tw->tw_sport; |
253 | r->id.idiag_dport = tw->tw_dport; | 254 | r->id.idiag_dport = tw->tw_dport; |
@@ -283,7 +284,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, | |||
283 | const struct nlmsghdr *unlh) | 284 | const struct nlmsghdr *unlh) |
284 | { | 285 | { |
285 | if (sk->sk_state == TCP_TIME_WAIT) | 286 | if (sk->sk_state == TCP_TIME_WAIT) |
286 | return inet_twsk_diag_fill(inet_twsk(sk), skb, r, portid, seq, | 287 | return inet_twsk_diag_fill(sk, skb, r, portid, seq, |
287 | nlmsg_flags, unlh); | 288 | nlmsg_flags, unlh); |
288 | 289 | ||
289 | return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq, | 290 | return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq, |
@@ -675,7 +676,7 @@ static int inet_twsk_diag_dump(struct sock *sk, | |||
675 | if (!inet_diag_bc_sk(bc, sk)) | 676 | if (!inet_diag_bc_sk(bc, sk)) |
676 | return 0; | 677 | return 0; |
677 | 678 | ||
678 | return inet_twsk_diag_fill(inet_twsk(sk), skb, r, | 679 | return inet_twsk_diag_fill(sk, skb, r, |
679 | NETLINK_CB(cb->skb).portid, | 680 | NETLINK_CB(cb->skb).portid, |
680 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 681 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
681 | } | 682 | } |
@@ -734,7 +735,10 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | |||
734 | r->idiag_retrans = req->num_retrans; | 735 | r->idiag_retrans = req->num_retrans; |
735 | 736 | ||
736 | r->id.idiag_if = sk->sk_bound_dev_if; | 737 | r->id.idiag_if = sk->sk_bound_dev_if; |
737 | sock_diag_save_cookie(req, r->id.idiag_cookie); | 738 | |
739 | BUILD_BUG_ON(offsetof(struct inet_request_sock, ir_cookie) != | ||
740 | offsetof(struct sock, sk_cookie)); | ||
741 | sock_diag_save_cookie((struct sock *)ireq, r->id.idiag_cookie); | ||
738 | 742 | ||
739 | tmo = req->expires - jiffies; | 743 | tmo = req->expires - jiffies; |
740 | if (tmo < 0) | 744 | if (tmo < 0) |