@@ -15,7 +15,7 @@ ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
ccflags-$(CONFIG_SECURITY_SELINUX_DEBUG) += -DDEBUG
selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
- netnode.o netport.o status.o \
+ netnode.o netport.o status.o global_sidtab.o \
ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/context.o
new file mode 100644
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "global_sidtab.h"
+#include "sidtab.h"
+
+static struct sidtab global_sidtab;
+
+int global_sidtab_init(void)
+{
+ struct context ctx;
+ int rc, sid;
+
+ rc = sidtab_init(&global_sidtab);
+ if (rc)
+ return rc;
+
+ memset(&ctx, 0, sizeof(ctx));
+ for (sid = 1; sid <= SECINITSID_NUM; sid++) {
+ const char *str = security_get_initial_sid_context(sid);
+
+ if (!str)
+ continue;
+ ctx.str = (char *)str;
+ ctx.len = strlen(str)+1;
+ rc = sidtab_set_initial(&global_sidtab, sid, &ctx);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
+int global_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
+{
+ struct context *ctx;
+
+ rcu_read_lock();
+ ctx = sidtab_search_force(&global_sidtab, sid);
+ if (!ctx) {
+ rcu_read_unlock();
+ *scontext = NULL;
+ *scontext_len = 0;
+ return -EINVAL;
+ }
+ *scontext_len = ctx->len;
+ /*
+ * Could eliminate allocation + copy if callers do not free
+ * since the global sidtab entries are never freed.
+ * This however would not match the current expectation
+ * of callers of security_sid_to_context().
+ * TODO: Update all callers and get rid of this copy.
+ */
+ *scontext = kstrdup(ctx->str, GFP_ATOMIC);
+ if (!(*scontext)) {
+ rcu_read_unlock();
+ *scontext_len = 0;
+ return -ENOMEM;
+ }
+
+ rcu_read_unlock();
+ return 0;
+}
+
+int global_context_to_sid(const char *scontext, u32 scontext_len, u32 *out_sid,
+ gfp_t gfp)
+{
+ char *str;
+ struct context ctx;
+ int rc;
+
+ if (!scontext_len)
+ return -EINVAL;
+
+ /*
+ * Could eliminate allocation + copy if callers were required to
+ * pass in a NUL-terminated string or if the context_cmp/cpy()
+ * functions did not assume that ctx.str is NUL-terminated.
+ * This however would not match the current expectation of
+ * callers of security_context_to_sid, particularly contexts
+ * fetched from xattr values or provided by the xattr APIs.
+ * TODO: Change context_cmp/cpy() or update all callers and
+ * get rid of this copy.
+ */
+ str = kmemdup_nul(scontext, scontext_len, gfp);
+ if (!str)
+ return -ENOMEM;
+
+ ctx.str = str;
+ ctx.len = strlen(str)+1;
+
+retry:
+ rcu_read_lock();
+ rc = sidtab_context_to_sid(&global_sidtab, &ctx, out_sid);
+ if (rc == -ESTALE) {
+ rcu_read_unlock();
+ goto retry;
+ }
+ rcu_read_unlock();
+ kfree(str);
+ return rc;
+}
@@ -105,6 +105,7 @@
#include "netlabel.h"
#include "audit.h"
#include "avc_ss.h"
+#include "global_sidtab.h"
#define SELINUX_INODE_INIT_XATTRS 1
@@ -7662,6 +7663,9 @@ static __init int selinux_init(void)
panic("SELinux: Could not create initial namespace\n");
enforcing_set(init_selinux_state, selinux_enforcing_boot);
+ if (global_sidtab_init())
+ panic("SELinux: Could not create global SID table\n");
+
/* Set the security state for the initial task. */
cred_init_security();
similarity index 100%
rename from security/selinux/ss/avtab.h
rename to security/selinux/include/avtab.h
similarity index 100%
rename from security/selinux/ss/constraint.h
rename to security/selinux/include/constraint.h
similarity index 100%
rename from security/selinux/ss/context.h
rename to security/selinux/include/context.h
similarity index 100%
rename from security/selinux/ss/ebitmap.h
rename to security/selinux/include/ebitmap.h
new file mode 100644
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * A global security identifier table (sidtab) is a lookup table
+ * of security context strings indexed by SID value.
+ */
+
+#ifndef _GLOBAL_SIDTAB_H_
+#define _GLOBAL_SIDTAB_H_
+
+#include <linux/types.h>
+
+extern int global_sidtab_init(void);
+
+extern int global_sid_to_context(u32 sid, char **scontext, u32 *scontext_len);
+
+extern int global_context_to_sid(const char *scontext, u32 scontext_len,
+ u32 *out_sid, gfp_t gfp);
+
+#endif /* _GLOBAL_SIDTAB_H_ */
similarity index 100%
rename from security/selinux/ss/hashtab.h
rename to security/selinux/include/hashtab.h
similarity index 100%
rename from security/selinux/ss/mls.h
rename to security/selinux/include/mls.h
similarity index 100%
rename from security/selinux/ss/mls_types.h
rename to security/selinux/include/mls_types.h
similarity index 100%
rename from security/selinux/ss/policydb.h
rename to security/selinux/include/policydb.h
similarity index 100%
rename from security/selinux/ss/sidtab.h
rename to security/selinux/include/sidtab.h
similarity index 100%
rename from security/selinux/ss/symtab.h
rename to security/selinux/include/symtab.h
Introduce a global SID table to provide stable global SID values independent of any particular policy or namespace. This table will only map between global SIDs and security context strings since it must remain policy-independent. Internally each of these global SIDs can then be mapped on a per-policy/namespace basis to per-namespace SIDs and context structures. The LSM interfaces and blob structures will only use the global SID values and thus remain namespace-neutral. Note that this required moving the SID table header and its dependencies out of the security server subdirectory. While we could re-factor it to to reduce the scope of this change, doing so does not seem worthwhile. The security server abstraction is largely obsoleted by LSM, no one has contributed any other security server implementation for SELinux, and over time there has been an increasing blurring of the boundary between the security server and the rest of the SELinux module. Eventually, I anticipate fully moving the security server files out of the ss subdirectory but that is left for a future change. Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com> --- security/selinux/Makefile | 2 +- security/selinux/global_sidtab.c | 100 ++++++++++++++++++ security/selinux/hooks.c | 4 + security/selinux/{ss => include}/avtab.h | 0 security/selinux/{ss => include}/constraint.h | 0 security/selinux/{ss => include}/context.h | 0 security/selinux/{ss => include}/ebitmap.h | 0 security/selinux/include/global_sidtab.h | 19 ++++ security/selinux/{ss => include}/hashtab.h | 0 security/selinux/{ss => include}/mls.h | 0 security/selinux/{ss => include}/mls_types.h | 0 security/selinux/{ss => include}/policydb.h | 0 security/selinux/{ss => include}/sidtab.h | 0 security/selinux/{ss => include}/symtab.h | 0 14 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 security/selinux/global_sidtab.c rename security/selinux/{ss => include}/avtab.h (100%) rename security/selinux/{ss => include}/constraint.h (100%) rename security/selinux/{ss => include}/context.h (100%) rename security/selinux/{ss => include}/ebitmap.h (100%) create mode 100644 security/selinux/include/global_sidtab.h rename security/selinux/{ss => include}/hashtab.h (100%) rename security/selinux/{ss => include}/mls.h (100%) rename security/selinux/{ss => include}/mls_types.h (100%) rename security/selinux/{ss => include}/policydb.h (100%) rename security/selinux/{ss => include}/sidtab.h (100%) rename security/selinux/{ss => include}/symtab.h (100%)