| #include "android_common.h" |
| |
| #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_split[] = { |
| { SELABEL_OPT_PATH, "/system/etc/selinux/plat_service_contexts" }, |
| { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_service_contexts" } |
| }; |
| |
| static const struct selinux_opt seopts_service_rootfs[] = { |
| { SELABEL_OPT_PATH, "/plat_service_contexts" }, |
| { SELABEL_OPT_PATH, "/nonplat_service_contexts" } |
| }; |
| |
| static const struct selinux_opt seopts_hwservice_split[] = { |
| { SELABEL_OPT_PATH, "/system/etc/selinux/plat_hwservice_contexts" }, |
| { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_hwservice_contexts" } |
| }; |
| |
| static const struct selinux_opt seopts_hwservice_rootfs[] = { |
| { SELABEL_OPT_PATH, "/plat_hwservice_contexts" }, |
| { SELABEL_OPT_PATH, "/nonplat_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" }; |
| |
| struct selabel_handle* selinux_android_service_open_context_handle(const struct selinux_opt* seopts_service, |
| unsigned nopts) |
| { |
| struct selabel_handle* sehandle; |
| |
| sehandle = selabel_open(SELABEL_CTX_ANDROID_SERVICE, |
| seopts_service, nopts); |
| |
| 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* selinux_android_service_context_handle(void) |
| { |
| const struct selinux_opt* seopts_service; |
| |
| // Prefer files from /system & /vendor, fall back to files from / |
| if (access(seopts_service_split[0].value, R_OK) != -1) { |
| seopts_service = seopts_service_split; |
| } else { |
| seopts_service = seopts_service_rootfs; |
| } |
| |
| // TODO(b/36866029) full treble devices can't load non-plat |
| return selinux_android_service_open_context_handle(seopts_service, 2); |
| } |
| |
| struct selabel_handle* selinux_android_hw_service_context_handle(void) |
| { |
| const struct selinux_opt* seopts_service; |
| if (access(seopts_hwservice_split[0].value, R_OK) != -1) { |
| seopts_service = seopts_hwservice_split; |
| } else { |
| seopts_service = seopts_hwservice_rootfs; |
| } |
| |
| return selinux_android_service_open_context_handle(seopts_service, 2); |
| } |
| |
| 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); |
| } |
| |
| int selinux_log_callback(int type, const char *fmt, ...) |
| { |
| va_list ap; |
| int priority; |
| char *strp; |
| |
| switch(type) { |
| case SELINUX_WARNING: |
| priority = ANDROID_LOG_WARN; |
| break; |
| case SELINUX_INFO: |
| priority = ANDROID_LOG_INFO; |
| break; |
| default: |
| priority = ANDROID_LOG_ERROR; |
| break; |
| } |
| |
| va_start(ap, fmt); |
| if (vasprintf(&strp, fmt, ap) != -1) { |
| LOG_PRI(priority, "SELinux", "%s", strp); |
| LOG_EVENT_STRING(AUDITD_LOG_TAG, strp); |
| free(strp); |
| } |
| va_end(ap); |
| return 0; |
| } |