aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorShan Wei <davidshan@tencent.com>2012-12-04 13:49:15 -0500
committerDavid S. Miller <davem@davemloft.net>2012-12-05 16:01:28 -0500
commitce46cc64d47a8afaf13c300b09a7f9c29f4979b6 (patch)
tree2fcaf39d15b41ee1f92f14eb8035f82eb80a5364 /net/core
parent1642182ea0eedecc5d6f330c43cef8639327f0e5 (diff)
net: neighbour: prohibit negative value for unres_qlen_bytes parameter
unres_qlen_bytes and unres_qlen are int type. But multiple relation(unres_qlen_bytes = unres_qlen * SKB_TRUESIZE(ETH_FRAME_LEN)) will cause type overflow when seting unres_qlen. e.g. $ echo 1027506 > /proc/sys/net/ipv4/neigh/eth1/unres_qlen $ cat /proc/sys/net/ipv4/neigh/eth1/unres_qlen 1182657265 $ cat /proc/sys/net/ipv4/neigh/eth1/unres_qlen_bytes -2147479756 The gutted value is not that we setting。 But user/administrator don't know this is caused by int type overflow. what's more, it is meaningless and even dangerous that unres_qlen_bytes is set with negative number. Because, for unresolved neighbour address, kernel will cache packets without limit in __neigh_event_send()(e.g. (u32)-1 = 2GB). Signed-off-by: Shan Wei <davidshan@tencent.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/neighbour.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index f1c0c2e9cad5..36fc692e2bde 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -62,6 +62,9 @@ static void __neigh_notify(struct neighbour *n, int type, int flags);
62static void neigh_update_notify(struct neighbour *neigh); 62static void neigh_update_notify(struct neighbour *neigh);
63static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev); 63static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
64 64
65static int zero;
66static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
67
65static struct neigh_table *neigh_tables; 68static struct neigh_table *neigh_tables;
66#ifdef CONFIG_PROC_FS 69#ifdef CONFIG_PROC_FS
67static const struct file_operations neigh_stat_seq_fops; 70static const struct file_operations neigh_stat_seq_fops;
@@ -1787,8 +1790,7 @@ static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1787 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes) || 1790 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes) ||
1788 /* approximative value for deprecated QUEUE_LEN (in packets) */ 1791 /* approximative value for deprecated QUEUE_LEN (in packets) */
1789 nla_put_u32(skb, NDTPA_QUEUE_LEN, 1792 nla_put_u32(skb, NDTPA_QUEUE_LEN,
1790 DIV_ROUND_UP(parms->queue_len_bytes, 1793 parms->queue_len_bytes / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1791 SKB_TRUESIZE(ETH_FRAME_LEN))) ||
1792 nla_put_u32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen) || 1794 nla_put_u32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen) ||
1793 nla_put_u32(skb, NDTPA_APP_PROBES, parms->app_probes) || 1795 nla_put_u32(skb, NDTPA_APP_PROBES, parms->app_probes) ||
1794 nla_put_u32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes) || 1796 nla_put_u32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes) ||
@@ -2777,9 +2779,13 @@ static int proc_unres_qlen(ctl_table *ctl, int write, void __user *buffer,
2777 int size, ret; 2779 int size, ret;
2778 ctl_table tmp = *ctl; 2780 ctl_table tmp = *ctl;
2779 2781
2782 tmp.extra1 = &zero;
2783 tmp.extra2 = &unres_qlen_max;
2780 tmp.data = &size; 2784 tmp.data = &size;
2781 size = DIV_ROUND_UP(*(int *)ctl->data, SKB_TRUESIZE(ETH_FRAME_LEN)); 2785
2782 ret = proc_dointvec(&tmp, write, buffer, lenp, ppos); 2786 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2787 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2788
2783 if (write && !ret) 2789 if (write && !ret)
2784 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN); 2790 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2785 return ret; 2791 return ret;
@@ -2865,7 +2871,8 @@ static struct neigh_sysctl_table {
2865 .procname = "unres_qlen_bytes", 2871 .procname = "unres_qlen_bytes",
2866 .maxlen = sizeof(int), 2872 .maxlen = sizeof(int),
2867 .mode = 0644, 2873 .mode = 0644,
2868 .proc_handler = proc_dointvec, 2874 .extra1 = &zero,
2875 .proc_handler = proc_dointvec_minmax,
2869 }, 2876 },
2870 [NEIGH_VAR_PROXY_QLEN] = { 2877 [NEIGH_VAR_PROXY_QLEN] = {
2871 .procname = "proxy_qlen", 2878 .procname = "proxy_qlen",