4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso pablo@netfilter.org
commit b301f2538759933cf9ff1f7c4f968da72e3f0757 upstream.
Make sure the table names via getsockopt GET_ENTRIES is nul-terminated in ebtables and all the x_tables variants and their respective compat code. Uncovered by KASAN.
Reported-by: Baozeng Ding sploving1@gmail.com Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org Cc: Zubin Mithra zsm@chromium.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- net/bridge/netfilter/ebtables.c | 4 ++++ net/ipv4/netfilter/arp_tables.c | 2 ++ net/ipv4/netfilter/ip_tables.c | 2 ++ net/ipv6/netfilter/ip6_tables.c | 2 ++ 4 files changed, 10 insertions(+)
--- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1528,6 +1528,8 @@ static int do_ebt_get_ctl(struct sock *s if (copy_from_user(&tmp, user, sizeof(tmp))) return -EFAULT;
+ tmp.name[sizeof(tmp.name) - 1] = '\0'; + t = find_table_lock(net, tmp.name, &ret, &ebt_mutex); if (!t) return ret; @@ -2368,6 +2370,8 @@ static int compat_do_ebt_get_ctl(struct if (copy_from_user(&tmp, user, sizeof(tmp))) return -EFAULT;
+ tmp.name[sizeof(tmp.name) - 1] = '\0'; + t = find_table_lock(net, tmp.name, &ret, &ebt_mutex); if (!t) return ret; --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -983,6 +983,7 @@ static int get_entries(struct net *net, sizeof(struct arpt_get_entries) + get.size); return -EINVAL; } + get.name[sizeof(get.name) - 1] = '\0';
t = xt_find_table_lock(net, NFPROTO_ARP, get.name); if (!IS_ERR_OR_NULL(t)) { @@ -1557,6 +1558,7 @@ static int compat_get_entries(struct net *len, sizeof(get) + get.size); return -EINVAL; } + get.name[sizeof(get.name) - 1] = '\0';
xt_compat_lock(NFPROTO_ARP); t = xt_find_table_lock(net, NFPROTO_ARP, get.name); --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1171,6 +1171,7 @@ get_entries(struct net *net, struct ipt_ *len, sizeof(get) + get.size); return -EINVAL; } + get.name[sizeof(get.name) - 1] = '\0';
t = xt_find_table_lock(net, AF_INET, get.name); if (!IS_ERR_OR_NULL(t)) { @@ -1799,6 +1800,7 @@ compat_get_entries(struct net *net, stru *len, sizeof(get) + get.size); return -EINVAL; } + get.name[sizeof(get.name) - 1] = '\0';
xt_compat_lock(AF_INET); t = xt_find_table_lock(net, AF_INET, get.name); --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1182,6 +1182,7 @@ get_entries(struct net *net, struct ip6t *len, sizeof(get) + get.size); return -EINVAL; } + get.name[sizeof(get.name) - 1] = '\0';
t = xt_find_table_lock(net, AF_INET6, get.name); if (!IS_ERR_OR_NULL(t)) { @@ -1800,6 +1801,7 @@ compat_get_entries(struct net *net, stru *len, sizeof(get) + get.size); return -EINVAL; } + get.name[sizeof(get.name) - 1] = '\0';
xt_compat_lock(AF_INET6); t = xt_find_table_lock(net, AF_INET6, get.name);