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. ====================
This commit is contained in:
Коммит
b747594829
|
@ -285,6 +285,8 @@ unsigned int *xt_alloc_entry_offsets(unsigned int size);
|
|||
bool xt_find_jump_offset(const unsigned int *offsets,
|
||||
unsigned int target, unsigned int size);
|
||||
|
||||
int xt_check_proc_name(const char *name, unsigned int size);
|
||||
|
||||
int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto,
|
||||
bool inv_proto);
|
||||
int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto,
|
||||
|
|
|
@ -177,6 +177,28 @@ static bool poolsize_invalid(const struct ebt_mac_wormhash *w)
|
|||
return w && w->poolsize >= (INT_MAX / sizeof(struct ebt_mac_wormhash_tuple));
|
||||
}
|
||||
|
||||
static bool wormhash_offset_invalid(int off, unsigned int len)
|
||||
{
|
||||
if (off == 0) /* not present */
|
||||
return false;
|
||||
|
||||
if (off < (int)sizeof(struct ebt_among_info) ||
|
||||
off % __alignof__(struct ebt_mac_wormhash))
|
||||
return true;
|
||||
|
||||
off += sizeof(struct ebt_mac_wormhash);
|
||||
|
||||
return off > len;
|
||||
}
|
||||
|
||||
static bool wormhash_sizes_valid(const struct ebt_mac_wormhash *wh, int a, int b)
|
||||
{
|
||||
if (a == 0)
|
||||
a = sizeof(struct ebt_among_info);
|
||||
|
||||
return ebt_mac_wormhash_size(wh) + a == b;
|
||||
}
|
||||
|
||||
static int ebt_among_mt_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct ebt_among_info *info = par->matchinfo;
|
||||
|
@ -189,6 +211,10 @@ static int ebt_among_mt_check(const struct xt_mtchk_param *par)
|
|||
if (expected_length > em->match_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (wormhash_offset_invalid(info->wh_dst_ofs, em->match_size) ||
|
||||
wormhash_offset_invalid(info->wh_src_ofs, em->match_size))
|
||||
return -EINVAL;
|
||||
|
||||
wh_dst = ebt_among_wh_dst(info);
|
||||
if (poolsize_invalid(wh_dst))
|
||||
return -EINVAL;
|
||||
|
@ -201,6 +227,14 @@ static int ebt_among_mt_check(const struct xt_mtchk_param *par)
|
|||
if (poolsize_invalid(wh_src))
|
||||
return -EINVAL;
|
||||
|
||||
if (info->wh_src_ofs < info->wh_dst_ofs) {
|
||||
if (!wormhash_sizes_valid(wh_src, info->wh_src_ofs, info->wh_dst_ofs))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (!wormhash_sizes_valid(wh_dst, info->wh_dst_ofs, info->wh_src_ofs))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
expected_length += ebt_mac_wormhash_size(wh_src);
|
||||
|
||||
if (em->match_size != EBT_ALIGN(expected_length)) {
|
||||
|
|
|
@ -2119,8 +2119,12 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
|
|||
* offsets are relative to beginning of struct ebt_entry (i.e., 0).
|
||||
*/
|
||||
for (i = 0; i < 4 ; ++i) {
|
||||
if (offsets[i] >= *total)
|
||||
if (offsets[i] > *total)
|
||||
return -EINVAL;
|
||||
|
||||
if (i < 3 && offsets[i] == *total)
|
||||
return -EINVAL;
|
||||
|
||||
if (i == 0)
|
||||
continue;
|
||||
if (offsets[i-1] > offsets[i])
|
||||
|
|
|
@ -5423,6 +5423,7 @@ err:
|
|||
static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
|
||||
{
|
||||
cancel_delayed_work_sync(&flowtable->data.gc_work);
|
||||
kfree(flowtable->ops);
|
||||
kfree(flowtable->name);
|
||||
flowtable->data.type->free(&flowtable->data);
|
||||
rhashtable_destroy(&flowtable->data.rhashtable);
|
||||
|
|
|
@ -674,7 +674,7 @@ static const struct nft_set_ops *
|
|||
nft_hash_select_ops(const struct nft_ctx *ctx, const struct nft_set_desc *desc,
|
||||
u32 flags)
|
||||
{
|
||||
if (desc->size) {
|
||||
if (desc->size && !(flags & NFT_SET_TIMEOUT)) {
|
||||
switch (desc->klen) {
|
||||
case 4:
|
||||
return &nft_hash_fast_ops;
|
||||
|
|
|
@ -423,6 +423,36 @@ textify_hooks(char *buf, size_t size, unsigned int mask, uint8_t nfproto)
|
|||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* xt_check_proc_name - check that name is suitable for /proc file creation
|
||||
*
|
||||
* @name: file name candidate
|
||||
* @size: length of buffer
|
||||
*
|
||||
* some x_tables modules wish to create a file in /proc.
|
||||
* This function makes sure that the name is suitable for this
|
||||
* purpose, it checks that name is NUL terminated and isn't a 'special'
|
||||
* name, like "..".
|
||||
*
|
||||
* returns negative number on error or 0 if name is useable.
|
||||
*/
|
||||
int xt_check_proc_name(const char *name, unsigned int size)
|
||||
{
|
||||
if (name[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
if (strnlen(name, size) == size)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
if (strcmp(name, ".") == 0 ||
|
||||
strcmp(name, "..") == 0 ||
|
||||
strchr(name, '/'))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(xt_check_proc_name);
|
||||
|
||||
int xt_check_match(struct xt_mtchk_param *par,
|
||||
unsigned int size, u_int8_t proto, bool inv_proto)
|
||||
{
|
||||
|
|
|
@ -917,8 +917,9 @@ static int hashlimit_mt_check_v1(const struct xt_mtchk_param *par)
|
|||
struct hashlimit_cfg3 cfg = {};
|
||||
int ret;
|
||||
|
||||
if (info->name[sizeof(info->name) - 1] != '\0')
|
||||
return -EINVAL;
|
||||
ret = xt_check_proc_name(info->name, sizeof(info->name));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cfg_copy(&cfg, (void *)&info->cfg, 1);
|
||||
|
||||
|
@ -935,8 +936,9 @@ static int hashlimit_mt_check_v2(const struct xt_mtchk_param *par)
|
|||
struct hashlimit_cfg3 cfg = {};
|
||||
int ret;
|
||||
|
||||
if (info->name[sizeof(info->name) - 1] != '\0')
|
||||
return -EINVAL;
|
||||
ret = xt_check_proc_name(info->name, sizeof(info->name));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cfg_copy(&cfg, (void *)&info->cfg, 2);
|
||||
|
||||
|
@ -950,9 +952,11 @@ static int hashlimit_mt_check_v2(const struct xt_mtchk_param *par)
|
|||
static int hashlimit_mt_check(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct xt_hashlimit_mtinfo3 *info = par->matchinfo;
|
||||
int ret;
|
||||
|
||||
if (info->name[sizeof(info->name) - 1] != '\0')
|
||||
return -EINVAL;
|
||||
ret = xt_check_proc_name(info->name, sizeof(info->name));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return hashlimit_mt_check_common(par, &info->hinfo, &info->cfg,
|
||||
info->name, 3);
|
||||
|
|
|
@ -361,9 +361,9 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
|
|||
info->hit_count, XT_RECENT_MAX_NSTAMPS - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (info->name[0] == '\0' ||
|
||||
strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN)
|
||||
return -EINVAL;
|
||||
ret = xt_check_proc_name(info->name, sizeof(info->name));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ip_pkt_list_tot && info->hit_count < ip_pkt_list_tot)
|
||||
nstamp_mask = roundup_pow_of_two(ip_pkt_list_tot) - 1;
|
||||
|
|
Загрузка…
Ссылка в новой задаче