Zygote: relabel to either system_userdir_file or system_data_file

To hide other apps' data directories, zygote mounts tmpfs instances over
various directories such as /data/user, then bind-mounts in the needed
app directories.  Files in tmpfs get the SELinux label "tmpfs" by
default.  After creating them, zygote relabels some of these "tmpfs"
files to their normal labels; however, in every case the desired label
was "u:object_r:system_data_file:s0", so zygote just copied the label of
/data/user_de which happened to have this same label.

With https://r.android.com/2078213, the /data/user_de directory, but not
its subdirectories, will start being labeled as
"u:object_r:system_userdir_file:s0".  This would break the
above-mentioned logic, as it would start assigning system_userdir_file
to files that should be system_data_file.  Therefore, update it to
assign the appropriate type of [system_userdir_file, system_data_file].

Note that alternatively, it seems that we could just always use
system_data_file, or just remove this relabeling code entirely since the
sepolicy contains 'allow domain tmpfs:dir search' anyway.  But as long
as zygote is trying to set the normal labels, it should do it correctly.

Test: Tested together with the sepolicy change
      https://r.android.com/2078213; see there for testing notes.
Bug: 156305599
Change-Id: I325aa873cf216e33924d0508100fcc755f265cf2
This commit is contained in:
Eric Biggers
2022-04-29 05:26:18 +00:00
parent 3d9c19f2fd
commit 5454379320

View File

@@ -1153,8 +1153,8 @@ static void relabelDir(const char* path, const char* context, fail_fn_t fail_fn)
}
}
// Relabel all directories under a path non-recursively.
static void relabelAllDirs(const char* path, const char* context, fail_fn_t fail_fn) {
// Relabel the subdirectories and symlinks in the given directory, non-recursively.
static void relabelSubdirs(const char* path, const char* context, fail_fn_t fail_fn) {
DIR* dir = opendir(path);
if (dir == nullptr) {
fail_fn(CREATE_ERROR("Failed to opendir %s", path));
@@ -1231,11 +1231,19 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
snprintf(internalDePath, PATH_MAX, "/data/user_de");
snprintf(externalPrivateMountPath, PATH_MAX, "/mnt/expand");
char* dataDataContext = nullptr;
if (getfilecon(internalDePath, &dataDataContext) < 0) {
fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", internalDePath,
// Get the "u:object_r:system_userdir_file:s0" security context. This can be
// gotten from several different places; we use /data/user.
char* dataUserdirContext = nullptr;
if (getfilecon(internalCePath, &dataUserdirContext) < 0) {
fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", internalCePath,
strerror(errno)));
}
// Get the "u:object_r:system_data_file:s0" security context. This can be
// gotten from several different places; we use /data/misc.
char* dataFileContext = nullptr;
if (getfilecon("/data/misc", &dataFileContext) < 0) {
fail_fn(CREATE_ERROR("Unable to getfilecon on /data/misc %s", strerror(errno)));
}
MountAppDataTmpFs(internalLegacyCePath, fail_fn);
MountAppDataTmpFs(internalCePath, fail_fn);
@@ -1330,19 +1338,19 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
// the file operations on tmpfs. If we set the label when we mount
// tmpfs, SELinux will not happy as we are changing system_data_files.
// Relabel dir under /data/user, including /data/user/0
relabelAllDirs(internalCePath, dataDataContext, fail_fn);
relabelSubdirs(internalCePath, dataFileContext, fail_fn);
// Relabel /data/user
relabelDir(internalCePath, dataDataContext, fail_fn);
relabelDir(internalCePath, dataUserdirContext, fail_fn);
// Relabel /data/data
relabelDir(internalLegacyCePath, dataDataContext, fail_fn);
relabelDir(internalLegacyCePath, dataFileContext, fail_fn);
// Relabel dir under /data/user_de
relabelAllDirs(internalDePath, dataDataContext, fail_fn);
// Relabel subdirectories of /data/user_de
relabelSubdirs(internalDePath, dataFileContext, fail_fn);
// Relabel /data/user_de
relabelDir(internalDePath, dataDataContext, fail_fn);
relabelDir(internalDePath, dataUserdirContext, fail_fn);
// Relabel CE and DE dirs under /mnt/expand
dir = opendir(externalPrivateMountPath);
@@ -1355,14 +1363,15 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
auto cePath = StringPrintf("%s/user", volPath.c_str());
auto dePath = StringPrintf("%s/user_de", volPath.c_str());
relabelAllDirs(cePath.c_str(), dataDataContext, fail_fn);
relabelDir(cePath.c_str(), dataDataContext, fail_fn);
relabelAllDirs(dePath.c_str(), dataDataContext, fail_fn);
relabelDir(dePath.c_str(), dataDataContext, fail_fn);
relabelSubdirs(cePath.c_str(), dataFileContext, fail_fn);
relabelDir(cePath.c_str(), dataUserdirContext, fail_fn);
relabelSubdirs(dePath.c_str(), dataFileContext, fail_fn);
relabelDir(dePath.c_str(), dataUserdirContext, fail_fn);
}
closedir(dir);
freecon(dataDataContext);
freecon(dataUserdirContext);
freecon(dataFileContext);
}
static void insertPackagesToMergedList(JNIEnv* env,