Skip to content

Commit b747594

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for your net tree, they are: 1) Fixed hashtable representation doesn't support timeout flag, skip it otherwise rules to add elements from the packet fail bogusly fail with EOPNOTSUPP. 2) Fix bogus error with 32-bits ebtables userspace and 64-bits kernel, patch from Florian Westphal. 3) Sanitize proc names in several x_tables extensions, also from Florian. 4) Add sanitization to ebt_among wormhash logic, from Florian. 5) Missing release of hook array in flowtable. ====================
2 parents 4665c6b + c04a3f7 commit b747594

File tree

8 files changed

+86
-11
lines changed

8 files changed

+86
-11
lines changed

include/linux/netfilter/x_tables.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ unsigned int *xt_alloc_entry_offsets(unsigned int size);
285285
bool xt_find_jump_offset(const unsigned int *offsets,
286286
unsigned int target, unsigned int size);
287287

288+
int xt_check_proc_name(const char *name, unsigned int size);
289+
288290
int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto,
289291
bool inv_proto);
290292
int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto,

net/bridge/netfilter/ebt_among.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,28 @@ static bool poolsize_invalid(const struct ebt_mac_wormhash *w)
177177
return w && w->poolsize >= (INT_MAX / sizeof(struct ebt_mac_wormhash_tuple));
178178
}
179179

180+
static bool wormhash_offset_invalid(int off, unsigned int len)
181+
{
182+
if (off == 0) /* not present */
183+
return false;
184+
185+
if (off < (int)sizeof(struct ebt_among_info) ||
186+
off % __alignof__(struct ebt_mac_wormhash))
187+
return true;
188+
189+
off += sizeof(struct ebt_mac_wormhash);
190+
191+
return off > len;
192+
}
193+
194+
static bool wormhash_sizes_valid(const struct ebt_mac_wormhash *wh, int a, int b)
195+
{
196+
if (a == 0)
197+
a = sizeof(struct ebt_among_info);
198+
199+
return ebt_mac_wormhash_size(wh) + a == b;
200+
}
201+
180202
static int ebt_among_mt_check(const struct xt_mtchk_param *par)
181203
{
182204
const struct ebt_among_info *info = par->matchinfo;
@@ -189,6 +211,10 @@ static int ebt_among_mt_check(const struct xt_mtchk_param *par)
189211
if (expected_length > em->match_size)
190212
return -EINVAL;
191213

214+
if (wormhash_offset_invalid(info->wh_dst_ofs, em->match_size) ||
215+
wormhash_offset_invalid(info->wh_src_ofs, em->match_size))
216+
return -EINVAL;
217+
192218
wh_dst = ebt_among_wh_dst(info);
193219
if (poolsize_invalid(wh_dst))
194220
return -EINVAL;
@@ -201,6 +227,14 @@ static int ebt_among_mt_check(const struct xt_mtchk_param *par)
201227
if (poolsize_invalid(wh_src))
202228
return -EINVAL;
203229

230+
if (info->wh_src_ofs < info->wh_dst_ofs) {
231+
if (!wormhash_sizes_valid(wh_src, info->wh_src_ofs, info->wh_dst_ofs))
232+
return -EINVAL;
233+
} else {
234+
if (!wormhash_sizes_valid(wh_dst, info->wh_dst_ofs, info->wh_src_ofs))
235+
return -EINVAL;
236+
}
237+
204238
expected_length += ebt_mac_wormhash_size(wh_src);
205239

206240
if (em->match_size != EBT_ALIGN(expected_length)) {

net/bridge/netfilter/ebtables.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2119,8 +2119,12 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
21192119
* offsets are relative to beginning of struct ebt_entry (i.e., 0).
21202120
*/
21212121
for (i = 0; i < 4 ; ++i) {
2122-
if (offsets[i] >= *total)
2122+
if (offsets[i] > *total)
21232123
return -EINVAL;
2124+
2125+
if (i < 3 && offsets[i] == *total)
2126+
return -EINVAL;
2127+
21242128
if (i == 0)
21252129
continue;
21262130
if (offsets[i-1] > offsets[i])

net/netfilter/nf_tables_api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5423,6 +5423,7 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
54235423
static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
54245424
{
54255425
cancel_delayed_work_sync(&flowtable->data.gc_work);
5426+
kfree(flowtable->ops);
54265427
kfree(flowtable->name);
54275428
flowtable->data.type->free(&flowtable->data);
54285429
rhashtable_destroy(&flowtable->data.rhashtable);

net/netfilter/nft_set_hash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ static const struct nft_set_ops *
674674
nft_hash_select_ops(const struct nft_ctx *ctx, const struct nft_set_desc *desc,
675675
u32 flags)
676676
{
677-
if (desc->size) {
677+
if (desc->size && !(flags & NFT_SET_TIMEOUT)) {
678678
switch (desc->klen) {
679679
case 4:
680680
return &nft_hash_fast_ops;

net/netfilter/x_tables.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,36 @@ textify_hooks(char *buf, size_t size, unsigned int mask, uint8_t nfproto)
423423
return buf;
424424
}
425425

426+
/**
427+
* xt_check_proc_name - check that name is suitable for /proc file creation
428+
*
429+
* @name: file name candidate
430+
* @size: length of buffer
431+
*
432+
* some x_tables modules wish to create a file in /proc.
433+
* This function makes sure that the name is suitable for this
434+
* purpose, it checks that name is NUL terminated and isn't a 'special'
435+
* name, like "..".
436+
*
437+
* returns negative number on error or 0 if name is useable.
438+
*/
439+
int xt_check_proc_name(const char *name, unsigned int size)
440+
{
441+
if (name[0] == '\0')
442+
return -EINVAL;
443+
444+
if (strnlen(name, size) == size)
445+
return -ENAMETOOLONG;
446+
447+
if (strcmp(name, ".") == 0 ||
448+
strcmp(name, "..") == 0 ||
449+
strchr(name, '/'))
450+
return -EINVAL;
451+
452+
return 0;
453+
}
454+
EXPORT_SYMBOL(xt_check_proc_name);
455+
426456
int xt_check_match(struct xt_mtchk_param *par,
427457
unsigned int size, u_int8_t proto, bool inv_proto)
428458
{

net/netfilter/xt_hashlimit.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -917,8 +917,9 @@ static int hashlimit_mt_check_v1(const struct xt_mtchk_param *par)
917917
struct hashlimit_cfg3 cfg = {};
918918
int ret;
919919

920-
if (info->name[sizeof(info->name) - 1] != '\0')
921-
return -EINVAL;
920+
ret = xt_check_proc_name(info->name, sizeof(info->name));
921+
if (ret)
922+
return ret;
922923

923924
ret = cfg_copy(&cfg, (void *)&info->cfg, 1);
924925

@@ -935,8 +936,9 @@ static int hashlimit_mt_check_v2(const struct xt_mtchk_param *par)
935936
struct hashlimit_cfg3 cfg = {};
936937
int ret;
937938

938-
if (info->name[sizeof(info->name) - 1] != '\0')
939-
return -EINVAL;
939+
ret = xt_check_proc_name(info->name, sizeof(info->name));
940+
if (ret)
941+
return ret;
940942

941943
ret = cfg_copy(&cfg, (void *)&info->cfg, 2);
942944

@@ -950,9 +952,11 @@ static int hashlimit_mt_check_v2(const struct xt_mtchk_param *par)
950952
static int hashlimit_mt_check(const struct xt_mtchk_param *par)
951953
{
952954
struct xt_hashlimit_mtinfo3 *info = par->matchinfo;
955+
int ret;
953956

954-
if (info->name[sizeof(info->name) - 1] != '\0')
955-
return -EINVAL;
957+
ret = xt_check_proc_name(info->name, sizeof(info->name));
958+
if (ret)
959+
return ret;
956960

957961
return hashlimit_mt_check_common(par, &info->hinfo, &info->cfg,
958962
info->name, 3);

net/netfilter/xt_recent.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,9 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
361361
info->hit_count, XT_RECENT_MAX_NSTAMPS - 1);
362362
return -EINVAL;
363363
}
364-
if (info->name[0] == '\0' ||
365-
strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN)
366-
return -EINVAL;
364+
ret = xt_check_proc_name(info->name, sizeof(info->name));
365+
if (ret)
366+
return ret;
367367

368368
if (ip_pkt_list_tot && info->hit_count < ip_pkt_list_tot)
369369
nstamp_mask = roundup_pow_of_two(ip_pkt_list_tot) - 1;

0 commit comments

Comments
 (0)