diff options
| author | Eric Dumazet <edumazet@google.com> | 2015-03-13 12:49:59 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-03-13 15:54:27 -0400 |
| commit | c8e2c80d7ec00d020320f905822bf49c5ad85250 (patch) | |
| tree | fba6ff42961ccce00d9d070ac44c2d26e48258ad | |
| parent | a2fe37b69d4fe369c284d50927193fed81c238a0 (diff) | |
inet_diag: fix possible overflow in inet_diag_dump_one_icsk()
inet_diag_dump_one_icsk() allocates too small skb.
Add inet_sk_attr_size() helper right before inet_sk_diag_fill()
so that it can be updated if/when new attributes are added.
iproute2/ss currently does not use this dump_one() interface,
this might explain nobody noticed this problem yet.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/ipv4/inet_diag.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 81751f12645f..592aff37366b 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
| @@ -71,6 +71,20 @@ static inline void inet_diag_unlock_handler( | |||
| 71 | mutex_unlock(&inet_diag_table_mutex); | 71 | mutex_unlock(&inet_diag_table_mutex); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static size_t inet_sk_attr_size(void) | ||
| 75 | { | ||
| 76 | return nla_total_size(sizeof(struct tcp_info)) | ||
| 77 | + nla_total_size(1) /* INET_DIAG_SHUTDOWN */ | ||
| 78 | + nla_total_size(1) /* INET_DIAG_TOS */ | ||
| 79 | + nla_total_size(1) /* INET_DIAG_TCLASS */ | ||
| 80 | + nla_total_size(sizeof(struct inet_diag_meminfo)) | ||
| 81 | + nla_total_size(sizeof(struct inet_diag_msg)) | ||
| 82 | + nla_total_size(SK_MEMINFO_VARS * sizeof(u32)) | ||
| 83 | + nla_total_size(TCP_CA_NAME_MAX) | ||
| 84 | + nla_total_size(sizeof(struct tcpvegas_info)) | ||
| 85 | + 64; | ||
| 86 | } | ||
| 87 | |||
| 74 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | 88 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, |
| 75 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 89 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
| 76 | struct user_namespace *user_ns, | 90 | struct user_namespace *user_ns, |
| @@ -326,9 +340,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s | |||
| 326 | if (err) | 340 | if (err) |
| 327 | goto out; | 341 | goto out; |
| 328 | 342 | ||
| 329 | rep = nlmsg_new(sizeof(struct inet_diag_msg) + | 343 | rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL); |
| 330 | sizeof(struct inet_diag_meminfo) + | ||
| 331 | sizeof(struct tcp_info) + 64, GFP_KERNEL); | ||
| 332 | if (!rep) { | 344 | if (!rep) { |
| 333 | err = -ENOMEM; | 345 | err = -ENOMEM; |
| 334 | goto out; | 346 | goto out; |
