Skip to content

Commit 259d4e4

Browse files
Eric Dumazetdavem330
authored andcommitted
[NETFILTER]: x_tables: struct xt_table_info diet
Instead of using a big array of NR_CPUS entries, we can compute the size needed at runtime, using nr_cpu_ids This should save some ram (especially on David's machines where NR_CPUS=4096 : 32 KB can be saved per table, and 64KB for dynamically allocated ones (because of slab/slub alignements) ) In particular, the 'bootstrap' tables are not any more static (in data section) but on stack as their size is now very small. This also should reduce the size used on stack in compat functions (get_info() declares an automatic variable, that could be bigger than kernel stack size for big NR_CPUS) Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d3c5ee6 commit 259d4e4

File tree

5 files changed

+18
-23
lines changed

5 files changed

+18
-23
lines changed

include/linux/netfilter/x_tables.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,12 @@ struct xt_table_info
269269
unsigned int underflow[NF_INET_NUMHOOKS];
270270

271271
/* ipt_entry tables: one per CPU */
272-
char *entries[NR_CPUS];
272+
/* Note : this field MUST be the last one, see XT_TABLE_INFO_SZ */
273+
char *entries[1];
273274
};
274275

276+
#define XT_TABLE_INFO_SZ (offsetof(struct xt_table_info, entries) \
277+
+ nr_cpu_ids * sizeof(char *))
275278
extern int xt_register_target(struct xt_target *target);
276279
extern void xt_unregister_target(struct xt_target *target);
277280
extern int xt_register_targets(struct xt_target *target, unsigned int n);

net/ipv4/netfilter/arp_tables.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -811,8 +811,7 @@ static int do_replace(void __user *user, unsigned int len)
811811
return -ENOPROTOOPT;
812812

813813
/* overflow check */
814-
if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
815-
SMP_CACHE_BYTES)
814+
if (tmp.size >= INT_MAX / num_possible_cpus())
816815
return -ENOMEM;
817816
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
818817
return -ENOMEM;
@@ -1090,7 +1089,7 @@ int arpt_register_table(struct arpt_table *table,
10901089
{
10911090
int ret;
10921091
struct xt_table_info *newinfo;
1093-
static struct xt_table_info bootstrap
1092+
struct xt_table_info bootstrap
10941093
= { 0, 0, 0, { 0 }, { 0 }, { } };
10951094
void *loc_cpu_entry;
10961095

net/ipv4/netfilter/ip_tables.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,7 +1090,8 @@ compat_calc_match(struct ipt_entry_match *m, int * size)
10901090
return 0;
10911091
}
10921092

1093-
static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
1093+
static int compat_calc_entry(struct ipt_entry *e,
1094+
const struct xt_table_info *info,
10941095
void *base, struct xt_table_info *newinfo)
10951096
{
10961097
struct ipt_entry_target *t;
@@ -1118,22 +1119,17 @@ static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
11181119
return 0;
11191120
}
11201121

1121-
static int compat_table_info(struct xt_table_info *info,
1122+
static int compat_table_info(const struct xt_table_info *info,
11221123
struct xt_table_info *newinfo)
11231124
{
11241125
void *loc_cpu_entry;
1125-
int i;
11261126

11271127
if (!newinfo || !info)
11281128
return -EINVAL;
11291129

1130-
memset(newinfo, 0, sizeof(struct xt_table_info));
1131-
newinfo->size = info->size;
1132-
newinfo->number = info->number;
1133-
for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1134-
newinfo->hook_entry[i] = info->hook_entry[i];
1135-
newinfo->underflow[i] = info->underflow[i];
1136-
}
1130+
/* we dont care about newinfo->entries[] */
1131+
memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1132+
newinfo->initial_entries = 0;
11371133
loc_cpu_entry = info->entries[raw_smp_processor_id()];
11381134
return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
11391135
compat_calc_entry, info, loc_cpu_entry, newinfo);
@@ -1327,8 +1323,7 @@ do_replace(void __user *user, unsigned int len)
13271323
return -ENOPROTOOPT;
13281324

13291325
/* overflow check */
1330-
if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1331-
SMP_CACHE_BYTES)
1326+
if (tmp.size >= INT_MAX / num_possible_cpus())
13321327
return -ENOMEM;
13331328
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
13341329
return -ENOMEM;
@@ -1868,8 +1863,7 @@ compat_do_replace(void __user *user, unsigned int len)
18681863
return -ENOPROTOOPT;
18691864

18701865
/* overflow check */
1871-
if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1872-
SMP_CACHE_BYTES)
1866+
if (tmp.size >= INT_MAX / num_possible_cpus())
18731867
return -ENOMEM;
18741868
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
18751869
return -ENOMEM;
@@ -2126,7 +2120,7 @@ int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
21262120
{
21272121
int ret;
21282122
struct xt_table_info *newinfo;
2129-
static struct xt_table_info bootstrap
2123+
struct xt_table_info bootstrap
21302124
= { 0, 0, 0, { 0 }, { 0 }, { } };
21312125
void *loc_cpu_entry;
21322126

net/ipv6/netfilter/ip6_tables.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,8 +1042,7 @@ do_replace(void __user *user, unsigned int len)
10421042
return -EFAULT;
10431043

10441044
/* overflow check */
1045-
if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1046-
SMP_CACHE_BYTES)
1045+
if (tmp.size >= INT_MAX / num_possible_cpus())
10471046
return -ENOMEM;
10481047
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
10491048
return -ENOMEM;
@@ -1339,7 +1338,7 @@ int ip6t_register_table(struct xt_table *table,
13391338
{
13401339
int ret;
13411340
struct xt_table_info *newinfo;
1342-
static struct xt_table_info bootstrap
1341+
struct xt_table_info bootstrap
13431342
= { 0, 0, 0, { 0 }, { 0 }, { } };
13441343
void *loc_cpu_entry;
13451344

net/netfilter/x_tables.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
499499
if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages)
500500
return NULL;
501501

502-
newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL);
502+
newinfo = kzalloc(XT_TABLE_INFO_SZ, GFP_KERNEL);
503503
if (!newinfo)
504504
return NULL;
505505

0 commit comments

Comments
 (0)