summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Vander Stoep <jeffv@google.com>2020-01-22 11:19:58 +0100
committerJeffrey Vander Stoep <jeffv@google.com>2020-01-23 18:43:27 +0000
commit1b6aeaf17f6de907dec61fde4eb137d9dd71e464 (patch)
treee39757b184fe1e48fca49cb901ea0dfc28c9c94d
parenta5869a66f7170c4b4ff06c0990a60269e906bd13 (diff)
ANDROID: selinux: modify RTM_GETLINK permission
Map the permission gating RTM_GETLINK messages to a new permission so that it can be distinguished from the other netlink route permissions in selinux policy. This is a temporary Android-only patch that will be deprecated in newer kernels once the long-term solution lands as discusssed on the mailing list [1]. The maintainer's recommended solution is more general, much more complex, and likely not suitable for backporting. This patch provides the minimal change needed for Android including the userspace settable trigger which ensures that the permission change is only applied to the newest version of Android which contains the changes needed for userpace compatibility. [1]: https://lore.kernel.org/selinux/20200116142653.61738-1-jeffv@google.com/ Bug: 141455849 Bug: 148218425 Test: CtsSelinuxTargetSdkCurrentTestCases Test: atest bionic-unit-tests-static Test: atest NetworkInterfaceTest Test: Connect to Wi-Fi network Test: Set up hotspot Test: Cast from device Test: Pair Bluetooth device Test: Call getifaddrs() directly from within an app. Test: Call NetworkInterface#getNetworkInterfaces() from within an app. Change-Id: I7b44ce60ad98f858c412722d41b9842f8577151f Signed-off-by: Jeff Vander Stoep <jeffv@google.com>
-rw-r--r--security/selinux/include/classmap.h2
-rw-r--r--security/selinux/include/security.h2
-rw-r--r--security/selinux/nlmsgtab.c24
-rw-r--r--security/selinux/ss/policydb.c4
-rw-r--r--security/selinux/ss/policydb.h2
-rw-r--r--security/selinux/ss/services.c4
6 files changed, 37 insertions, 1 deletions
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index b393d29ae857..31dc821a6be0 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -100,7 +100,7 @@ struct security_class_mapping secclass_map[] = {
{ COMMON_IPC_PERMS, NULL } },
{ "netlink_route_socket",
{ COMMON_SOCK_PERMS,
- "nlmsg_read", "nlmsg_write", NULL } },
+ "nlmsg_read", "nlmsg_write", "nlmsg_readpriv", NULL } },
{ "netlink_tcpdiag_socket",
{ COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } },
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 223e9fd15d66..dff1d1a1367a 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -79,6 +79,7 @@ enum {
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
+extern int selinux_android_netlink_route;
extern int selinux_policycap_netpeer;
extern int selinux_policycap_openperm;
extern int selinux_policycap_alwaysnetwork;
@@ -264,6 +265,7 @@ extern struct vfsmount *selinuxfs_mount;
extern void selnl_notify_setenforce(int val);
extern void selnl_notify_policyload(u32 seqno);
extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
+extern void selinux_nlmsg_init(void);
#endif /* _SELINUX_SECURITY_H_ */
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 0714b4c61a8b..78a8c420b1f5 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -191,3 +191,27 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
return err;
}
+
+static void nlmsg_set_getlink_perm(u32 perm)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(nlmsg_route_perms); i++) {
+ if (nlmsg_route_perms[i].nlmsg_type == RTM_GETLINK) {
+ nlmsg_route_perms[i].perm = perm;
+ break;
+ }
+ }
+}
+
+/**
+ * Use nlmsg_readpriv as the permission for RTM_GETLINK messages if the
+ * netlink_route_getlink policy capability is set. Otherwise use nlmsg_read.
+ */
+void selinux_nlmsg_init(void)
+{
+ if (selinux_android_netlink_route)
+ nlmsg_set_getlink_perm(NETLINK_ROUTE_SOCKET__NLMSG_READPRIV);
+ else
+ nlmsg_set_getlink_perm(NETLINK_ROUTE_SOCKET__NLMSG_READ);
+}
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 01fbbbf89f41..5ee23e3a3678 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -2329,6 +2329,10 @@ int policydb_read(struct policydb *p, void *fp)
p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
+ if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE)) {
+ p->android_netlink_route = 1;
+ }
+
if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
rc = ebitmap_read(&p->policycaps, fp);
if (rc)
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 725d5945a97e..0d511cf3c1e9 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -227,6 +227,7 @@ struct genfs {
/* The policy database */
struct policydb {
int mls_enabled;
+ int android_netlink_route;
/* symbol tables */
struct symtab symtab[SYM_NUM];
@@ -313,6 +314,7 @@ extern int policydb_write(struct policydb *p, void *fp);
#define PERM_SYMTAB_SIZE 32
#define POLICYDB_CONFIG_MLS 1
+#define POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE (1 << 31)
/* the config flags related to unknown classes/perms are bits 2 and 3 */
#define REJECT_UNKNOWN 0x00000002
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 0a258c0602d1..2b3907e0d93c 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -70,6 +70,7 @@
#include "ebitmap.h"
#include "audit.h"
+int selinux_android_netlink_route;
int selinux_policycap_netpeer;
int selinux_policycap_openperm;
int selinux_policycap_alwaysnetwork;
@@ -1997,6 +1998,9 @@ static void security_load_policycaps(void)
POLICYDB_CAPABILITY_OPENPERM);
selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
POLICYDB_CAPABILITY_ALWAYSNETWORK);
+
+ selinux_android_netlink_route = policydb.android_netlink_route;
+ selinux_nlmsg_init();
}
static int security_preserve_bools(struct policydb *p);