On Tue, 11 Mar 2025 at 17:23, Stephen Smalley <stephen.smalley.work@xxxxxxxxx> wrote: > > On Tue, Mar 11, 2025 at 6:52 AM Christian Göttsche > <cgzones@xxxxxxxxxxxxxx> wrote: > > > > Mar 11, 2025 10:29:42 Takaya Saeki <takayas@xxxxxxxxxxxx>: > > > > > 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, but relabeling thousands of paths under sysfs > > > after it is mounted is inefficient compared to using genfscon. > > > > > > This commit adds wildcard match to support rules efficient but > > > expressive enough. This allows users to create fine-grained sysfs rules > > > without burden of listing specific paths. 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 genfscon policy will > > > be applied. However, 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@xxxxxxxxxxxx> > > > --- > > > Changelog between v2 and v1 > > > - Use given genfs rules by the userspace as is, instead of appending "*". > > > - Fix __security_genfs_sid hadn't checked caps of the given argument. > > > - Fix the wrong strncmp usage bug. > > > > > > security/selinux/include/policycap.h | 1 + > > > security/selinux/include/policycap_names.h | 1 + > > > security/selinux/ss/services.c | 20 ++++++++++++++++---- > > > 3 files changed, 18 insertions(+), 4 deletions(-) > > > > > > diff --git a/security/selinux/include/policycap.h b/security/selinux/include/policycap.h > > > index 079679fe7254..2b4014a826f0 100644 > > > --- a/security/selinux/include/policycap.h > > > +++ b/security/selinux/include/policycap.h > > > @@ -15,6 +15,7 @@ enum { > > > POLICYDB_CAP_IOCTL_SKIP_CLOEXEC, > > > POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT, > > > POLICYDB_CAP_NETLINK_XPERM, > > > + POLICYDB_CAP_GENFS_SECLABEL_WILDCARD, > > > __POLICYDB_CAP_MAX > > > }; > > > #define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1) > > > diff --git a/security/selinux/include/policycap_names.h b/security/selinux/include/policycap_names.h > > > index e080827408c4..1053f2c95ff3 100644 > > > --- a/security/selinux/include/policycap_names.h > > > +++ b/security/selinux/include/policycap_names.h > > > @@ -18,6 +18,7 @@ const char *const selinux_policycap_names[__POLICYDB_CAP_MAX] = { > > > "ioctl_skip_cloexec", > > > "userspace_initial_context", > > > "netlink_xperm", > > > + "genfs_seclabel_wildcard", > > > }; > > > /* clang-format on */ > > > > > > diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c > > > index 8478842fbf9e..9f98c9dc71f6 100644 > > > --- a/security/selinux/ss/services.c > > > +++ b/security/selinux/ss/services.c > > > @@ -48,6 +48,7 @@ > > > #include <linux/audit.h> > > > #include <linux/vmalloc.h> > > > #include <linux/lsm_hooks.h> > > > +#include <linux/parser.h> > > > #include <net/netlabel.h> > > > > > > #include "flask.h" > > > @@ -2863,6 +2864,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, > > > struct genfs *genfs; > > > struct ocontext *c; > > > int cmp = 0; > > > + bool wildcard = 0; > > > > > > while (path[0] == '/' && path[1] == '/') > > > path++; > > > @@ -2879,11 +2881,21 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, > > > if (!genfs || cmp) > > > return -ENOENT; > > > > > > + > > > + wildcard = ebitmap_get_bit(&policy->policydb.policycaps, > > > + POLICYDB_CAP_GENFS_SECLABEL_WILDCARD); > > > > Commonly policy capabilities are gathered via a helper from security.h from selinux_state, shouldn't it here too? > > Those are for accessing the cached policy capabilities in the > selinux_state from outside of the security server (and without holding > any locks), e.g. from the hook functions. > No need for that here, and this is more correct - using the policy we > were passed rather than whatever selinux_state might reference at the > time (e.g. during a policy reload). Should this also be used in security_netif_sid()? diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 1b11648d9b85..720a69fb4234 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2587,14 +2587,13 @@ int security_netif_sid(const char *name, u32 *if_sid) return 0; } - wildcard_support = selinux_policycap_netif_wildcard(); - retry: rc = 0; rcu_read_lock(); policy = rcu_dereference(selinux_state.policy); policydb = &policy->policydb; sidtab = policy->sidtab; + wildcard_support = ebitmap_get_bit(policydb->policycaps, POLICYDB_CAP_NETIF_WILDCARD); c = policydb->ocontexts[OCON_NETIF]; while (c) {