diff options
author | Inseob Kim <inseob@google.com> | 2023-07-26 02:31:24 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-07-26 02:31:24 +0000 |
commit | 5ad7961fff24d5804c0ed3391bd37cb86f0f7004 (patch) | |
tree | 3fd72f227a1ede0473665af03f7cea39fbc40fdb | |
parent | 0a8954744d327ab73dc47a4eff1d2f14755d0e3e (diff) | |
parent | 44b95e92a75d7b96322dd48cff4804a6bfb3f9cc (diff) | |
download | selinux-5ad7961fff24d5804c0ed3391bd37cb86f0f7004.tar.gz |
Check preinstalled app's partition am: be36d71068 am: 44b95e92a7
Original change: https://android-review.googlesource.com/c/platform/external/selinux/+/2670896
Change-Id: I7f2e49ed1c0054ae27dae1589f4b2d7706cd2430
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-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; |