diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-11-14 12:14:33 -0500 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-11-17 06:01:13 -0500 |
commit | 97840cb67ff5ac8add836684f011fd838518d698 (patch) | |
tree | 237eb4fd6e6fda986127ce6b79b8ae5c916b9943 /net | |
parent | feb91a02ccb09661507f170b2a444aec94f307f9 (diff) |
netfilter: nfnetlink: fix insufficient validation in nfnetlink_bind
Make sure the netlink group exists, otherwise you can trigger an out
of bound array memory access from the netlink_bind() path. This splat
can only be triggered only by superuser.
[ 180.203600] UBSan: Undefined behaviour in ../net/netfilter/nfnetlink.c:467:28
[ 180.204249] index 9 is out of range for type 'int [9]'
[ 180.204697] CPU: 0 PID: 1771 Comm: trinity-main Not tainted 3.18.0-rc4-mm1+ #122
[ 180.205365] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org
+04/01/2014
[ 180.206498] 0000000000000018 0000000000000000 0000000000000009 ffff88007bdf7da8
[ 180.207220] ffffffff82b0ef5f 0000000000000092 ffffffff845ae2e0 ffff88007bdf7db8
[ 180.207887] ffffffff8199e489 ffff88007bdf7e18 ffffffff8199ea22 0000003900000000
[ 180.208639] Call Trace:
[ 180.208857] dump_stack (lib/dump_stack.c:52)
[ 180.209370] ubsan_epilogue (lib/ubsan.c:174)
[ 180.209849] __ubsan_handle_out_of_bounds (lib/ubsan.c:400)
[ 180.210512] nfnetlink_bind (net/netfilter/nfnetlink.c:467)
[ 180.210986] netlink_bind (net/netlink/af_netlink.c:1483)
[ 180.211495] SYSC_bind (net/socket.c:1541)
Moreover, define the missing nf_tables and nf_acct multicast groups too.
Reported-by: Andrey Ryabinin <a.ryabinin@samsung.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nfnetlink.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 6c5a915cfa75..13c2e17bbe27 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -47,6 +47,8 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = { | |||
47 | [NFNLGRP_CONNTRACK_EXP_NEW] = NFNL_SUBSYS_CTNETLINK_EXP, | 47 | [NFNLGRP_CONNTRACK_EXP_NEW] = NFNL_SUBSYS_CTNETLINK_EXP, |
48 | [NFNLGRP_CONNTRACK_EXP_UPDATE] = NFNL_SUBSYS_CTNETLINK_EXP, | 48 | [NFNLGRP_CONNTRACK_EXP_UPDATE] = NFNL_SUBSYS_CTNETLINK_EXP, |
49 | [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP, | 49 | [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP, |
50 | [NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES, | ||
51 | [NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT, | ||
50 | }; | 52 | }; |
51 | 53 | ||
52 | void nfnl_lock(__u8 subsys_id) | 54 | void nfnl_lock(__u8 subsys_id) |
@@ -464,7 +466,12 @@ static void nfnetlink_rcv(struct sk_buff *skb) | |||
464 | static int nfnetlink_bind(int group) | 466 | static int nfnetlink_bind(int group) |
465 | { | 467 | { |
466 | const struct nfnetlink_subsystem *ss; | 468 | const struct nfnetlink_subsystem *ss; |
467 | int type = nfnl_group2type[group]; | 469 | int type; |
470 | |||
471 | if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX) | ||
472 | return -EINVAL; | ||
473 | |||
474 | type = nfnl_group2type[group]; | ||
468 | 475 | ||
469 | rcu_read_lock(); | 476 | rcu_read_lock(); |
470 | ss = nfnetlink_get_subsys(type); | 477 | ss = nfnetlink_get_subsys(type); |
@@ -514,6 +521,9 @@ static int __init nfnetlink_init(void) | |||
514 | { | 521 | { |
515 | int i; | 522 | int i; |
516 | 523 | ||
524 | for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++) | ||
525 | BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE); | ||
526 | |||
517 | for (i=0; i<NFNL_SUBSYS_COUNT; i++) | 527 | for (i=0; i<NFNL_SUBSYS_COUNT; i++) |
518 | mutex_init(&table[i].mutex); | 528 | mutex_init(&table[i].mutex); |
519 | 529 | ||