minijail: Copy the mount flags from source when bind-mounting
This change makes all bindmounts copy the mount flags from the source
path if a remount is issued. It also fixes a bug where ro mounts could
never become rw.
Bug: 111325710
Test: make tests
Test: Repro scenario in https://crbug.com/862171
Change-Id: Ia87ea2933f1ab1b8a9fd2efd6f832c51a5a8f7a2
diff --git a/system.c b/system.c
index 5e2a6f6..434980a 100644
--- a/system.c
+++ b/system.c
@@ -17,6 +17,7 @@
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <unistd.h>
#include "util.h"
@@ -268,7 +269,7 @@
* Creates it if needed and possible.
*/
int setup_mount_destination(const char *source, const char *dest, uid_t uid,
- uid_t gid, bool bind)
+ uid_t gid, bool bind, unsigned long *mnt_flags)
{
int rc;
struct stat st_buf;
@@ -309,6 +310,20 @@
domkdir = S_ISDIR(st_buf.st_mode) ||
(!bind && (S_ISBLK(st_buf.st_mode) ||
S_ISCHR(st_buf.st_mode)));
+
+ /* If bind mounting, also grab the mount flags of the source. */
+ if (bind && mnt_flags) {
+ struct statvfs stvfs_buf;
+ rc = statvfs(source, &stvfs_buf);
+ if (rc) {
+ rc = errno;
+ pwarn(
+ "failed to look up mount flags: source=%s",
+ source);
+ return -rc;
+ }
+ *mnt_flags = stvfs_buf.f_flag;
+ }
} else {
/* The source is a relative path -- assume it's a pseudo fs. */