mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 03:21:08 +00:00
fix(storage): Windows installs on a natively mounted card no longer ask for an administrator (#2100)
* fix(storage): Windows installs on a natively mounted card no longer ask for an administrator Cards mounted directly as FAT, exFAT or NTFS were not treated as Android storage, so wineserver reported an Anonymous owner and refused permission changes. Its chmod on these volumes also no longer fails the request. * fix(storage): keep NTFS owners and the chmod error
This commit is contained in:
1 parent
a9d2d09e64
commit
b9dbd006be
2 files changed
+61
-7
No files matched your search
@@ -1,4 +1,5 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
@@ -8,6 +9,8 @@
|
||||
|
||||
#define FUSE_MAGIC 0x65735546
|
||||
#define SDCARDFS_MAGIC 0x5dca2df5
|
||||
#define FAT_MAGIC 0x4d44
|
||||
#define EXFAT_MAGIC 0x2011bab0
|
||||
|
||||
static int is_wineserver(void) {
|
||||
static int cached = -1;
|
||||
@@ -27,15 +30,42 @@ static int is_wineserver(void) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
static int has_no_unix_owner(int fd) {
|
||||
struct statfs fs;
|
||||
|
||||
if (fstatfs(fd, &fs) != 0) return 0;
|
||||
return fs.f_type == FUSE_MAGIC || fs.f_type == SDCARDFS_MAGIC || fs.f_type == FAT_MAGIC ||
|
||||
(unsigned int)fs.f_type == EXFAT_MAGIC;
|
||||
}
|
||||
|
||||
__attribute__((visibility("hidden")))
|
||||
void bl_storage_owner(int fd, struct stat *st) {
|
||||
struct statfs fs;
|
||||
int saved = errno;
|
||||
uid_t uid;
|
||||
|
||||
if (st != NULL && is_wineserver()) {
|
||||
uid = getuid();
|
||||
if (st->st_uid != uid && fstatfs(fd, &fs) == 0 && (fs.f_type == FUSE_MAGIC || fs.f_type == SDCARDFS_MAGIC)) st->st_uid = uid;
|
||||
if (st->st_uid != uid && has_no_unix_owner(fd)) st->st_uid = uid;
|
||||
}
|
||||
errno = saved;
|
||||
}
|
||||
|
||||
int fchmod(int fd, mode_t mode) {
|
||||
static int (*next_fchmod)(int, mode_t);
|
||||
int saved = errno, result;
|
||||
|
||||
if (next_fchmod == NULL) next_fchmod = dlsym(RTLD_NEXT, "fchmod");
|
||||
if (next_fchmod == NULL) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
result = next_fchmod(fd, mode);
|
||||
if (result != 0 && errno == EPERM && is_wineserver()) {
|
||||
if (has_no_unix_owner(fd)) {
|
||||
errno = saved;
|
||||
return 0;
|
||||
}
|
||||
errno = EPERM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -11,7 +11,9 @@ FAKE = r"""
|
||||
#define _GNU_SOURCE
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
@@ -29,8 +31,22 @@ int fstatfs(int fd, struct statfs *out) {
|
||||
if (result == 0 && strstr(path, "/fuse/")) out->f_type = 0x65735546;
|
||||
if (result == 0 && strstr(path, "/sdcardfs/")) out->f_type = 0x5dca2df5;
|
||||
if (result == 0 && strstr(path, "/ext4/")) out->f_type = 0xef53;
|
||||
if (result == 0 && strstr(path, "/fat/")) out->f_type = 0x4d44;
|
||||
if (result == 0 && strstr(path, "/exfat/")) out->f_type = 0x2011bab0;
|
||||
if (result == 0 && strstr(path, "/ntfs/")) out->f_type = 0x5346544e;
|
||||
if (strstr(path, "/broken/")) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int fchmod(int fd, mode_t mode) {
|
||||
(void)fd;
|
||||
(void)mode;
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
"""
|
||||
|
||||
PROGRAM = r"""
|
||||
@@ -50,6 +66,8 @@ int main(int argc, char **argv) {
|
||||
errno = 1234;
|
||||
int result = fstat(fd, &st);
|
||||
printf("%s %d\n", st.st_uid == real ? "real" : st.st_uid == real + 1 ? "user" : "other", result == 0 && errno == 1234);
|
||||
errno = 0;
|
||||
printf("%s\n", fchmod(fd, 0755) == 0 ? "chmod-ok" : errno == EPERM ? "chmod-denied" : "chmod-other");
|
||||
close(fd);
|
||||
}
|
||||
return 0;
|
||||
@@ -76,7 +94,7 @@ class StorageOwnerPreloadTest(unittest.TestCase):
|
||||
subprocess.run(["cc", "-O2", "-o", str(cls.wineserver), str(build / "program.c")], check=True)
|
||||
cls.other = build / "wine64-preloader"
|
||||
shutil.copy(cls.wineserver, cls.other)
|
||||
for kind in ("fuse", "sdcardfs", "ext4"):
|
||||
for kind in ("fuse", "sdcardfs", "ext4", "fat", "exfat", "ntfs", "broken"):
|
||||
(cls.dir / kind).mkdir()
|
||||
(cls.dir / kind / "file").write_text("x")
|
||||
|
||||
@@ -85,20 +103,26 @@ class StorageOwnerPreloadTest(unittest.TestCase):
|
||||
cls.temp.cleanup()
|
||||
|
||||
def owners(self, program, *kinds):
|
||||
env = dict(os.environ, LD_PRELOAD="%s:%s" % (self.fake, self.preload))
|
||||
env = dict(os.environ, LD_PRELOAD="%s:%s" % (self.preload, self.fake))
|
||||
env.pop("BL_STORAGE_DIAGNOSTICS", None)
|
||||
paths = [str(self.dir / kind / "file") for kind in kinds]
|
||||
result = subprocess.run([str(program)] + paths, env=env, capture_output=True, text=True, check=True)
|
||||
return result.stdout.split()
|
||||
|
||||
def test_wineserver_owns_what_is_on_android_storage(self):
|
||||
self.assertEqual(["user", "1", "user", "1"], self.owners(self.wineserver, "fuse", "sdcardfs"))
|
||||
self.assertEqual(["user", "1", "chmod-ok"] * 2, self.owners(self.wineserver, "fuse", "sdcardfs"))
|
||||
|
||||
def test_wineserver_owns_what_is_on_a_native_card(self):
|
||||
self.assertEqual(["user", "1", "chmod-ok"] * 2, self.owners(self.wineserver, "fat", "exfat"))
|
||||
|
||||
def test_other_filesystems_keep_their_owner(self):
|
||||
self.assertEqual(["real", "1"], self.owners(self.wineserver, "ext4"))
|
||||
self.assertEqual(["real", "1", "chmod-denied"] * 2, self.owners(self.wineserver, "ext4", "ntfs"))
|
||||
|
||||
def test_chmod_keeps_its_error_when_the_volume_is_unknown(self):
|
||||
self.assertEqual(["real", "1", "chmod-denied"], self.owners(self.wineserver, "broken"))
|
||||
|
||||
def test_other_programs_see_the_real_owner(self):
|
||||
self.assertEqual(["real", "1", "real", "1"], self.owners(self.other, "fuse", "sdcardfs"))
|
||||
self.assertEqual(["real", "1", "chmod-denied"] * 2, self.owners(self.other, "fuse", "sdcardfs"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in new issue
Block a user