From 33eee52b2bd927afd34805dd1031a9f2d579d6ea Mon Sep 17 00:00:00 2001 From: "pengzhao.liu" Date: Tue, 22 Mar 2022 14:03:33 +0800 Subject: [PATCH] ANDROID: selinux: modify RTM_GETNEIGH [1/1] MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit PD#SWPL-71742 Bug: 171572148 Problem: Map the permission gating RTM_GETNEIGH/RTM_GETNEIGHTBL messages to a new permission so that it can be distinguished from the other netlink route permissions in selinux policy. The new permission is triggered by a flag set in system images T and up. Solution: This change is intended to be backported to all kernels that a T system image can run on top of. Verify: on adt3-t kernel Test: ateddst NetworkInterfaceTest Test: atest CtsSelinuxTargetSdkCurrentTestCases Test: atest bionic-unit-tests-static Test: On Cuttlefish, run combinations of: - Policy bit set or omitted (see https://r.android.com/1701847) - This patch applied or omitted - App having nlmsg_readneigh permission or not Verify that only the combination of this patch + the policy bit being set + the app not having the nlmsg_readneigh permission prevents the app from sending RTM_GETNEIGH messages. Change-Id: I4bcfce4decb34ea9388eeedfc4be67403de8a980 Signed-off-by: Bram Bonné Signed-off-by: pengzhao.liu Change-Id: Ic9d51cebab8c195537d54a28a23a7e93f09ba0b3 --- security/selinux/include/classmap.h | 3 ++- security/selinux/include/security.h | 1 + security/selinux/nlmsgtab.c | 31 ++++++++++++++++++++++------- security/selinux/ss/policydb.c | 4 ++++ security/selinux/ss/policydb.h | 2 ++ security/selinux/ss/services.c | 2 ++ 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 1764b221d545..3742d8788224 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -105,7 +105,8 @@ struct security_class_mapping secclass_map[] = { { COMMON_IPC_PERMS, NULL } }, { "netlink_route_socket", { COMMON_SOCK_PERMS, - "nlmsg_read", "nlmsg_write", "nlmsg_readpriv", NULL } }, + "nlmsg_read", "nlmsg_write", "nlmsg_readpriv", "nlmsg_getneigh", + 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 2775170b526f..ea3c8a35f045 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -79,6 +79,7 @@ extern int selinux_android_netlink_route; extern int selinux_policycap_netpeer; extern int selinux_policycap_openperm; extern int selinux_policycap_alwaysnetwork; +extern int selinux_android_netlink_getneigh; /* * type_datum properties diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 697785cec7f6..957e37041ea7 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -194,26 +194,43 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) return err; } -static void nlmsg_set_getlink_perm(u32 perm) + +static void nlmsg_set_perm_for_type(u32 perm, u16 type) { int i; for (i = 0; i < ARRAY_SIZE(nlmsg_route_perms); i++) { - if (nlmsg_route_perms[i].nlmsg_type == RTM_GETLINK) { + if (nlmsg_route_perms[i].nlmsg_type == type) { 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. + * Similarly, use nlmsg_getneigh for RTM_GETNEIGH and RTM_GETNEIGHTBL if the + * netlink_route_getneigh 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); + if (selinux_android_netlink_route) { + nlmsg_set_perm_for_type(NETLINK_ROUTE_SOCKET__NLMSG_READPRIV, + RTM_GETLINK); + } else { + nlmsg_set_perm_for_type(NETLINK_ROUTE_SOCKET__NLMSG_READ, + RTM_GETLINK); + } + + if (selinux_android_netlink_getneigh) { + nlmsg_set_perm_for_type(NETLINK_ROUTE_SOCKET__NLMSG_GETNEIGH, + RTM_GETNEIGH); + nlmsg_set_perm_for_type(NETLINK_ROUTE_SOCKET__NLMSG_GETNEIGH, + RTM_GETNEIGHTBL); + } else { + nlmsg_set_perm_for_type(NETLINK_ROUTE_SOCKET__NLMSG_READ, + RTM_GETNEIGH); + nlmsg_set_perm_for_type(NETLINK_ROUTE_SOCKET__NLMSG_READ, + RTM_GETNEIGHTBL); + } } diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 62518b031e5e..12553cbe0b48 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -2335,6 +2335,10 @@ int policydb_read(struct policydb *p, void *fp) if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE)) { p->android_netlink_route = 1; } + if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH)) { + p->android_netlink_getneigh = 1; + } + if (p->policyvers >= POLICYDB_VERSION_POLCAP) { rc = ebitmap_read(&p->policycaps, fp); diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 0d511cf3c1e9..45698f754766 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -228,6 +228,7 @@ struct genfs { struct policydb { int mls_enabled; int android_netlink_route; + int android_netlink_getneigh; /* symbol tables */ struct symtab symtab[SYM_NUM]; @@ -315,6 +316,7 @@ extern int policydb_write(struct policydb *p, void *fp); #define POLICYDB_CONFIG_MLS 1 #define POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE (1 << 31) +#define POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH (1 << 30) /* 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 14bbea8ad596..66a8a6f67fb1 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -74,6 +74,7 @@ int selinux_android_netlink_route; int selinux_policycap_netpeer; int selinux_policycap_openperm; int selinux_policycap_alwaysnetwork; +int selinux_android_netlink_getneigh; static DEFINE_RWLOCK(policy_rwlock); @@ -1994,6 +1995,7 @@ static void security_load_policycaps(void) POLICYDB_CAPABILITY_ALWAYSNETWORK); selinux_android_netlink_route = policydb.android_netlink_route; + selinux_android_netlink_getneigh = policydb.android_netlink_getneigh; selinux_nlmsg_init(); } -- 2.20.1