[pkg-netfilter-team] Bug#968457: Bug#968457: iptables: segfault with specific command when run as non-root
Jeremy Sowden
jeremy at azazel.net
Sun Aug 16 16:02:12 BST 2020
On 2020-08-16, at 14:48:12 +0200, Bernhard Übelacker wrote:
> Program received signal SIGSEGV, Segmentation fault.
> nftnl_rule_list_add (r=r at entry=0x5555555f5900, list=0x0) at rule.c:782
> 782 list_add(&r->head, &list->list);
> (gdb) bt
> #0 nftnl_rule_list_add (r=r at entry=0x5555555f5900, list=0x0) at rule.c:782
> #1 0x0000555555567eac in nft_rule_insert (h=h at entry=0x7fffffffe480, chain=chain at entry=0x7fffffffe848 "OUTPUT", table=table at entry=0x55555557b126 "filter", data=data at entry=0x7fffffffe300, rulenum=rulenum at entry=0, verbose=verbose at entry=false) at nft.c:2146
> #2 0x0000555555562629 in add_entry (chain=0x7fffffffe848 "OUTPUT", table=0x55555557b126 "filter", cs=cs at entry=0x7fffffffe300, rulenum=0, family=2, s=..., d=..., verbose=false, h=0x7fffffffe480, append=false) at xtables.c:412
> #3 0x0000555555564270 in do_commandx (h=h at entry=0x7fffffffe480, argc=argc at entry=3, argv=argv at entry=0x7fffffffe608, table=table at entry=0x7fffffffe478, restore=restore at entry=false) at xtables.c:1122
> #4 0x0000555555562350 in xtables_main (family=family at entry=2, progname=progname at entry=0x55555557a011 "iptables", argc=3, argv=0x7fffffffe608) at xtables-standalone.c:72
> #5 0x000055555556248a in xtables_ip4_main (argc=<optimized out>, argv=<optimized out>) at xtables-standalone.c:96
> #6 0x00007ffff763809b in __libc_start_main (main=0x55555555cfb0 <main>, argc=3, argv=0x7fffffffe608, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe5f8) at ../csu/libc-start.c:308
> #7 0x000055555555cfea in _start ()
Here is the relevant part of nft_rule_insert (iptables/nft.c,
ll. 2131ff.):
if (rulenum > 0) {
list = nft_rule_list_get(h);
if (list == NULL)
goto err;
r = nft_rule_find(h, list, chain, table, data, rulenum);
if (r == NULL) {
/* special case: iptables allows to insert into
* rule_count + 1 position.
*/
r = nft_rule_find(h, list, chain, table, data,
rulenum - 1);
if (r != NULL)
return nft_rule_append(h, chain, table, data,
0, verbose);
errno = ENOENT;
goto err;
}
handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE);
DEBUGP("adding after rule handle %"PRIu64"\n", handle);
} else {
nft_rule_list_get(h);
}
new_rule = nft_rule_add(h, chain, table, data, handle, verbose);
if (!new_rule)
goto err;
if (handle)
nftnl_rule_list_insert_at(new_rule, r);
else
nftnl_rule_list_add(new_rule, h->rule_cache);
If rulenum == 0, the code assumes that nft_rule_list_get, which sets
h->rule_cache, does not fail.
Here is the relevant part of nft_rule_list_get (iptables/nft.c,
ll. 1407ff.):
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nftnl_rule_list_cb, list);
if (ret < 0) {
if (errno == EINTR) {
assert(nft_restart(h) >= 0);
nftnl_rule_list_free(list);
goto retry;
}
nftnl_rule_list_free(list);
return NULL;
}
Because we are running iptables as an unprivileged user, the kernel
returns EPERM in response to our NFT_MSG_GETRULE request.
We need to check the return value of nft_rule_list_get in both cases.
Patch attached.
J.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: iptables-nft.eperm_segv_fix.patch
Type: text/x-diff
Size: 724 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/pkg-netfilter-team/attachments/20200816/43b1e400/attachment.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 659 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/pkg-netfilter-team/attachments/20200816/43b1e400/attachment.sig>
More information about the pkg-netfilter-team
mailing list