| From 7f063e595ca7357c8d519b93b5f266af72a2e591 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> |
| |
| [rebase515(groeck): |
| Squashed: |
| FIXUP: CHROMIUM: Introduce ANDROID_PARANOID_NETWORK as per-netns setting |
| ] |
| Signed-off-by: Guenter Roeck <groeck@chromium.org> |
| --- |
| drivers/net/tun.c | 5 +++++ |
| include/linux/android_aid.h | 28 ++++++++++++++++++++++++++++ |
| include/net/netns/core.h | 1 + |
| include/net/sock.h | 1 + |
| net/core/sock.c | 20 ++++++++++++++++++++ |
| net/core/sysctl_net_core.c | 11 +++++++++++ |
| net/ipv4/af_inet.c | 4 ++++ |
| net/ipv6/af_inet6.c | 4 ++++ |
| 8 files changed, 74 insertions(+) |
| create mode 100644 include/linux/android_aid.h |
| |
| diff --git a/drivers/net/tun.c b/drivers/net/tun.c |
| index 7a3ab3427369abab7472c3fbb07c24e7031f21b2..6bf6989aae545dc302d06f854a32295ce16035ba 100644 |
| --- a/drivers/net/tun.c |
| +++ b/drivers/net/tun.c |
| @@ -3056,6 +3056,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/linux/android_aid.h b/include/linux/android_aid.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..97946ef0a383d94ce30fc57a8bc6a5135e6cc1df |
| --- /dev/null |
| +++ b/include/linux/android_aid.h |
| @@ -0,0 +1,28 @@ |
| +/* include/linux/android_aid.h |
| + * |
| + * Copyright (C) 2008 Google, Inc. |
| + * |
| + * This software is licensed under the terms of the GNU General Public |
| + * License version 2, as published by the Free Software Foundation, and |
| + * may be copied, distributed, and modified under those terms. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + */ |
| + |
| +#ifndef _LINUX_ANDROID_AID_H |
| +#define _LINUX_ANDROID_AID_H |
| + |
| +/* AIDs that the kernel treats differently */ |
| +#define AID_OBSOLETE_000 (3001) /* was NET_BT_ADMIN */ |
| +#define AID_OBSOLETE_001 (3002) /* was NET_BT */ |
| +#define AID_INET (3003) |
| +#define AID_NET_RAW (3004) |
| +#define AID_NET_ADMIN (3005) |
| +#define AID_NET_BW_STATS (3006) /* read bandwidth statistics */ |
| +#define AID_NET_BW_ACCT (3007) /* change bandwidth statistics accounting */ |
| + |
| +#endif |
| diff --git a/include/net/netns/core.h b/include/net/netns/core.h |
| index 8249060cf5d0063de5295f7a1bc0e3c77f1f90fc..f7fead62797f38cce2a0a5c39992b19ffdb973ed 100644 |
| --- a/include/net/netns/core.h |
| +++ b/include/net/netns/core.h |
| @@ -12,6 +12,7 @@ struct netns_core { |
| struct ctl_table_header *sysctl_hdr; |
| |
| int sysctl_somaxconn; |
| + int sysctl_android_paranoid; |
| u8 sysctl_txrehash; |
| |
| #ifdef CONFIG_PROC_FS |
| diff --git a/include/net/sock.h b/include/net/sock.h |
| index e0517ecc6531571f05568029408a49fa472dc9be..d18824da40f2897a91e4014c8dd0369f4638dab2 100644 |
| --- a/include/net/sock.h |
| +++ b/include/net/sock.h |
| @@ -2872,6 +2872,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 a3ba0358c77c0e44db1cfbaeb420f8b80ad7cf98..41f5e2b9004767fbbce39d631759f2674f904bb5 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> |
| |
| @@ -197,6 +199,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 5b1ce656baa1d4701a1b62724edc437d847d8f5f..a9b92490842e87f567b06aeab1d57c7e25c9c104 100644 |
| --- a/net/core/sysctl_net_core.c |
| +++ b/net/core/sysctl_net_core.c |
| @@ -606,6 +606,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 |
| + }, |
| { |
| .procname = "txrehash", |
| .data = &init_net.core.sysctl_txrehash, |
| @@ -635,6 +644,8 @@ static __net_init int sysctl_core_net_init(struct net *net) |
| { |
| struct ctl_table *tbl, *tmp; |
| |
| + 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); |
| diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c |
| index 4728087c42a5cc879d25a935e73d162b4db74e03..3f3116363c177deedb9ce5cccdae8b523e58a1d9 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> |
| |
| @@ -256,6 +257,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 0241910049825ba6e67ac66e3569bdca4512640d..c4998a42cdba84372a64519a916617f173e57e55 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> |
| @@ -130,6 +131,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.38.1.584.g0f3c55d4c2-goog |
| |