ANDROID: selinux: modify RTM_GETNEIGH{TBL}

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.

This change is intended to be backported to all kernels that a T system
image can run on top of.

Bug: 171572148
Test: atest 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é <brambonne@google.com>
(cherry picked from commit fac07550bdac9adea0dbe3edbdbec7a9a690a178)
This commit is contained in:
Bram Bonné 2021-04-30 11:50:19 +02:00
parent e399f16519
commit 6f8540b744
6 changed files with 38 additions and 5 deletions

View File

@ -116,7 +116,8 @@ struct security_class_mapping secclass_map[] = {
{ COMMON_IPC_PERMS, NULL } }, { COMMON_IPC_PERMS, NULL } },
{ "netlink_route_socket", { "netlink_route_socket",
{ COMMON_SOCK_PERMS, { COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", "nlmsg_readpriv", NULL } }, "nlmsg_read", "nlmsg_write", "nlmsg_readpriv", "nlmsg_getneigh",
NULL } },
{ "netlink_tcpdiag_socket", { "netlink_tcpdiag_socket",
{ COMMON_SOCK_PERMS, { COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } }, "nlmsg_read", "nlmsg_write", NULL } },

View File

@ -106,6 +106,8 @@ struct selinux_state {
bool initialized; bool initialized;
bool policycap[__POLICYDB_CAPABILITY_MAX]; bool policycap[__POLICYDB_CAPABILITY_MAX];
bool android_netlink_route; bool android_netlink_route;
bool android_netlink_getneigh;
struct selinux_avc *avc; struct selinux_avc *avc;
struct selinux_ss *ss; struct selinux_ss *ss;
}; };
@ -185,6 +187,13 @@ static inline bool selinux_android_nlroute_getlink(void)
return state->android_netlink_route; return state->android_netlink_route;
} }
static inline bool selinux_android_nlroute_getneigh(void)
{
struct selinux_state *state = &selinux_state;
return state->android_netlink_getneigh;
}
int security_mls_enabled(struct selinux_state *state); int security_mls_enabled(struct selinux_state *state);
int security_load_policy(struct selinux_state *state, int security_load_policy(struct selinux_state *state,
void *data, size_t len); void *data, size_t len);

View File

@ -207,12 +207,12 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
return err; return err;
} }
static void nlmsg_set_getlink_perm(u32 perm) static void nlmsg_set_perm_for_type(u32 perm, u16 type)
{ {
int i; int i;
for (i = 0; i < ARRAY_SIZE(nlmsg_route_perms); 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; nlmsg_route_perms[i].perm = perm;
break; break;
} }
@ -222,11 +222,27 @@ static void nlmsg_set_getlink_perm(u32 perm)
/** /**
* Use nlmsg_readpriv as the permission for RTM_GETLINK messages if the * Use nlmsg_readpriv as the permission for RTM_GETLINK messages if the
* netlink_route_getlink policy capability is set. Otherwise use nlmsg_read. * 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) void selinux_nlmsg_init(void)
{ {
if (selinux_android_nlroute_getlink()) if (selinux_android_nlroute_getlink())
nlmsg_set_getlink_perm(NETLINK_ROUTE_SOCKET__NLMSG_READPRIV); nlmsg_set_perm_for_type(NETLINK_ROUTE_SOCKET__NLMSG_READPRIV,
RTM_GETLINK);
else else
nlmsg_set_getlink_perm(NETLINK_ROUTE_SOCKET__NLMSG_READ); nlmsg_set_perm_for_type(NETLINK_ROUTE_SOCKET__NLMSG_READ,
RTM_GETLINK);
if (selinux_android_nlroute_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);
}
} }

View File

@ -2353,6 +2353,10 @@ int policydb_read(struct policydb *p, void *fp)
p->android_netlink_route = 1; 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) { if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
rc = ebitmap_read(&p->policycaps, fp); rc = ebitmap_read(&p->policycaps, fp);
if (rc) if (rc)

View File

@ -235,6 +235,7 @@ struct genfs {
struct policydb { struct policydb {
int mls_enabled; int mls_enabled;
int android_netlink_route; int android_netlink_route;
int android_netlink_getneigh;
/* symbol tables */ /* symbol tables */
struct symtab symtab[SYM_NUM]; struct symtab symtab[SYM_NUM];
@ -322,6 +323,7 @@ extern int policydb_write(struct policydb *p, void *fp);
#define POLICYDB_CONFIG_MLS 1 #define POLICYDB_CONFIG_MLS 1
#define POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE (1 << 31) #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 */ /* the config flags related to unknown classes/perms are bits 2 and 3 */
#define REJECT_UNKNOWN 0x00000002 #define REJECT_UNKNOWN 0x00000002

View File

@ -2127,6 +2127,7 @@ static void security_load_policycaps(struct selinux_state *state)
} }
state->android_netlink_route = p->android_netlink_route; state->android_netlink_route = p->android_netlink_route;
state->android_netlink_getneigh = p->android_netlink_getneigh;
selinux_nlmsg_init(); selinux_nlmsg_init();
} }