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>hifive-unleashed-5.1
parent
1642182ea0
commit
ce46cc64d4
|
@ -62,6 +62,9 @@ static void __neigh_notify(struct neighbour *n, int type, int flags);
|
||||||
static void neigh_update_notify(struct neighbour *neigh);
|
static void neigh_update_notify(struct neighbour *neigh);
|
||||||
static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
|
static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
|
||||||
|
|
||||||
|
static int zero;
|
||||||
|
static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
|
||||||
|
|
||||||
static struct neigh_table *neigh_tables;
|
static struct neigh_table *neigh_tables;
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static const struct file_operations neigh_stat_seq_fops;
|
static 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)
|
||||||
nla_put_u32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes) ||
|
nla_put_u32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes) ||
|
||||||
/* approximative value for deprecated QUEUE_LEN (in packets) */
|
/* approximative value for deprecated QUEUE_LEN (in packets) */
|
||||||
nla_put_u32(skb, NDTPA_QUEUE_LEN,
|
nla_put_u32(skb, NDTPA_QUEUE_LEN,
|
||||||
DIV_ROUND_UP(parms->queue_len_bytes,
|
parms->queue_len_bytes / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
|
||||||
SKB_TRUESIZE(ETH_FRAME_LEN))) ||
|
|
||||||
nla_put_u32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen) ||
|
nla_put_u32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen) ||
|
||||||
nla_put_u32(skb, NDTPA_APP_PROBES, parms->app_probes) ||
|
nla_put_u32(skb, NDTPA_APP_PROBES, parms->app_probes) ||
|
||||||
nla_put_u32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes) ||
|
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,
|
||||||
int size, ret;
|
int size, ret;
|
||||||
ctl_table tmp = *ctl;
|
ctl_table tmp = *ctl;
|
||||||
|
|
||||||
|
tmp.extra1 = &zero;
|
||||||
|
tmp.extra2 = &unres_qlen_max;
|
||||||
tmp.data = &size;
|
tmp.data = &size;
|
||||||
size = DIV_ROUND_UP(*(int *)ctl->data, SKB_TRUESIZE(ETH_FRAME_LEN));
|
|
||||||
ret = proc_dointvec(&tmp, write, buffer, lenp, ppos);
|
size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
|
||||||
|
ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
|
||||||
|
|
||||||
if (write && !ret)
|
if (write && !ret)
|
||||||
*(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
|
*(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2865,7 +2871,8 @@ static struct neigh_sysctl_table {
|
||||||
.procname = "unres_qlen_bytes",
|
.procname = "unres_qlen_bytes",
|
||||||
.maxlen = sizeof(int),
|
.maxlen = sizeof(int),
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dointvec,
|
.extra1 = &zero,
|
||||||
|
.proc_handler = proc_dointvec_minmax,
|
||||||
},
|
},
|
||||||
[NEIGH_VAR_PROXY_QLEN] = {
|
[NEIGH_VAR_PROXY_QLEN] = {
|
||||||
.procname = "proxy_qlen",
|
.procname = "proxy_qlen",
|
||||||
|
|
Loading…
Reference in New Issue