Ignore error for fchown if sgid bit is set for parent directory
When a file is transferred to device, fchown will be called to set
gid/uid. If sgid permission is set, then gid will be set automatically,
in this case ignore return code from fchown.
Bug: 192445890
Test: Manual, confirm permissions:
adb shell ls -la /storage/emulated/0/Android/data/com.android.vending/
drwxrws--- 3 u0_a207 ext_data_rw 3452 2021-06-29 14:49 .
push file to filesystem
adb push foo /storage/emulated/0/Android/data/com.android.vending/files
Change-Id: I9719bf7d2bb6dc473c826114067288ceecb52755
(cherry picked from commit e79769d3b6e535b6774528438d8c5514320b0279)
diff --git a/daemon/file_sync_service.cpp b/daemon/file_sync_service.cpp
index 513b8dd..b59da97 100644
--- a/daemon/file_sync_service.cpp
+++ b/daemon/file_sync_service.cpp
@@ -65,6 +65,7 @@
using android::base::borrowed_fd;
using android::base::Dirname;
+using android::base::Realpath;
using android::base::StringPrintf;
static bool should_use_fs_config(const std::string& path) {
@@ -369,8 +370,16 @@
goto fail;
} else {
if (fchown(fd.get(), uid, gid) == -1) {
- SendSyncFailErrno(s, "fchown failed");
- goto fail;
+ struct stat st;
+ std::string real_path;
+
+ // Only return failure if parent directory does not have S_ISGID bit set,
+ // if S_ISGID is set then file will inherit groupid from directory
+ if (!Realpath(path, &real_path) || lstat(Dirname(real_path).c_str(), &st) == -1 ||
+ (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) == 0)) {
+ SendSyncFailErrno(s, "fchown failed");
+ goto fail;
+ }
}
#if defined(__ANDROID__)