Skip to content

Commit 8716451

Browse files
nullpo-headpcmoore
authored andcommitted
selinux: support wildcard match in genfscon
Currently, genfscon only supports string prefix match to label files. Thus, labeling numerous dynamic sysfs entries requires many specific path rules. For example, labeling device paths such as `/sys/devices/pci0000:00/0000:00:03.1/<...>/0000:04:00.1/wakeup` requires listing all specific PCI paths, which is challenging to maintain. While user-space restorecon can handle these paths with regular expression rules, relabeling thousands of paths under sysfs after it is mounted is inefficient compared to using genfscon. This commit adds wildcard matching to genfscon to make rules more efficient and expressive. This new behavior is enabled by genfs_seclabel_wildcard capability. With this capability, genfscon does wildcard matching instead of prefix matching. When multiple wildcard rules match against a path, then the longest rule (determined by the length of the rule string) will be applied. If multiple rules of the same length match, the first matching rule encountered in the given genfscon policy will be applied. Users are encouraged to write longer, more explicit path rules to avoid relying on this behavior. This change resulted in nice real-world performance improvements. For example, boot times on test Android devices were reduced by 15%. This improvement is due to the elimination of the "restorecon -R /sys" step during boot, which takes more than two seconds in the worst case. Signed-off-by: Takaya Saeki <takayas@chromium.org> Signed-off-by: Paul Moore <paul@paul-moore.com>
1 parent 4926c3f commit 8716451

3 files changed

Lines changed: 17 additions & 4 deletions

File tree

security/selinux/include/policycap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ enum {
1616
POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT,
1717
POLICYDB_CAP_NETLINK_XPERM,
1818
POLICYDB_CAP_NETIF_WILDCARD,
19+
POLICYDB_CAP_GENFS_SECLABEL_WILDCARD,
1920
__POLICYDB_CAP_MAX
2021
};
2122
#define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1)

security/selinux/include/policycap_names.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const char *const selinux_policycap_names[__POLICYDB_CAP_MAX] = {
1919
"userspace_initial_context",
2020
"netlink_xperm",
2121
"netif_wildcard",
22+
"genfs_seclabel_wildcard",
2223
};
2324
/* clang-format on */
2425

security/selinux/ss/services.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include <linux/parser.h>
5050
#include <linux/vmalloc.h>
5151
#include <linux/lsm_hooks.h>
52+
#include <linux/parser.h>
5253
#include <net/netlabel.h>
5354

5455
#include "flask.h"
@@ -2872,6 +2873,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
28722873
struct genfs *genfs;
28732874
struct ocontext *c;
28742875
int cmp = 0;
2876+
bool wildcard;
28752877

28762878
while (path[0] == '/' && path[1] == '/')
28772879
path++;
@@ -2888,11 +2890,20 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
28882890
if (!genfs || cmp)
28892891
return -ENOENT;
28902892

2893+
wildcard = ebitmap_get_bit(&policy->policydb.policycaps,
2894+
POLICYDB_CAP_GENFS_SECLABEL_WILDCARD);
28912895
for (c = genfs->head; c; c = c->next) {
2892-
size_t len = strlen(c->u.name);
2893-
if ((!c->v.sclass || sclass == c->v.sclass) &&
2894-
(strncmp(c->u.name, path, len) == 0))
2895-
break;
2896+
if (!c->v.sclass || sclass == c->v.sclass) {
2897+
if (wildcard) {
2898+
if (match_wildcard(c->u.name, path))
2899+
break;
2900+
} else {
2901+
size_t len = strlen(c->u.name);
2902+
2903+
if ((strncmp(c->u.name, path, len)) == 0)
2904+
break;
2905+
}
2906+
}
28962907
}
28972908

28982909
if (!c)

0 commit comments

Comments
 (0)