adb: Preserve the original mount flags when remounting
This change preserves any additional flags mount flags (e.g. MS_NODEV) that any of the mounts would have. This avoids unnecessarily opening up permissions, and also allows kernels that have additional restrictions about what mount flags can be used to be happy with the remounts. Bug: 111618714 Test: `adb remount` works in Chrome OS Test: `adb remount` works in sailfish_aosp Change-Id: I20d9f2feaf3a47b93bfcdfb4164ee61546ec0b68
This commit is contained in:
parent
54f40303d5
commit
c20c85008d
1 changed files with 23 additions and 2 deletions
|
@ -26,6 +26,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -145,6 +146,17 @@ static bool can_unshare_blocks(int fd, const char* dev) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static unsigned long get_mount_flags(int fd, const char* dir) {
|
||||
struct statvfs st_vfs;
|
||||
if (statvfs(dir, &st_vfs) == -1) {
|
||||
// Even though we could not get the original mount flags, assume that
|
||||
// the mount was originally read-only.
|
||||
WriteFdFmt(fd, "statvfs of the %s mount failed: %s.\n", dir, strerror(errno));
|
||||
return MS_RDONLY;
|
||||
}
|
||||
return st_vfs.f_flag;
|
||||
}
|
||||
|
||||
static bool remount_partition(int fd, const char* dir) {
|
||||
if (!directory_exists(dir)) {
|
||||
return true;
|
||||
|
@ -163,14 +175,23 @@ static bool remount_partition(int fd, const char* dir) {
|
|||
dir, dev.c_str(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if (mount(dev.c_str(), dir, "none", MS_REMOUNT | MS_BIND, nullptr) == -1) {
|
||||
|
||||
unsigned long remount_flags = get_mount_flags(fd, dir);
|
||||
if ((remount_flags & MS_RDONLY) == 0) {
|
||||
// Mount is already writable.
|
||||
return true;
|
||||
}
|
||||
remount_flags &= ~MS_RDONLY;
|
||||
remount_flags |= MS_REMOUNT;
|
||||
|
||||
if (mount(dev.c_str(), dir, "none", remount_flags | MS_BIND, nullptr) == -1) {
|
||||
// This is useful for cases where the superblock is already marked as
|
||||
// read-write, but the mount itself is read-only, such as containers
|
||||
// where the remount with just MS_REMOUNT is forbidden by the kernel.
|
||||
WriteFdFmt(fd, "remount of the %s mount failed: %s.\n", dir, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) {
|
||||
if (mount(dev.c_str(), dir, "none", remount_flags, nullptr) == -1) {
|
||||
WriteFdFmt(fd, "remount of the %s superblock failed: %s\n", dir, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue