Skip to content

Commit 3e67f10

Browse files
edumazetdavem330
authored andcommitted
inet: frags: break the 2GB limit for frags storage
Some users are willing to provision huge amounts of memory to be able to perform reassembly reasonnably well under pressure. Current memory tracking is using one atomic_t and integers. Switch to atomic_long_t so that 64bit arches can use more than 2GB, without any cost for 32bit arches. Note that this patch avoids an overflow error, if high_thresh was set to ~2GB, since this test in inet_frag_alloc() was never true : if (... || frag_mem_limit(nf) > nf->high_thresh) Tested: $ echo 16000000000 >/proc/sys/net/ipv4/ipfrag_high_thresh <frag DDOS> $ grep FRAG /proc/net/sockstat FRAG: inuse 14705885 memory 16000002880 $ nstat -n ; sleep 1 ; nstat | grep Reas IpReasmReqds 3317150 0.0 IpReasmFails 3317112 0.0 Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2d44ed2 commit 3e67f10

File tree

8 files changed

+32
-32
lines changed

8 files changed

+32
-32
lines changed

Documentation/networking/ip-sysctl.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,10 @@ min_adv_mss - INTEGER
133133

134134
IP Fragmentation:
135135

136-
ipfrag_high_thresh - INTEGER
136+
ipfrag_high_thresh - LONG INTEGER
137137
Maximum memory used to reassemble IP fragments.
138138

139-
ipfrag_low_thresh - INTEGER
139+
ipfrag_low_thresh - LONG INTEGER
140140
(Obsolete since linux-4.17)
141141
Maximum memory used to reassemble IP fragments before the kernel
142142
begins to remove incomplete fragment queues to free up resources.

include/net/inet_frag.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ struct netns_frags {
88
struct rhashtable rhashtable ____cacheline_aligned_in_smp;
99

1010
/* Keep atomic mem on separate cachelines in structs that include it */
11-
atomic_t mem ____cacheline_aligned_in_smp;
11+
atomic_long_t mem ____cacheline_aligned_in_smp;
1212
/* sysctls */
13+
long high_thresh;
14+
long low_thresh;
1315
int timeout;
14-
int high_thresh;
15-
int low_thresh;
1616
int max_dist;
1717
struct inet_frags *f;
1818
};
@@ -102,7 +102,7 @@ void inet_frags_fini(struct inet_frags *);
102102

103103
static inline int inet_frags_init_net(struct netns_frags *nf)
104104
{
105-
atomic_set(&nf->mem, 0);
105+
atomic_long_set(&nf->mem, 0);
106106
return rhashtable_init(&nf->rhashtable, &nf->f->rhash_params);
107107
}
108108
void inet_frags_exit_net(struct netns_frags *nf);
@@ -119,19 +119,19 @@ static inline void inet_frag_put(struct inet_frag_queue *q)
119119

120120
/* Memory Tracking Functions. */
121121

122-
static inline int frag_mem_limit(struct netns_frags *nf)
122+
static inline long frag_mem_limit(const struct netns_frags *nf)
123123
{
124-
return atomic_read(&nf->mem);
124+
return atomic_long_read(&nf->mem);
125125
}
126126

127-
static inline void sub_frag_mem_limit(struct netns_frags *nf, int i)
127+
static inline void sub_frag_mem_limit(struct netns_frags *nf, long val)
128128
{
129-
atomic_sub(i, &nf->mem);
129+
atomic_long_sub(val, &nf->mem);
130130
}
131131

132-
static inline void add_frag_mem_limit(struct netns_frags *nf, int i)
132+
static inline void add_frag_mem_limit(struct netns_frags *nf, long val)
133133
{
134-
atomic_add(i, &nf->mem);
134+
atomic_long_add(val, &nf->mem);
135135
}
136136

137137
/* RFC 3168 support :

net/ieee802154/6lowpan/reassembly.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -411,23 +411,23 @@ int lowpan_frag_rcv(struct sk_buff *skb, u8 frag_type)
411411
}
412412

413413
#ifdef CONFIG_SYSCTL
414-
static int zero;
414+
static long zero;
415415

416416
static struct ctl_table lowpan_frags_ns_ctl_table[] = {
417417
{
418418
.procname = "6lowpanfrag_high_thresh",
419419
.data = &init_net.ieee802154_lowpan.frags.high_thresh,
420-
.maxlen = sizeof(int),
420+
.maxlen = sizeof(unsigned long),
421421
.mode = 0644,
422-
.proc_handler = proc_dointvec_minmax,
422+
.proc_handler = proc_doulongvec_minmax,
423423
.extra1 = &init_net.ieee802154_lowpan.frags.low_thresh
424424
},
425425
{
426426
.procname = "6lowpanfrag_low_thresh",
427427
.data = &init_net.ieee802154_lowpan.frags.low_thresh,
428-
.maxlen = sizeof(int),
428+
.maxlen = sizeof(unsigned long),
429429
.mode = 0644,
430-
.proc_handler = proc_dointvec_minmax,
430+
.proc_handler = proc_doulongvec_minmax,
431431
.extra1 = &zero,
432432
.extra2 = &init_net.ieee802154_lowpan.frags.high_thresh
433433
},

net/ipv4/ip_fragment.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -678,23 +678,23 @@ struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
678678
EXPORT_SYMBOL(ip_check_defrag);
679679

680680
#ifdef CONFIG_SYSCTL
681-
static int zero;
681+
static long zero;
682682

683683
static struct ctl_table ip4_frags_ns_ctl_table[] = {
684684
{
685685
.procname = "ipfrag_high_thresh",
686686
.data = &init_net.ipv4.frags.high_thresh,
687-
.maxlen = sizeof(int),
687+
.maxlen = sizeof(unsigned long),
688688
.mode = 0644,
689-
.proc_handler = proc_dointvec_minmax,
689+
.proc_handler = proc_doulongvec_minmax,
690690
.extra1 = &init_net.ipv4.frags.low_thresh
691691
},
692692
{
693693
.procname = "ipfrag_low_thresh",
694694
.data = &init_net.ipv4.frags.low_thresh,
695-
.maxlen = sizeof(int),
695+
.maxlen = sizeof(unsigned long),
696696
.mode = 0644,
697-
.proc_handler = proc_dointvec_minmax,
697+
.proc_handler = proc_doulongvec_minmax,
698698
.extra1 = &zero,
699699
.extra2 = &init_net.ipv4.frags.high_thresh
700700
},

net/ipv4/proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static int sockstat_seq_show(struct seq_file *seq, void *v)
7171
sock_prot_inuse_get(net, &udplite_prot));
7272
seq_printf(seq, "RAW: inuse %d\n",
7373
sock_prot_inuse_get(net, &raw_prot));
74-
seq_printf(seq, "FRAG: inuse %u memory %u\n",
74+
seq_printf(seq, "FRAG: inuse %u memory %lu\n",
7575
atomic_read(&net->ipv4.frags.rhashtable.nelems),
7676
frag_mem_limit(&net->ipv4.frags));
7777
return 0;

net/ipv6/netfilter/nf_conntrack_reasm.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct nf_ct_frag6_skb_cb
6363
static struct inet_frags nf_frags;
6464

6565
#ifdef CONFIG_SYSCTL
66-
static int zero;
66+
static long zero;
6767

6868
static struct ctl_table nf_ct_frag6_sysctl_table[] = {
6969
{
@@ -76,18 +76,18 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
7676
{
7777
.procname = "nf_conntrack_frag6_low_thresh",
7878
.data = &init_net.nf_frag.frags.low_thresh,
79-
.maxlen = sizeof(unsigned int),
79+
.maxlen = sizeof(unsigned long),
8080
.mode = 0644,
81-
.proc_handler = proc_dointvec_minmax,
81+
.proc_handler = proc_doulongvec_minmax,
8282
.extra1 = &zero,
8383
.extra2 = &init_net.nf_frag.frags.high_thresh
8484
},
8585
{
8686
.procname = "nf_conntrack_frag6_high_thresh",
8787
.data = &init_net.nf_frag.frags.high_thresh,
88-
.maxlen = sizeof(unsigned int),
88+
.maxlen = sizeof(unsigned long),
8989
.mode = 0644,
90-
.proc_handler = proc_dointvec_minmax,
90+
.proc_handler = proc_doulongvec_minmax,
9191
.extra1 = &init_net.nf_frag.frags.low_thresh
9292
},
9393
{ }

net/ipv6/proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v)
4747
sock_prot_inuse_get(net, &udplitev6_prot));
4848
seq_printf(seq, "RAW6: inuse %d\n",
4949
sock_prot_inuse_get(net, &rawv6_prot));
50-
seq_printf(seq, "FRAG6: inuse %u memory %u\n",
50+
seq_printf(seq, "FRAG6: inuse %u memory %lu\n",
5151
atomic_read(&net->ipv6.frags.rhashtable.nelems),
5252
frag_mem_limit(&net->ipv6.frags));
5353
return 0;

net/ipv6/reassembly.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -552,15 +552,15 @@ static struct ctl_table ip6_frags_ns_ctl_table[] = {
552552
{
553553
.procname = "ip6frag_high_thresh",
554554
.data = &init_net.ipv6.frags.high_thresh,
555-
.maxlen = sizeof(int),
555+
.maxlen = sizeof(unsigned long),
556556
.mode = 0644,
557-
.proc_handler = proc_dointvec_minmax,
557+
.proc_handler = proc_doulongvec_minmax,
558558
.extra1 = &init_net.ipv6.frags.low_thresh
559559
},
560560
{
561561
.procname = "ip6frag_low_thresh",
562562
.data = &init_net.ipv6.frags.low_thresh,
563-
.maxlen = sizeof(int),
563+
.maxlen = sizeof(unsigned long),
564564
.mode = 0644,
565565
.proc_handler = proc_dointvec_minmax,
566566
.extra1 = &zero,

0 commit comments

Comments
 (0)