Set default ACL on application-specific directories.
On devices without sdcardfs, application-specific directories have a particular GID that ensure some privileged daemons (like installers) are able to write to them. Android applications however run with a umask of 0077, which means that any subdirectory they create within their app-specific directory has mode 700, which in turn prevents things like DownloadManager from working, since it can be asked to download into a subdir of the app's private storage. To prevent this from happening, set a default 770 ACL on the top-level app-specific directory (eg, /data/media/0/Android/data/com.foo); the effect of that default ACL is that all directories that are created within these directories automatically get a 770 mask, regardless of the umask that the process has. Bug: 146419093 Test: atest FuseDaemonHostTest on cf_x86 (without sdcardfs) Change-Id: I3178694e6d25ce3d04a0918ac66862f644635704
This commit is contained in:
parent
04bb17f112
commit
879fa8015d
1 changed files with 53 additions and 1 deletions
54
Utils.cpp
54
Utils.cpp
|
@ -33,16 +33,18 @@
|
|||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
#include <linux/posix_acl_xattr.h>
|
||||
#include <mntent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <list>
|
||||
|
@ -122,6 +124,45 @@ status_t DestroyDeviceNode(const std::string& path) {
|
|||
}
|
||||
}
|
||||
|
||||
// Sets a default ACL where the owner and group can read/write/execute.
|
||||
// Other users aren't allowed anything.
|
||||
int SetDefault770Acl(const std::string& path, uid_t uid, gid_t gid) {
|
||||
if (IsFilesystemSupported("sdcardfs")) {
|
||||
// sdcardfs magically takes care of this
|
||||
return OK;
|
||||
}
|
||||
|
||||
static constexpr size_t size =
|
||||
sizeof(posix_acl_xattr_header) + 3 * sizeof(posix_acl_xattr_entry);
|
||||
auto buf = std::make_unique<uint8_t[]>(size);
|
||||
|
||||
posix_acl_xattr_header* acl_header = reinterpret_cast<posix_acl_xattr_header*>(buf.get());
|
||||
acl_header->a_version = POSIX_ACL_XATTR_VERSION;
|
||||
|
||||
posix_acl_xattr_entry* entry =
|
||||
reinterpret_cast<posix_acl_xattr_entry*>(buf.get() + sizeof(posix_acl_xattr_header));
|
||||
|
||||
entry[0].e_tag = ACL_USER_OBJ;
|
||||
entry[0].e_perm = ACL_READ | ACL_WRITE | ACL_EXECUTE;
|
||||
entry[0].e_id = uid;
|
||||
|
||||
entry[1].e_tag = ACL_GROUP_OBJ;
|
||||
entry[1].e_perm = ACL_READ | ACL_WRITE | ACL_EXECUTE;
|
||||
entry[1].e_id = gid;
|
||||
|
||||
entry[2].e_tag = ACL_OTHER;
|
||||
entry[2].e_perm = 0;
|
||||
entry[2].e_id = 0;
|
||||
|
||||
int ret = setxattr(path.c_str(), XATTR_NAME_POSIX_ACL_DEFAULT, acl_header, size, 0);
|
||||
|
||||
if (ret != 0) {
|
||||
PLOG(ERROR) << "Failed to set default ACL on " << path;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SetQuotaInherit(const std::string& path) {
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -232,6 +273,17 @@ int PrepareAppDirFromRoot(std::string path, int appUid) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// Set the default ACL, to ensure that even if applications run with a
|
||||
// umask of 0077, new directories within these directories will allow the
|
||||
// GID specified here to write; this is necessary for apps like installers
|
||||
// and MTP, that require access here.
|
||||
//
|
||||
// See man (5) acl for more details.
|
||||
ret = SetDefault770Acl(package_path, uid, gid);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Next, create the directory within the package, if needed
|
||||
if (match.size() <= 4) {
|
||||
return OK;
|
||||
|
|
Loading…
Reference in a new issue