In a Linux user namespace, as non-root, I bind mount /tmp/foo to itself. This succeeds.
Then, I try to remount /tmp/foo to be read-only. If /tmp is mounted with nosuid or nodev, then the remount fails. Otherwise, the remount succeeds.
Is there some reason why nosuid and/or nodev prevent the remount from succeeding? Is this behavior documented somewhere? I'm puzzled, as I would expect the bind mount and remount to either both succeed, or both fail.
Here is the code to reproduce the bind mount and remount:
#define _GNU_SOURCE /* unshare */ #include <errno.h> /* errno */ #include <sched.h> /* unshare */ #include <stdio.h> /* printf */ #include <string.h> /* strerror */ #include <sys/mount.h> /* mount */ #include <unistd.h> /* getuid */ int main() { printf ( "getuid %d\n", getuid() ); int rv = unshare ( CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUSER ); printf ( "unshare %2d %s\n", rv, strerror(errno) ); rv = mount ( "/tmp/foo", "/tmp/foo", 0, MS_BIND | MS_REC, 0 ), printf ( "mount %2d %s\n", rv, strerror(errno) ); rv = mount ( "/tmp/foo", "/tmp/foo", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0 ), printf ( "remount %2d %s\n", rv, strerror(errno) ); return 0; } Sample output:
$ mkdir -p /tmp/foo $ mount | grep /tmp tmpfs on /tmp type tmpfs (rw,nosuid,nodev,relatime,inode64) $ gcc test.c && ./a.out getuid 1000 unshare 0 No error information mount 0 No error information remount -1 Operation not permitted $ uname -a Linux hostname 5.12.12_1 #1 SMP 1624132767 x86_64 GNU/Linux Whereas, if /tmp is mounted with neither nosuid nor nodev, then the bind mount and the remount will both succeed, as follows:
$ mkdir -p /tmp/foo $ mount | grep /tmp tmpfs on /tmp type tmpfs (rw,relatime,inode64) $ gcc test.c && ./a.out getuid 1000 unshare 0 No error information mount 0 No error information remount 0 No error information