ANDROID: selinux: modify RTM_GETNEIGH{TBL}
authorBram Bonné <brambonne@google.com>
Fri, 30 Apr 2021 09:50:19 +0000 (11:50 +0200)
committerBram Bonné <brambonne@google.com>
Tue, 27 Jul 2021 15:16:25 +0000 (17:16 +0200)
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)
(cherry picked from commit 32d7afd1472c3cce509a3455b40a575540eac780)

security/selinux/include/classmap.h
security/selinux/include/security.h
security/selinux/nlmsgtab.c
security/selinux/ss/policydb.c
security/selinux/ss/policydb.h
security/selinux/ss/services.c

index 702bdaf07252dd63482316136797b510542c38ff..97fa672a9f0ee080ec2ecdd645ef91aae64cc75e 100644 (file)
@@ -115,7 +115,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 } },
index 45cc615fddaedd9852256e8e524a7da080572aba..afd41bad48b78cdde9cf239f24e7026207012be9 100644 (file)
@@ -82,6 +82,7 @@ enum {
 extern char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX];
 
 extern int selinux_android_netlink_route;
+extern int selinux_android_netlink_getneigh;
 extern int selinux_policycap_netpeer;
 extern int selinux_policycap_openperm;
 extern int selinux_policycap_extsockclass;
index 963930b4e2f8cd5c7126157074f1dd542367c053..04406b7a21c8b73908427b79138b435bb8bfd070 100644 (file)
@@ -196,12 +196,12 @@ 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;
                }
@@ -211,11 +211,27 @@ static void nlmsg_set_getlink_perm(u32 perm)
 /**
  * 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);
+               nlmsg_set_perm_for_type(NETLINK_ROUTE_SOCKET__NLMSG_READPRIV,
+                                       RTM_GETLINK);
        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_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);
+       }
 }
index 51564b2aba9e18374d6846fccea77b8f83cc0684..a2333997edf6e87f3daa25514c18b5d00626f188 100644 (file)
@@ -2390,6 +2390,10 @@ int policydb_read(struct policydb *p, void *fp)
                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);
                if (rc)
index dbb0ed57ed8b164d1001b5cb761358bbb553f9ac..9423952faf7b6505d1b278727f6b743461e9e392 100644 (file)
@@ -239,6 +239,7 @@ struct genfs {
 struct policydb {
        int mls_enabled;
        int android_netlink_route;
+       int android_netlink_getneigh;
 
        /* symbol tables */
        struct symtab symtab[SYM_NUM];
@@ -326,6 +327,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
index 37a4ec12d74a0d3edbd86b3db6973d1bfd1ac2ea..2e1716f6890aaafd0991ba3705e11ccf9ee4301b 100644 (file)
@@ -81,6 +81,7 @@ char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = {
 };
 
 int selinux_android_netlink_route;
+int selinux_android_netlink_getneigh;
 int selinux_policycap_netpeer;
 int selinux_policycap_openperm;
 int selinux_policycap_extsockclass;
@@ -2029,6 +2030,7 @@ static void security_load_policycaps(void)
        }
 
        selinux_android_netlink_route = policydb.android_netlink_route;
+       selinux_android_netlink_getneigh = policydb.android_netlink_getneigh;
        selinux_nlmsg_init();
 }