diff options
author | Inseob Kim <inseob@google.com> | 2023-06-16 10:46:04 +0900 |
---|---|---|
committer | Inseob Kim <inseob@google.com> | 2023-07-25 10:32:35 +0900 |
commit | be36d7106882bf6819c5a14632dac4937377af37 (patch) | |
tree | 3fd72f227a1ede0473665af03f7cea39fbc40fdb | |
parent | c3d1e5a24a92d73697b535bc74c582a5d92f7713 (diff) | |
download | selinux-be36d7106882bf6819c5a14632dac4937377af37.tar.gz |
Check preinstalled app's partition
Bug: 280547417
Test: boot pixel and cuttlefish
Change-Id: I6ed125eff392020ace6686514e0a102dab1fb10f
Merged-In: I6ed125eff392020ace6686514e0a102dab1fb10f
(cherry picked from commit dc9f3516d764207a83dbc4b08284def062ad95fb)
-rw-r--r-- | libselinux/src/android/android.c | 15 | ||||
-rw-r--r-- | libselinux/src/android/android_internal.h | 9 | ||||
-rw-r--r-- | libselinux/src/android/android_seapp.c | 61 |
3 files changed, 82 insertions, 3 deletions
diff --git a/libselinux/src/android/android.c b/libselinux/src/android/android.c index ab0a15f8..4e330599 100644 --- a/libselinux/src/android/android.c +++ b/libselinux/src/android/android.c @@ -94,11 +94,26 @@ size_t find_existing_files( const path_alts_t *path_sets, const char* paths[MAX_CONTEXT_PATHS]) { + return find_existing_files_with_partitions( + path_sets, + paths, + NULL + ); +} + +size_t find_existing_files_with_partitions( + const path_alts_t *path_sets, + const char* paths[MAX_CONTEXT_PATHS], + const char* partitions[MAX_CONTEXT_PATHS]) +{ 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->paths[i][j]; if (file && access(file, R_OK) != -1) { + if (partitions) { + partitions[len] = path_sets->partitions[i]; + } paths[len++] = file; /* Within each set, only the first valid entry is used */ break; diff --git a/libselinux/src/android/android_internal.h b/libselinux/src/android/android_internal.h index 411ce483..4960e729 100644 --- a/libselinux/src/android/android_internal.h +++ b/libselinux/src/android/android_internal.h @@ -17,6 +17,7 @@ extern "C" { #define MAX_ALT_CONTEXT_PATHS 2 typedef struct path_alts { const char *paths[MAX_CONTEXT_PATHS][MAX_ALT_CONTEXT_PATHS]; + const char *partitions[MAX_CONTEXT_PATHS]; } path_alts_t; /* Within each set of files, adds the first file that is accessible to `paths`. @@ -25,6 +26,14 @@ size_t find_existing_files( const path_alts_t *path_sets, const char *paths[MAX_CONTEXT_PATHS]); +/* Within each set of files, adds the first file that is accessible to `paths`. + * Returns the number of accessible files. Also returns the partitions where + * the files exist. */ +size_t find_existing_files_with_partitions( + const path_alts_t *path_sets, + const char *paths[MAX_CONTEXT_PATHS], + const char *partitions[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( diff --git a/libselinux/src/android/android_seapp.c b/libselinux/src/android/android_seapp.c index b903657f..db7bd0bf 100644 --- a/libselinux/src/android/android_seapp.c +++ b/libselinux/src/android/android_seapp.c @@ -48,8 +48,8 @@ static const path_alts_t file_context_paths = { .paths = { } }}; -/* Locations for the seapp_contexts files. For each partition, only the first - * existing entry will be used (for example, if +/* Locations for the seapp_contexts files, and corresponding partitions. 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). */ @@ -77,6 +77,13 @@ static const path_alts_t seapp_context_paths = { .paths = { "/odm/etc/selinux/odm_seapp_contexts", "/odm_seapp_contexts" } +}, .partitions= { + "system", + "system", // regard APEX sepolicy as system + "system_ext", + "product", + "vendor", + "odm" }}; /* Returns a handle for the file contexts backend, initialized with the Android @@ -141,6 +148,7 @@ struct seapp_context { char *type; char *level; enum levelFrom levelFrom; + const char* partition; }; static void free_seapp_context(struct seapp_context *s) @@ -273,8 +281,9 @@ int seapp_context_reload_internal(const path_alts_t *context_paths) size_t i, len, files_len = 0; int ret; const char* seapp_contexts_files[MAX_CONTEXT_PATHS]; + const char* seapp_contexts_partitions[MAX_CONTEXT_PATHS]; - files_len = find_existing_files(context_paths, seapp_contexts_files); + files_len = find_existing_files_with_partitions(context_paths, seapp_contexts_files, seapp_contexts_partitions); /* Reset the current entries */ free_seapp_contexts(); @@ -525,6 +534,7 @@ int seapp_context_reload_internal(const path_alts_t *context_paths) goto err; } + cur->partition = seapp_contexts_partitions[i]; seapp_contexts[nspec] = cur; nspec++; lineno++; @@ -643,6 +653,7 @@ void selinux_android_seapp_context_init(void) { #define APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS_STR ":isSdkSandboxNext" #define EPHEMERAL_APP_STR ":ephemeralapp" #define TARGETSDKVERSION_STR ":targetSdkVersion=" +#define PARTITION_STR ":partition=" #define FROM_RUNAS_STR ":fromRunAs" static int32_t get_app_targetSdkVersion(const char *seinfo) { @@ -664,6 +675,39 @@ static int32_t get_app_targetSdkVersion(const char *seinfo) return 0; /* default to 0 when targetSdkVersion= is not present in seinfo */ } +// returns true if found, false if not found or error +static bool get_partition(const char *seinfo, char partition[], size_t size) +{ + if (size == 0) return false; + + const char *substr = strstr(seinfo, PARTITION_STR); + if (substr == NULL) return false; + + const char *src = substr + strlen(PARTITION_STR); + const char *p = strchr(src, ':'); + size_t len = p ? p - src : strlen(src); + if (len > size - 1) return -1; + strncpy(partition, src, len); + partition[len] = '\0'; + + return true; +} + +static bool is_platform(const char *partition) { + // system, system_ext, product are regarded as "platform", whereas vendor + // and odm are regarded as vendor. + if (strcmp(partition, "system") == 0) return true; + if (strcmp(partition, "system_ext") == 0) return true; + if (strcmp(partition, "product") == 0) return true; + return false; +} + +static bool check_preinstalled_app_partition(const char *spec, const char *app) { + // We forbid system/system_ext/product installed apps from being labeled with vendor sepolicy. + return !is_platform(spec) && is_platform(app); +} + + static int seinfo_parse(char *dest, const char *src, size_t size) { size_t len; @@ -742,6 +786,8 @@ int seapp_context_lookup_internal(enum seapp_kind kind, bool isSdkSandboxNext = false; int32_t targetSdkVersion = 0; bool fromRunAs = false; + bool isPreinstalledApp = false; + char partition[BUFSIZ]; char parsedseinfo[BUFSIZ]; if (seinfo) { @@ -753,6 +799,7 @@ int seapp_context_lookup_internal(enum seapp_kind kind, isSdkSandboxNext = strstr(seinfo, APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS_STR) ? true : false; fromRunAs = strstr(seinfo, FROM_RUNAS_STR) ? true : false; targetSdkVersion = get_app_targetSdkVersion(seinfo); + isPreinstalledApp = get_partition(seinfo, partition, BUFSIZ); if (targetSdkVersion < 0) { selinux_log(SELINUX_ERROR, "%s: Invalid targetSdkVersion passed for app with uid %d, seinfo %s, name %s\n", @@ -849,6 +896,14 @@ int seapp_context_lookup_internal(enum seapp_kind kind, } if (cur->levelFrom != LEVELFROM_NONE) { + if (isPreinstalledApp + && !check_preinstalled_app_partition(cur->partition, partition)) { + // TODO(b/280547417): make this an error after fixing violations + selinux_log(SELINUX_ERROR, + "%s: App %s preinstalled to %s can't be labeled with %s sepolicy", + __FUNCTION__, pkgname, partition, cur->partition); + } + int res = set_range_from_level(ctx, cur->levelFrom, userid, appid); if (res != 0) { return res; |