| From 24c910207376ed21dd55d2a84971262347ee9ed6 Mon Sep 17 00:00:00 2001 |
| From: Kevin Cernekee <cernekee@chromium.org> |
| Date: Mon, 16 May 2016 22:28:46 -0700 |
| Subject: [PATCH] CHROMIUM: Introduce ANDROID_PARANOID_NETWORK as per-netns |
| setting |
| |
| ANDROID_PARANOID_NETWORK requires creators of AF_INET/AF_INET6 sockets |
| to be in the AID_INET group. In our system it is problematic to enable |
| this globally. Change the logic so that the changes apply on a per-netns |
| basis. Also, interpret AID_* as gids instead of kgids. |
| |
| BUG=b:27932716 |
| TEST=`echo 1 > /proc/sys/net/core/android_paranoid` |
| |
| Signed-off-by: Kevin Cernekee <cernekee@chromium.org> |
| Reviewed-on: https://chromium-review.googlesource.com/362671 |
| Reviewed-by: Guenter Roeck <groeck@google.com> |
| |
| Conflicts: |
| Documentation/android.txt (deleted locally) |
| include/net/sock.h |
| net/core/sock.c |
| net/core/sysctl_net_core.c |
| net/ipv6/af_inet6.c |
| security/commoncap.c |
| net/ipv4/af_inet.c |
| |
| [rebase412(groeck): Clean version, not depending on Android |
| version of ANDROID_PARANOID_NETWORK] |
| |
| Conflicts: |
| net/core/sysctl_net_core.c |
| net/ipv4/af_inet.c |
| net/ipv6/af_inet6.c |
| security/commoncap.c |
| |
| [rebase419(groeck): Resolve various conflicts] |
| Signed-off-by: Guenter Roeck <groeck@google.com> |
| |
| (cherry picked from commit eeff9e17e144063f761163315007ea67d42106ab) |
| |
| Conflicts: |
| drivers/net/tun.c |
| net/core/sysctl_net_core.c |
| net/ipv4/af_inet.c |
| net/ipv6/af_inet6.c |
| security/commoncap.c |
| |
| [Cherry-pick to 5.4: Resolve various conflicts] |
| |
| Signed-off-by: Taoyu Li <taoyl@google.com> |
| Change-Id: Ie14fbfbe24d875bb103bcaebb3edd1e4528baf3b |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2213509 |
| Tested-by: Taoyu Li <taoyl@chromium.org> |
| Reviewed-by: Guenter Roeck <groeck@chromium.org> |
| Reviewed-by: Hugo Benichi <hugobenichi@google.com> |
| Commit-Queue: Taoyu Li <taoyl@chromium.org> |
| Conflicts: net/core/sock.c |
| [rebase510(groeck): Context conflicts] |
| Signed-off-by: Guenter Roeck <groeck@chromium.org> |
| --- |
| drivers/net/tun.c | 5 +++++ |
| include/net/netns/core.h | 1 + |
| include/net/sock.h | 1 + |
| net/core/sock.c | 20 ++++++++++++++++++++ |
| net/core/sysctl_net_core.c | 12 ++++++++++++ |
| net/ipv4/af_inet.c | 4 ++++ |
| net/ipv6/af_inet6.c | 4 ++++ |
| 7 files changed, 47 insertions(+) |
| |
| diff --git a/drivers/net/tun.c b/drivers/net/tun.c |
| index fc86da7f1628..e4b0d49fa3c4 100644 |
| --- a/drivers/net/tun.c |
| +++ b/drivers/net/tun.c |
| @@ -2936,6 +2936,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, |
| int ret; |
| bool do_notify = false; |
| |
| + if (current->nsproxy->net_ns->core.sysctl_android_paranoid && |
| + cmd != TUNGETIFF && !capable(CAP_NET_ADMIN)) { |
| + return -EPERM; |
| + } |
| + |
| if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || |
| (_IOC_TYPE(cmd) == SOCK_IOC_TYPE && cmd != SIOCGSKNS)) { |
| if (copy_from_user(&ifr, argp, ifreq_len)) |
| diff --git a/include/net/netns/core.h b/include/net/netns/core.h |
| index 36c2d998a43c..2c13b2176335 100644 |
| --- a/include/net/netns/core.h |
| +++ b/include/net/netns/core.h |
| @@ -10,6 +10,7 @@ struct netns_core { |
| struct ctl_table_header *sysctl_hdr; |
| |
| int sysctl_somaxconn; |
| + int sysctl_android_paranoid; |
| |
| #ifdef CONFIG_PROC_FS |
| int __percpu *sock_inuse; |
| diff --git a/include/net/sock.h b/include/net/sock.h |
| index 0b6266fd6bf6..1bc0ad8cbbcf 100644 |
| --- a/include/net/sock.h |
| +++ b/include/net/sock.h |
| @@ -2647,6 +2647,7 @@ bool sk_ns_capable(const struct sock *sk, |
| struct user_namespace *user_ns, int cap); |
| bool sk_capable(const struct sock *sk, int cap); |
| bool sk_net_capable(const struct sock *sk, int cap); |
| +bool inet_sk_allowed(struct net *net, gid_t gid); |
| |
| void sk_get_meminfo(const struct sock *sk, u32 *meminfo); |
| |
| diff --git a/net/core/sock.c b/net/core/sock.c |
| index cc31b601ae10..466e08015d8a 100644 |
| --- a/net/core/sock.c |
| +++ b/net/core/sock.c |
| @@ -114,6 +114,8 @@ |
| #include <linux/memcontrol.h> |
| #include <linux/prefetch.h> |
| #include <linux/compat.h> |
| +#include <linux/cred.h> |
| +#include <linux/uidgid.h> |
| |
| #include <linux/uaccess.h> |
| |
| @@ -192,6 +194,24 @@ bool sk_net_capable(const struct sock *sk, int cap) |
| } |
| EXPORT_SYMBOL(sk_net_capable); |
| |
| +static bool in_android_group(struct user_namespace *user, gid_t gid) |
| +{ |
| + kgid_t kgid = make_kgid(user, gid); |
| + |
| + if (!gid_valid(kgid)) |
| + return false; |
| + return in_egroup_p(kgid); |
| +} |
| + |
| +bool inet_sk_allowed(struct net *net, gid_t gid) |
| +{ |
| + if (!net->core.sysctl_android_paranoid || |
| + ns_capable(net->user_ns, CAP_NET_RAW)) |
| + return true; |
| + return in_android_group(net->user_ns, gid); |
| +} |
| +EXPORT_SYMBOL(inet_sk_allowed); |
| + |
| /* |
| * Each address family might have different locking rules, so we have |
| * one slock key per address family and separate keys for internal and |
| diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c |
| index 4567de519603..4a6c29978a51 100644 |
| --- a/net/core/sysctl_net_core.c |
| +++ b/net/core/sysctl_net_core.c |
| @@ -582,6 +582,15 @@ static struct ctl_table netns_core_table[] = { |
| .extra1 = SYSCTL_ZERO, |
| .proc_handler = proc_dointvec_minmax |
| }, |
| + { |
| + .procname = "android_paranoid", |
| + .data = &init_net.core.sysctl_android_paranoid, |
| + .maxlen = sizeof(int), |
| + .mode = 0644, |
| + .extra1 = SYSCTL_ZERO, |
| + .extra2 = SYSCTL_ONE, |
| + .proc_handler = proc_dointvec_minmax |
| + }, |
| { } |
| }; |
| |
| @@ -602,6 +611,8 @@ static __net_init int sysctl_core_net_init(struct net *net) |
| { |
| struct ctl_table *tbl; |
| |
| + net->core.sysctl_android_paranoid = 0; |
| + |
| tbl = netns_core_table; |
| if (!net_eq(net, &init_net)) { |
| tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL); |
| @@ -609,6 +620,7 @@ static __net_init int sysctl_core_net_init(struct net *net) |
| goto err_dup; |
| |
| tbl[0].data = &net->core.sysctl_somaxconn; |
| + tbl[1].data = &net->core.sysctl_android_paranoid; |
| |
| /* Don't export any sysctls to unprivileged users */ |
| if (net->user_ns != &init_user_ns) { |
| diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c |
| index 1355e6c0d567..60a085be3941 100644 |
| --- a/net/ipv4/af_inet.c |
| +++ b/net/ipv4/af_inet.c |
| @@ -85,6 +85,7 @@ |
| #include <linux/netfilter_ipv4.h> |
| #include <linux/random.h> |
| #include <linux/slab.h> |
| +#include <linux/android_aid.h> |
| |
| #include <linux/uaccess.h> |
| |
| @@ -259,6 +260,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol, |
| if (protocol < 0 || protocol >= IPPROTO_MAX) |
| return -EINVAL; |
| |
| + if (!inet_sk_allowed(net, AID_INET)) |
| + return -EACCES; |
| + |
| sock->state = SS_UNCONNECTED; |
| |
| /* Look for the requested type/protocol pair. */ |
| diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c |
| index 802f5111805a..12cbe691cd08 100644 |
| --- a/net/ipv6/af_inet6.c |
| +++ b/net/ipv6/af_inet6.c |
| @@ -39,6 +39,7 @@ |
| #include <linux/netdevice.h> |
| #include <linux/icmpv6.h> |
| #include <linux/netfilter_ipv6.h> |
| +#include <linux/android_aid.h> |
| |
| #include <net/ip.h> |
| #include <net/ipv6.h> |
| @@ -122,6 +123,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, |
| if (protocol < 0 || protocol >= IPPROTO_MAX) |
| return -EINVAL; |
| |
| + if (!inet_sk_allowed(net, AID_INET)) |
| + return -EACCES; |
| + |
| /* Look for the requested type/protocol pair. */ |
| lookup_protocol: |
| err = -ESOCKTNOSUPPORT; |
| -- |
| 2.17.1 |
| |