| From 11ff7288beb2b7da889a014aff0a7b80bf8efcf3 Mon Sep 17 00:00:00 2001 |
| From: Florian Westphal <fw@strlen.de> |
| Date: Wed, 6 Jun 2018 12:14:56 +0200 |
| Subject: netfilter: ebtables: reject non-bridge targets |
| |
| From: Florian Westphal <fw@strlen.de> |
| |
| commit 11ff7288beb2b7da889a014aff0a7b80bf8efcf3 upstream. |
| |
| the ebtables evaluation loop expects targets to return |
| positive values (jumps), or negative values (absolute verdicts). |
| |
| This is completely different from what xtables does. |
| In xtables, targets are expected to return the standard netfilter |
| verdicts, i.e. NF_DROP, NF_ACCEPT, etc. |
| |
| ebtables will consider these as jumps. |
| |
| Therefore reject any target found due to unspec fallback. |
| v2: also reject watchers. ebtables ignores their return value, so |
| a target that assumes skb ownership (and returns NF_STOLEN) causes |
| use-after-free. |
| |
| The only watchers in the 'ebtables' front-end are log and nflog; |
| both have AF_BRIDGE specific wrappers on kernel side. |
| |
| Reported-by: syzbot+2b43f681169a2a0d306a@syzkaller.appspotmail.com |
| Signed-off-by: Florian Westphal <fw@strlen.de> |
| Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/bridge/netfilter/ebtables.c | 13 +++++++++++++ |
| 1 file changed, 13 insertions(+) |
| |
| --- a/net/bridge/netfilter/ebtables.c |
| +++ b/net/bridge/netfilter/ebtables.c |
| @@ -404,6 +404,12 @@ ebt_check_watcher(struct ebt_entry_watch |
| watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0); |
| if (IS_ERR(watcher)) |
| return PTR_ERR(watcher); |
| + |
| + if (watcher->family != NFPROTO_BRIDGE) { |
| + module_put(watcher->me); |
| + return -ENOENT; |
| + } |
| + |
| w->u.watcher = watcher; |
| |
| par->target = watcher; |
| @@ -724,6 +730,13 @@ ebt_check_entry(struct ebt_entry *e, str |
| goto cleanup_watchers; |
| } |
| |
| + /* Reject UNSPEC, xtables verdicts/return values are incompatible */ |
| + if (target->family != NFPROTO_BRIDGE) { |
| + module_put(target->me); |
| + ret = -ENOENT; |
| + goto cleanup_watchers; |
| + } |
| + |
| t->u.target = target; |
| if (t->u.target == &ebt_standard_target) { |
| if (gap < sizeof(struct ebt_standard_target)) { |