| From d8d03f933cec524f9de9acda2b76f8616e967684 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 276a0e42ca8e..7825fa58f930 100644 |
| --- a/drivers/net/tun.c |
| +++ b/drivers/net/tun.c |
| @@ -3034,6 +3034,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 000000000000..97946ef0a383 |
| --- /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 388244e315e7..aa4dec1e5ba5 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; |
| u8 sysctl_txrehash; |
| |
| #ifdef CONFIG_PROC_FS |
| diff --git a/include/net/sock.h b/include/net/sock.h |
| index c4b91fc19b9c..dbbb8be57541 100644 |
| --- a/include/net/sock.h |
| +++ b/include/net/sock.h |
| @@ -2805,6 +2805,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 1180a0cb0110..93e35681da46 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 7123fe7feeac..4a2e238155c4 100644 |
| --- a/net/core/sysctl_net_core.c |
| +++ b/net/core/sysctl_net_core.c |
| @@ -591,6 +591,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, |
| @@ -620,6 +629,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 72fde2888ad2..e38a87fbcaf6 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 7d7b7523d126..e320391040f4 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> |
| @@ -123,6 +124,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.35.0 |
| |