blob: 04ea240cea2c03f4c189f3442c9031c108d1fef9 [file] [log] [blame]
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