aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-26 19:07:27 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-26 19:07:27 +0000
commit5ce91b1cc6e7edda99c9319d1c998d3dab7ff96b (patch)
tree344775c0a84b555cede4e77a39917eba4613f46c
parentcd93689d6164133a44944bdb76fd1e9487cbc672 (diff)
parent5a0344eaeccb6bc9ac443e00e9997a09d84327bc (diff)
downloadselinux-main-cg-testing-release.tar.gz
Snap for 8502205 from 5a0344eaeccb6bc9ac443e00e9997a09d84327bc to main-cg-testing-releasemain-cg-testing-release
Change-Id: I170879bc642326f03a9f4192822faf0b3471e744
-rw-r--r--libselinux/include/selinux/android.h33
-rw-r--r--libselinux/src/android/android.c322
-rw-r--r--libselinux/src/android/android_common.h8
-rw-r--r--libselinux/src/android/android_internal.h24
-rw-r--r--libselinux/src/android/android_platform.c258
5 files changed, 291 insertions, 354 deletions
diff --git a/libselinux/include/selinux/android.h b/libselinux/include/selinux/android.h
index 60813248..1249133f 100644
--- a/libselinux/include/selinux/android.h
+++ b/libselinux/include/selinux/android.h
@@ -11,38 +11,61 @@
extern "C" {
#endif
+/* Returns the file context handle */
extern struct selabel_handle* selinux_android_file_context_handle(void);
+/* Returns the service context handle */
extern struct selabel_handle* selinux_android_service_context_handle(void);
+/* Returns the hardware service context handle */
extern struct selabel_handle* selinux_android_hw_service_context_handle(void);
+/* Returns the vendor service context handle */
extern struct selabel_handle* selinux_android_vendor_service_context_handle(void);
+/* Returns the keystore2 context handle */
extern struct selabel_handle* selinux_android_keystore2_key_context_handle(void);
+/* Sets the file context handle. Must be called using the output of
+ * selinux_android_file_context_handle. This function can be used to preload
+ * the file_contexts files and speed up later calls to
+ * selinux_android_restorecon and selinux_android_restorecon_pkgdir */
extern void selinux_android_set_sehandle(const struct selabel_handle *hndl);
+/* Deprecated. Loads the default policy from /sepolicy. The policy loading is
+ * done directly by init. See system/core/init/selinux.cpp. */
extern int selinux_android_load_policy(void);
+/* Deprecated. Loads a policy from fd. The policy loading is done directly by
+ * init. See system/core/init/selinux.cpp. */
extern int selinux_android_load_policy_from_fd(int fd, const char *description);
+/* Sets the context of the current process. This should be used in preference
+ * to setcon() on Android. */
extern int selinux_android_setcon(const char *con);
+/* Sets the context of the current app process based on the information
+ * provided. Returns -1 if no matching context is found or the transition
+ * failed */
extern int selinux_android_setcontext(uid_t uid,
bool isSystemServer,
const char *seinfo,
const char *name);
+/* Builds a new context based on context, adding the categories from userid and
+ * appid. If userid or appid are -1, the corresponding categories are not
+ * modified. */
extern int selinux_android_context_with_level(const char * context,
char ** newContext,
uid_t userid,
uid_t appid);
+/* Provides a log callback that uses the Android logging facility. See selinux_set_callback. */
extern int selinux_log_callback(int type, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
-// API to support legacy usecase where full-treble legacy VNDK vendor needs to use this callback.
+/* Provides a log callback that uses the Android logging facility for vendors.
+ * See selinux_set_callback. */
extern int selinux_vendor_log_callback(int type, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
@@ -54,15 +77,23 @@ extern int selinux_vendor_log_callback(int type, const char *fmt, ...)
#define SELINUX_ANDROID_RESTORECON_SKIPCE 32
#define SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS 64
#define SELINUX_ANDROID_RESTORECON_SKIP_SEHASH 128
+/* Restores the security context of a file. */
extern int selinux_android_restorecon(const char *file, unsigned int flags);
+/* Restores the security context of a package's private directory. */
extern int selinux_android_restorecon_pkgdir(const char *pkgdir,
const char *seinfo,
uid_t uid,
unsigned int flags);
+/* Initialize the seapp contexts for future lookups. Loads all the
+ * seapp_contexts files. To force a reload of the files, use
+ * selinux_android_seapp_context_reload. While not required, this function can
+ * be used to speed up the inital calls to selinux_android_setcontext,
+ * selinux_android_restorecon and selinux_android_restorecon_pkgdir. */
extern void selinux_android_seapp_context_init(void);
+/* Forces a reload of the seapp_contexts files. */
extern int selinux_android_seapp_context_reload(void);
#ifdef __cplusplus
diff --git a/libselinux/src/android/android.c b/libselinux/src/android/android.c
index 7ee9e774..169af51f 100644
--- a/libselinux/src/android/android.c
+++ b/libselinux/src/android/android.c
@@ -1,239 +1,167 @@
#include "android_common.h"
-// For 'system', 'system_ext' (optional), 'product' (optional), 'vendor' (mandatory)
-// and/or 'odm' (optional).
-#define MAX_FILE_CONTEXT_SIZE 5
-
#ifdef __ANDROID_VNDK__
#ifndef LOG_EVENT_STRING
#define LOG_EVENT_STRING(...)
#endif // LOG_EVENT_STRING
#endif // __ANDROID_VNDK__
-static const struct selinux_opt seopts_service_plat[] = {
- { SELABEL_OPT_PATH, "/system/etc/selinux/plat_service_contexts" },
- { SELABEL_OPT_PATH, "/plat_service_contexts" }
-};
-static const struct selinux_opt seopts_service_apex[] = {
- { SELABEL_OPT_PATH, "/dev/selinux/apex_service_contexts" }
-};
-static const struct selinux_opt seopts_service_system_ext[] = {
- { SELABEL_OPT_PATH, "/system_ext/etc/selinux/system_ext_service_contexts" },
- { SELABEL_OPT_PATH, "/system_ext_service_contexts" }
-};
-static const struct selinux_opt seopts_service_product[] = {
- { SELABEL_OPT_PATH, "/product/etc/selinux/product_service_contexts" },
- { SELABEL_OPT_PATH, "/product_service_contexts" }
-};
-static const struct selinux_opt seopts_service_vendor[] = {
- { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_service_contexts" },
- { SELABEL_OPT_PATH, "/vendor_service_contexts" }
+static const char* const service_context_paths[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS] = {
+ {
+ "/system/etc/selinux/plat_service_contexts",
+ "/plat_service_contexts"
+ },
+ {
+ "/dev/selinux/apex_service_contexts"
+ },
+ {
+ "/system_ext/etc/selinux/system_ext_service_contexts",
+ "/system_ext_service_contexts"
+ },
+ {
+ "/product/etc/selinux/product_service_contexts",
+ "/product_service_contexts"
+ },
+ {
+ "/vendor/etc/selinux/vendor_service_contexts",
+ "/vendor_service_contexts"
+ }
};
-static const struct selinux_opt seopts_hwservice_plat[] = {
- { SELABEL_OPT_PATH, "/system/etc/selinux/plat_hwservice_contexts" },
- { SELABEL_OPT_PATH, "/plat_hwservice_contexts" }
+static const char* const hwservice_context_paths[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS] = {
+ {
+ "/system/etc/selinux/plat_hwservice_contexts",
+ "/plat_hwservice_contexts"
+ },
+ {
+ "/system_ext/etc/selinux/system_ext_hwservice_contexts",
+ "/system_ext_hwservice_contexts"
+ },
+ {
+ "/product/etc/selinux/product_hwservice_contexts",
+ "/product_hwservice_contexts"
+ },
+ {
+ "/vendor/etc/selinux/vendor_hwservice_contexts",
+ "/vendor_hwservice_contexts"
+ },
+ {
+ "/odm/etc/selinux/odm_hwservice_contexts",
+ "/odm_hwservice_contexts"
+ },
};
-static const struct selinux_opt seopts_hwservice_system_ext[] = {
- { SELABEL_OPT_PATH, "/system_ext/etc/selinux/system_ext_hwservice_contexts" },
- { SELABEL_OPT_PATH, "/system_ext_hwservice_contexts" }
-};
-static const struct selinux_opt seopts_hwservice_product[] = {
- { SELABEL_OPT_PATH, "/product/etc/selinux/product_hwservice_contexts" },
- { SELABEL_OPT_PATH, "/product_hwservice_contexts" }
-};
-static const struct selinux_opt seopts_hwservice_vendor[] = {
- { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_hwservice_contexts" },
- { SELABEL_OPT_PATH, "/vendor_hwservice_contexts" }
-};
-static const struct selinux_opt seopts_hwservice_odm[] = {
- { SELABEL_OPT_PATH, "/odm/etc/selinux/odm_hwservice_contexts" },
- { SELABEL_OPT_PATH, "/odm_hwservice_contexts" }
-};
-
-static const struct selinux_opt seopts_vndservice =
- { SELABEL_OPT_PATH, "/vendor/etc/selinux/vndservice_contexts" };
-static const struct selinux_opt seopts_vndservice_rootfs =
- { SELABEL_OPT_PATH, "/vndservice_contexts" };
-
-static const struct selinux_opt seopts_keystore2_key_plat[] = {
- { SELABEL_OPT_PATH, "/system/etc/selinux/plat_keystore2_key_contexts" },
- { SELABEL_OPT_PATH, "/plat_keystore2_key_contexts" }
-};
-static const struct selinux_opt seopts_keystore2_key_system_ext[] = {
- { SELABEL_OPT_PATH, "/system_ext/etc/selinux/system_ext_keystore2_key_contexts" },
- { SELABEL_OPT_PATH, "/system_ext_keystore2_key_contexts" }
-};
-static const struct selinux_opt seopts_keystore2_key_product[] = {
- { SELABEL_OPT_PATH, "/product/etc/selinux/product_keystore2_key_contexts" },
- { SELABEL_OPT_PATH, "/product_keystore2_key_contexts" }
+static const char* const vndservice_context_paths[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS] = {
+ {
+ "/vendor/etc/selinux/vndservice_contexts",
+ "/vndservice_contexts"
+ }
};
-static const struct selinux_opt seopts_keystore2_key_vendor[] = {
- { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_keystore2_key_contexts" },
- { SELABEL_OPT_PATH, "/vendor_keystore2_key_contexts" },
+
+static const char* const keystore2_context_paths[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS] = {
+ {
+ "/system/etc/selinux/plat_keystore2_key_contexts",
+ "/plat_keystore2_key_contexts"
+ },
+ {
+ "/system_ext/etc/selinux/system_ext_keystore2_key_contexts",
+ "/system_ext_keystore2_key_contexts"
+ },
+ {
+ "/product/etc/selinux/product_keystore2_key_contexts",
+ "/product_keystore2_key_contexts"
+ },
+ {
+ "/vendor/etc/selinux/vendor_keystore2_key_contexts",
+ "/vendor_keystore2_key_contexts"
+ }
};
-struct selabel_handle* selinux_android_service_open_context_handle(const struct selinux_opt* seopts_service,
- unsigned nopts)
+size_t find_existing_files(
+ const char* const path_sets[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS],
+ const char* paths[MAX_CONTEXT_PATHS])
{
- struct selabel_handle* sehandle;
+ size_t i, j, len = 0;
+ for (i = 0; i < MAX_CONTEXT_PATHS; i++) {
+ for (j = 0; j < MAX_ALT_CONTEXT_PATHS; j++) {
+ const char* file = path_sets[i][j];
+ if (file && access(file, R_OK) != -1) {
+ paths[len++] = file;
+ /* Within each set, only the first valid entry is used */
+ break;
+ }
+ }
+ }
+ return len;
+}
- sehandle = selabel_open(SELABEL_CTX_ANDROID_SERVICE,
- seopts_service, nopts);
+void paths_to_opts(const char* paths[MAX_CONTEXT_PATHS],
+ size_t npaths,
+ struct selinux_opt* const opts)
+{
+ for (size_t i = 0; i < npaths; i++) {
+ opts[i].type = SELABEL_OPT_PATH;
+ opts[i].value = paths[i];
+ }
+}
- if (!sehandle) {
- selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n",
- __FUNCTION__, strerror(errno));
- return NULL;
- }
- selinux_log(SELINUX_INFO, "SELinux: Loaded service_contexts from:\n");
- for (unsigned i = 0; i < nopts; i++) {
- selinux_log(SELINUX_INFO, " %s\n", seopts_service[i].value);
- }
- return sehandle;
+struct selabel_handle* initialize_backend(
+ unsigned int backend,
+ const char* name,
+ const struct selinux_opt* opts,
+ size_t nopts)
+{
+ struct selabel_handle* sehandle;
+
+ sehandle = selabel_open(backend, opts, nopts);
+
+ if (!sehandle) {
+ selinux_log(SELINUX_ERROR, "%s: Error getting %s handle (%s)\n",
+ __FUNCTION__, name, strerror(errno));
+ return NULL;
+ }
+ selinux_log(SELINUX_INFO, "SELinux: Loaded %s context from:\n", name);
+ for (unsigned i = 0; i < nopts; i++) {
+ if (opts[i].type == SELABEL_OPT_PATH)
+ selinux_log(SELINUX_INFO, " %s\n", opts[i].value);
+ }
+ return sehandle;
}
-struct selabel_handle* selinux_android_keystore2_key_open_context_handle(const struct selinux_opt* seopts_service,
- unsigned nopts)
+/* Initialize a backend using a set of context paths */
+static struct selabel_handle* context_handle(
+ unsigned int backend,
+ const char* const context_paths[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS],
+ char *name)
{
- struct selabel_handle* sehandle;
+ const char* existing_paths[MAX_CONTEXT_PATHS];
+ struct selinux_opt opts[MAX_CONTEXT_PATHS];
+ int size = 0;
- sehandle = selabel_open(SELABEL_CTX_ANDROID_KEYSTORE2_KEY,
- seopts_service, nopts);
+ size = find_existing_files(context_paths, existing_paths);
+ paths_to_opts(existing_paths, size, opts);
- if (!sehandle) {
- selinux_log(SELINUX_ERROR, "%s: Error getting keystore key context handle (%s)\n",
- __FUNCTION__, strerror(errno));
- return NULL;
- }
- selinux_log(SELINUX_INFO, "SELinux: Loaded keystore2_key_contexts from:\n");
- for (unsigned i = 0; i < nopts; i++) {
- selinux_log(SELINUX_INFO, " %s\n", seopts_service[i].value);
- }
- return sehandle;
+ return initialize_backend(backend, name, opts, size);
}
struct selabel_handle* selinux_android_service_context_handle(void)
{
- struct selinux_opt seopts_service[MAX_FILE_CONTEXT_SIZE];
- int size = 0;
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE(seopts_service_plat); i++) {
- if (access(seopts_service_plat[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_service_plat[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_service_apex); i++) {
- if (access(seopts_service_apex[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_service_apex[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_service_system_ext); i++) {
- if (access(seopts_service_system_ext[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_service_system_ext[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_service_product); i++) {
- if (access(seopts_service_product[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_service_product[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_service_vendor); i++) {
- if (access(seopts_service_vendor[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_service_vendor[i];
- break;
- }
- }
-
- return selinux_android_service_open_context_handle(seopts_service, size);
+ return context_handle(SELABEL_CTX_ANDROID_SERVICE, service_context_paths, "service");
}
struct selabel_handle* selinux_android_hw_service_context_handle(void)
{
- struct selinux_opt seopts_service[MAX_FILE_CONTEXT_SIZE];
- int size = 0;
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE(seopts_hwservice_plat); i++) {
- if (access(seopts_hwservice_plat[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_hwservice_plat[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_hwservice_system_ext); i++) {
- if (access(seopts_hwservice_system_ext[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_hwservice_system_ext[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_hwservice_product); i++) {
- if (access(seopts_hwservice_product[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_hwservice_product[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_hwservice_vendor); i++) {
- if (access(seopts_hwservice_vendor[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_hwservice_vendor[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_hwservice_odm); i++) {
- if (access(seopts_hwservice_odm[i].value, R_OK) != -1) {
- seopts_service[size++] = seopts_hwservice_odm[i];
- break;
- }
- }
- return selinux_android_service_open_context_handle(seopts_service, size);
+ return context_handle(SELABEL_CTX_ANDROID_SERVICE, hwservice_context_paths, "hwservice");
}
struct selabel_handle* selinux_android_vendor_service_context_handle(void)
{
- const struct selinux_opt* seopts_service;
- if (access(seopts_vndservice.value, R_OK) != -1) {
- seopts_service = &seopts_vndservice;
- } else {
- seopts_service = &seopts_vndservice_rootfs;
- }
-
- return selinux_android_service_open_context_handle(seopts_service, 1);
+ return context_handle(SELABEL_CTX_ANDROID_SERVICE, vndservice_context_paths, "vndservice");
}
struct selabel_handle* selinux_android_keystore2_key_context_handle(void)
{
- struct selinux_opt seopts_keystore2_key[MAX_FILE_CONTEXT_SIZE];
- int size = 0;
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE(seopts_keystore2_key_plat); i++) {
- if (access(seopts_keystore2_key_plat[i].value, R_OK) != -1) {
- seopts_keystore2_key[size++] = seopts_keystore2_key_plat[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_keystore2_key_system_ext); i++) {
- if (access(seopts_keystore2_key_system_ext[i].value, R_OK) != -1) {
- seopts_keystore2_key[size++] = seopts_keystore2_key_system_ext[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_keystore2_key_product); i++) {
- if (access(seopts_keystore2_key_product[i].value, R_OK) != -1) {
- seopts_keystore2_key[size++] = seopts_keystore2_key_product[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_keystore2_key_vendor); i++) {
- if (access(seopts_keystore2_key_vendor[i].value, R_OK) != -1) {
- seopts_keystore2_key[size++] = seopts_keystore2_key_vendor[i];
- break;
- }
- }
-
- return selinux_android_keystore2_key_open_context_handle(seopts_keystore2_key, size);
+ return context_handle(SELABEL_CTX_ANDROID_KEYSTORE2_KEY, keystore2_context_paths, "keystore2");
}
int selinux_log_callback(int type, const char *fmt, ...)
diff --git a/libselinux/src/android/android_common.h b/libselinux/src/android/android_common.h
index 78b2e712..db634945 100644
--- a/libselinux/src/android/android_common.h
+++ b/libselinux/src/android/android_common.h
@@ -1,5 +1,3 @@
-
-#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
@@ -40,3 +38,9 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define FC_DIGEST_SIZE SHA_DIGEST_LENGTH
+
+// Context files (file_contexts, service_contexts, etc) may be spread over
+// multiple partitions: system, apex, system_ext, product, vendor and/or odm.
+#define MAX_CONTEXT_PATHS 6
+// The maximum number of alternatives for a file on one partition.
+#define MAX_ALT_CONTEXT_PATHS 2
diff --git a/libselinux/src/android/android_internal.h b/libselinux/src/android/android_internal.h
new file mode 100644
index 00000000..f7764c63
--- /dev/null
+++ b/libselinux/src/android/android_internal.h
@@ -0,0 +1,24 @@
+#include <sys/types.h>
+
+#include "android_common.h"
+
+/* Within each set of files, adds the first file that is accessible to `paths`.
+ * Returns the number of accessible files. */
+size_t find_existing_files(
+ const char* const path_sets[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS],
+ const char* paths[MAX_CONTEXT_PATHS]);
+
+/* Converts an array of file paths into an array of options for selabel_open.
+ * opts must be at least as large as paths. */
+void paths_to_opts(
+ const char* paths[MAX_CONTEXT_PATHS],
+ size_t npaths,
+ struct selinux_opt* const opts);
+
+/* Initialize a backend using the specified options. Ensure that any error is
+ * reported to the android logging facility */
+struct selabel_handle* initialize_backend(
+ unsigned int backend,
+ const char* name,
+ const struct selinux_opt* opts,
+ size_t nopts);
diff --git a/libselinux/src/android/android_platform.c b/libselinux/src/android/android_platform.c
index 05c923bc..ad08c596 100644
--- a/libselinux/src/android/android_platform.c
+++ b/libselinux/src/android/android_platform.c
@@ -1,136 +1,98 @@
#include "android_common.h"
+#include "android_internal.h"
#include <packagelistparser/packagelistparser.h>
-// For 'system', 'system_ext' (optional), 'apex' (optional), 'product' (optional),
-// 'vendor' (mandatory) and/or 'odm' (optional) .
-#define MAX_FILE_CONTEXT_SIZE 6
-
static const char *const sepolicy_file = "/sepolicy";
-static const struct selinux_opt seopts_file_plat[] = {
- { SELABEL_OPT_PATH, "/system/etc/selinux/plat_file_contexts" },
- { SELABEL_OPT_PATH, "/plat_file_contexts" }
-};
-static const struct selinux_opt seopts_file_apex[] = {
- { SELABEL_OPT_PATH, "/dev/selinux/apex_file_contexts" }
-};
-static const struct selinux_opt seopts_file_system_ext[] = {
- { SELABEL_OPT_PATH, "/system_ext/etc/selinux/system_ext_file_contexts" },
- { SELABEL_OPT_PATH, "/system_ext_file_contexts" }
-};
-static const struct selinux_opt seopts_file_product[] = {
- { SELABEL_OPT_PATH, "/product/etc/selinux/product_file_contexts" },
- { SELABEL_OPT_PATH, "/product_file_contexts" }
-};
-static const struct selinux_opt seopts_file_vendor[] = {
- { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_file_contexts" },
- { SELABEL_OPT_PATH, "/vendor_file_contexts" }
-};
-static const struct selinux_opt seopts_file_odm[] = {
- { SELABEL_OPT_PATH, "/odm/etc/selinux/odm_file_contexts" },
- { SELABEL_OPT_PATH, "/odm_file_contexts" }
+/* Locations for the file_contexts files. For each partition, only the first
+ * existing entry will be used (for example, if
+ * /system/etc/selinux/plat_file_contexts exists, /plat_file_contexts will be
+ * ignored).
+ */
+static const char* const file_context_paths[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS] = {
+ {
+ "/system/etc/selinux/plat_file_contexts",
+ "/plat_file_contexts"
+ },
+ {
+ "/dev/selinux/apex_file_contexts",
+ },
+ {
+ "/system_ext/etc/selinux/system_ext_file_contexts",
+ "/system_ext_file_contexts"
+ },
+ {
+ "/product/etc/selinux/product_file_contexts",
+ "/product_file_contexts"
+ },
+ {
+ "/vendor/etc/selinux/vendor_file_contexts",
+ "/vendor_file_contexts"
+ },
+ {
+ "/odm/etc/selinux/odm_file_contexts",
+ "/odm_file_contexts"
+ }
};
-/*
- * XXX Where should this configuration file be located?
- * Needs to be accessible by zygote and installd when
- * setting credentials for app processes and setting permissions
- * on app data directories.
+/* Locations for the seapp_contexts files. For each partition, only the first
+ * existing entry will be used (for example, if
+ * /system/etc/selinux/plat_seapp_contexts exists, /plat_seapp_contexts will be
+ * ignored).
*/
-static char const * const seapp_contexts_plat[] = {
- "/system/etc/selinux/plat_seapp_contexts",
- "/plat_seapp_contexts"
-};
-static char const * const seapp_contexts_apex[] = {
- "/dev/selinux/apex_seapp_contexts"
-};
-static char const * const seapp_contexts_system_ext[] = {
- "/system_ext/etc/selinux/system_ext_seapp_contexts",
- "/system_ext_seapp_contexts"
-};
-static char const * const seapp_contexts_product[] = {
- "/product/etc/selinux/product_seapp_contexts",
- "/product_seapp_contexts"
-};
-static char const * const seapp_contexts_vendor[] = {
- "/vendor/etc/selinux/vendor_seapp_contexts",
- "/vendor_seapp_contexts"
-};
-static char const * const seapp_contexts_odm[] = {
- "/odm/etc/selinux/odm_seapp_contexts",
- "/odm_seapp_contexts"
+static const char* const seapp_context_paths[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS] = {
+ {
+ "/system/etc/selinux/plat_seapp_contexts",
+ "/plat_seapp_contexts"
+ },
+ {
+ "/dev/selinux/apex_seapp_contexts",
+ },
+ {
+ "/system_ext/etc/selinux/system_ext_seapp_contexts",
+ "/system_ext_seapp_contexts"
+ },
+ {
+ "/product/etc/selinux/product_seapp_contexts",
+ "/product_seapp_contexts"
+ },
+ {
+ "/vendor/etc/selinux/vendor_seapp_contexts",
+ "/vendor_seapp_contexts"
+ },
+ {
+ "/odm/etc/selinux/odm_seapp_contexts",
+ "/odm_seapp_contexts"
+ }
};
-static struct selabel_handle* selinux_android_file_context(const struct selinux_opt *opts,
- unsigned nopts)
+/* Returns a handle for the file contexts backend, initialized with the Android
+ * configuration */
+struct selabel_handle* selinux_android_file_context_handle(void)
{
- struct selabel_handle *sehandle;
- struct selinux_opt fc_opts[nopts + 1];
-
- memcpy(fc_opts, opts, nopts*sizeof(struct selinux_opt));
- fc_opts[nopts].type = SELABEL_OPT_BASEONLY;
- fc_opts[nopts].value = (char *)1;
-
- sehandle = selabel_open(SELABEL_CTX_FILE, fc_opts, ARRAY_SIZE(fc_opts));
- if (!sehandle) {
- selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n",
- __FUNCTION__, strerror(errno));
- return NULL;
- }
+ const char* file_contexts[MAX_CONTEXT_PATHS];
+ struct selinux_opt opts[MAX_CONTEXT_PATHS + 1];
+ int npaths, nopts;
- selinux_log(SELINUX_INFO, "SELinux: Loaded file_contexts\n");
+ npaths = find_existing_files(file_context_paths, file_contexts);
+ paths_to_opts(file_contexts, npaths, opts);
- return sehandle;
-}
+ opts[npaths].type = SELABEL_OPT_BASEONLY;
+ opts[npaths].value = (char *) 1;
+ nopts = npaths + 1;
-struct selabel_handle* selinux_android_file_context_handle(void)
-{
- struct selinux_opt seopts_file[MAX_FILE_CONTEXT_SIZE];
- int size = 0;
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE(seopts_file_plat); i++) {
- if (access(seopts_file_plat[i].value, R_OK) != -1) {
- seopts_file[size++] = seopts_file_plat[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_file_apex); i++) {
- if (access(seopts_file_apex[i].value, R_OK) != -1) {
- seopts_file[size++] = seopts_file_apex[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_file_system_ext); i++) {
- if (access(seopts_file_system_ext[i].value, R_OK) != -1) {
- seopts_file[size++] = seopts_file_system_ext[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_file_product); i++) {
- if (access(seopts_file_product[i].value, R_OK) != -1) {
- seopts_file[size++] = seopts_file_product[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_file_vendor); i++) {
- if (access(seopts_file_vendor[i].value, R_OK) != -1) {
- seopts_file[size++] = seopts_file_vendor[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seopts_file_odm); i++) {
- if (access(seopts_file_odm[i].value, R_OK) != -1) {
- seopts_file[size++] = seopts_file_odm[i];
- break;
- }
- }
- return selinux_android_file_context(seopts_file, size);
+ return initialize_backend(SELABEL_CTX_FILE, "file", opts, nopts);
}
+/* Which categories should be associated to the process */
enum levelFrom {
+ /* None */
LEVELFROM_NONE,
+ /* The categories of the application */
LEVELFROM_APP,
+ /* The categories of the end-user */
LEVELFROM_USER,
+ /* Application and end-user */
LEVELFROM_ALL
};
@@ -156,6 +118,9 @@ static void free_prefix_str(struct prefix_str *p)
free(p->str);
}
+/* For a set of selectors, represents the contexts that should be applied to an
+ * app and its data. Each instance is based on a line in a seapp_contexts file.
+ * */
struct seapp_context {
/* input selectors */
bool isSystemServer;
@@ -188,8 +153,10 @@ static void free_seapp_context(struct seapp_context *s)
free(s->level);
}
+/* If any duplicate was found while sorting the entries */
static bool seapp_contexts_dup = false;
+/* Compare two seapp_context. Used to sort all the entries found. */
static int seapp_context_cmp(const void *A, const void *B)
{
const struct seapp_context *const *sp1 = (const struct seapp_context *const *) A;
@@ -288,7 +255,9 @@ static int seapp_context_cmp(const void *A, const void *B)
return 0;
}
+/* Array of all the seapp_context entries configured. */
static struct seapp_context **seapp_contexts = NULL;
+/* Size of seapp_contexts */
static int nspec = 0;
static void free_seapp_contexts(void)
@@ -328,44 +297,11 @@ int selinux_android_seapp_context_reload(void)
char *p, *name = NULL, *value = NULL, *saveptr;
size_t i, len, files_len = 0;
int ret;
- const char* seapp_contexts_files[MAX_FILE_CONTEXT_SIZE];
- for (i = 0; i < ARRAY_SIZE(seapp_contexts_plat); i++) {
- if (access(seapp_contexts_plat[i], R_OK) != -1) {
- seapp_contexts_files[files_len++] = seapp_contexts_plat[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seapp_contexts_apex); i++) {
- if (access(seapp_contexts_apex[i], R_OK) != -1) {
- seapp_contexts_files[files_len++] = seapp_contexts_apex[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seapp_contexts_system_ext); i++) {
- if (access(seapp_contexts_system_ext[i], R_OK) != -1) {
- seapp_contexts_files[files_len++] = seapp_contexts_system_ext[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seapp_contexts_product); i++) {
- if (access(seapp_contexts_product[i], R_OK) != -1) {
- seapp_contexts_files[files_len++] = seapp_contexts_product[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seapp_contexts_vendor); i++) {
- if (access(seapp_contexts_vendor[i], R_OK) != -1) {
- seapp_contexts_files[files_len++] = seapp_contexts_vendor[i];
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(seapp_contexts_odm); i++) {
- if (access(seapp_contexts_odm[i], R_OK) != -1) {
- seapp_contexts_files[files_len++] = seapp_contexts_odm[i];
- break;
- }
- }
+ const char* seapp_contexts_files[MAX_CONTEXT_PATHS];
+ files_len = find_existing_files(seapp_context_paths, seapp_contexts_files);
+
+ /* Reset the current entries */
free_seapp_contexts();
nspec = 0;
@@ -654,16 +590,16 @@ oom:
goto out;
}
-
+/* indirection to support pthread_once */
static void seapp_context_init(void)
{
- selinux_android_seapp_context_reload();
+ selinux_android_seapp_context_reload();
}
-static pthread_once_t once = PTHREAD_ONCE_INIT;
+static pthread_once_t seapp_once = PTHREAD_ONCE_INIT;
void selinux_android_seapp_context_init(void) {
- __selinux_once(once, seapp_context_init);
+ __selinux_once(seapp_once, seapp_context_init);
}
/*
@@ -672,8 +608,11 @@ void selinux_android_seapp_context_init(void) {
*/
#define CAT_MAPPING_MAX_ID (0x1<<16)
+/* The kind of request when looking up an seapp_context. */
enum seapp_kind {
+ /* Returns the SELinux type for the app data directory */
SEAPP_TYPE,
+ /* Returns the SELinux type for the app process */
SEAPP_DOMAIN
};
@@ -720,6 +659,7 @@ static int seinfo_parse(char *dest, const char *src, size_t size)
return 0;
}
+/* Sets the categories of ctx based on the level request */
static int set_range_from_level(context_t ctx, enum levelFrom levelFrom, uid_t userid, uid_t appid)
{
char level[255];
@@ -753,6 +693,9 @@ static int set_range_from_level(context_t ctx, enum levelFrom levelFrom, uid_t u
return 0;
}
+/* Search an app (or its data) based on its name and information within the list
+ * of known seapp_contexts. If found, sets the type and categories of ctx and
+ * returns 0. Returns -1 in case of error; -2 for out of memory */
static int seapp_context_lookup(enum seapp_kind kind,
uid_t uid,
bool isSystemServer,
@@ -1043,8 +986,11 @@ static void file_context_init(void)
static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
#define PKGTAB_SIZE 256
+/* Hash table for pkg_info. It uses the package name as key. In case of
+ * collision, the next entry is the private_data attribute */
static struct pkg_info *pkgTab[PKGTAB_SIZE];
+/* Returns a hash based on the package name */
static unsigned int pkghash(const char *pkgname)
{
unsigned int h = 7;
@@ -1054,17 +1000,20 @@ static unsigned int pkghash(const char *pkgname)
return h & (PKGTAB_SIZE - 1);
}
+/* Adds the pkg_info entry to the hash table */
static bool pkg_parse_callback(pkg_info *info, void *userdata) {
(void) userdata;
unsigned int hash = pkghash(info->name);
if (pkgTab[hash])
+ /* Collision. Prepend the entry. */
info->private_data = pkgTab[hash];
pkgTab[hash] = info;
return true;
}
+/* Initialize the pkg_info hash table */
static void package_info_init(void)
{
@@ -1103,6 +1052,7 @@ static void package_info_init(void)
static pthread_once_t pkg_once = PTHREAD_ONCE_INIT;
+/* Returns the pkg_info for a package with a specific name */
struct pkg_info *package_info_lookup(const char *name)
{
struct pkg_info *info;