Fix /mnt/user/<userid> permission bits

Previously, when mounting a FUSE volume, the permission bits for
/mnt/user/<userid> were very strict, 700 which was good, however this
value was ignored because it was overriden in zygote to 755. In fact
if it wasn't ignored, apps wouldn't have had access to /sdcard becase
they would lack the directory 'execute' bit for /mnt/user/<userid>
needed while looking up /mnt/user/<userid>/emulated

Now we set it to a strict enough value, 710 that only allows apps
running under the same user id to lookup /mnt/user/<userid>.
This ensures that user 10 cannot access /mnt/user/0.

A special case is added for /mnt/user/0 for shell since it is not in
the 'everybody' group and would otherwise not be able to 'adb shell ls
/sdcard'

Bug: 135341433
Test: atest -c android.appsecurity.cts.ExternalStorageHostTest#testSecondaryUsersInaccessible

Change-Id: Ia427d1b69c7140254ae3459b98e51531d8322f1a
This commit is contained in:
Zim 2020-01-05 02:11:47 +00:00
parent e3102990ca
commit 06b0cafb29

View file

@ -1021,7 +1021,13 @@ status_t MountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str())); StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str()));
// Create directories. // Create directories.
auto result = PrepareDir(pre_fuse_path, 0700, AID_ROOT, AID_ROOT); // Shell is neither AID_ROOT nor AID_EVERYBODY. Since it equally needs 'execute' access to
// /mnt/user/0 to 'adb shell ls /sdcard' for instance, we set the uid bit of /mnt/user/0 to
// AID_SHELL. This gives shell access along with apps running as group everybody (user 0 apps)
// These bits should be consistent with what is set in zygote in
// com_android_internal_os_Zygote#MountEmulatedStorage on volume bind mount during app fork
auto result = PrepareDir(pre_fuse_path, 0710, user_id ? AID_ROOT : AID_SHELL,
multiuser_get_uid(user_id, AID_EVERYBODY));
if (result != android::OK) { if (result != android::OK) {
PLOG(ERROR) << "Failed to prepare directory " << pre_fuse_path; PLOG(ERROR) << "Failed to prepare directory " << pre_fuse_path;
return -1; return -1;