mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 12:38:12 +00:00
Kernel+Userland: Support remounting filesystems :^)
This makes it possible to change flags of a mount after the fact, with the caveats outlined in the man page.
This commit is contained in:
parent
d395b93b15
commit
3847d00727
8 changed files with 58 additions and 0 deletions
|
@ -34,6 +34,7 @@ The following `flags` are supported:
|
||||||
* `MS_NOSUID`: Ignore set-user-id bits on executables from this file system.
|
* `MS_NOSUID`: Ignore set-user-id bits on executables from this file system.
|
||||||
* `MS_BIND`: Perform a bind-mount (see below).
|
* `MS_BIND`: Perform a bind-mount (see below).
|
||||||
* `MS_RDONLY`: Mount the filesystem read-only.
|
* `MS_RDONLY`: Mount the filesystem read-only.
|
||||||
|
* `MS_REMOUNT`: Remount an already mounted filesystem (see below).
|
||||||
|
|
||||||
These flags can be used as a security measure to limit the possible abuses of the newly
|
These flags can be used as a security measure to limit the possible abuses of the newly
|
||||||
mounted file system.
|
mounted file system.
|
||||||
|
@ -45,6 +46,36 @@ performed instead. In this case, the file or directory specified by `source_fd`
|
||||||
is overlayed over `target` — the target appears to be replaced by a copy of the
|
is overlayed over `target` — the target appears to be replaced by a copy of the
|
||||||
source. This can be used as an alternative to symlinks or hardlinks.
|
source. This can be used as an alternative to symlinks or hardlinks.
|
||||||
|
|
||||||
|
Each bind mount has its own set of flags, independent of the others or the
|
||||||
|
original file system. It is possible to bind-mount a file or directory over
|
||||||
|
itself, which may be useful for changing mount flags for a part of a filesystem.
|
||||||
|
|
||||||
|
### Remounting
|
||||||
|
|
||||||
|
If `MS_REMOUNT` is specified in `flags`, `source_fd` and `fs_type` are ignored,
|
||||||
|
and a remount is performed instead. `target` must point to an existing mount
|
||||||
|
point. The mount flags for that mount point are reset to `flags` (except the
|
||||||
|
`MS_REMOUNT` flag itself, which is stripped from the value).
|
||||||
|
|
||||||
|
Note that remounting a file system will only affect future operations with the
|
||||||
|
file system, not any already opened files. For example, if you open a directory
|
||||||
|
on a filesystem that's mounted with `MS_NODEV`, then remount the filesystem to
|
||||||
|
allow opening devices, attempts to open a devices relative to the directory file
|
||||||
|
descriptor (such as by using `openat()`) will still fail.
|
||||||
|
|
||||||
|
In particular, current working directory and root directory of any already
|
||||||
|
running processes behave the same way, and don't automatically "pick up" changes
|
||||||
|
in mount flags of the underlying file system. To "refresh" the working directory
|
||||||
|
to use the new mount flags after remounting a filesystem, a process can call
|
||||||
|
`chdir()` with the path to the same directory.
|
||||||
|
|
||||||
|
Similarly, to change the mount flags used by the root directory, a process can
|
||||||
|
call [`chroot_with_mount_flags`(2)](chroot.md), specifying a single slash (`/`)
|
||||||
|
as the path along with the desired flags. While is's possible to remount the
|
||||||
|
root filesystem using `MS_REMOUNT`, it would only have a noticeable effect if
|
||||||
|
the kernel was to launch more userspace processes directly, the way it does
|
||||||
|
launch the initial userspace process.
|
||||||
|
|
||||||
## Errors
|
## Errors
|
||||||
|
|
||||||
* `EFAULT`: The `fs_type` or `target` are invalid strings.
|
* `EFAULT`: The `fs_type` or `target` are invalid strings.
|
||||||
|
|
|
@ -91,6 +91,20 @@ KResult VFS::bind_mount(Custody& source, Custody& mount_point, int flags)
|
||||||
return KSuccess;
|
return KSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KResult VFS::remount(Custody& mount_point, int new_flags)
|
||||||
|
{
|
||||||
|
LOCKER(m_lock);
|
||||||
|
|
||||||
|
dbg() << "VFS: Remounting " << mount_point.absolute_path();
|
||||||
|
|
||||||
|
Mount* mount = find_mount_for_guest(mount_point.inode().identifier());
|
||||||
|
if (!mount)
|
||||||
|
return KResult(-ENODEV);
|
||||||
|
|
||||||
|
mount->set_flags(new_flags);
|
||||||
|
return KSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
KResult VFS::unmount(InodeIdentifier guest_inode_id)
|
KResult VFS::unmount(InodeIdentifier guest_inode_id)
|
||||||
{
|
{
|
||||||
LOCKER(m_lock);
|
LOCKER(m_lock);
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
String absolute_path() const;
|
String absolute_path() const;
|
||||||
|
|
||||||
int flags() const { return m_flags; }
|
int flags() const { return m_flags; }
|
||||||
|
void set_flags(int flags) { m_flags = flags; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
InodeIdentifier m_host;
|
InodeIdentifier m_host;
|
||||||
|
@ -83,6 +84,7 @@ public:
|
||||||
bool mount_root(FS&);
|
bool mount_root(FS&);
|
||||||
KResult mount(FS&, Custody& mount_point, int flags);
|
KResult mount(FS&, Custody& mount_point, int flags);
|
||||||
KResult bind_mount(Custody& source, Custody& mount_point, int flags);
|
KResult bind_mount(Custody& source, Custody& mount_point, int flags);
|
||||||
|
KResult remount(Custody& mount_point, int new_flags);
|
||||||
KResult unmount(InodeIdentifier guest_inode_id);
|
KResult unmount(InodeIdentifier guest_inode_id);
|
||||||
|
|
||||||
KResultOr<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> = {});
|
KResultOr<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> = {});
|
||||||
|
|
|
@ -4103,6 +4103,11 @@ int Process::sys$mount(const Syscall::SC_mount_params* user_params)
|
||||||
|
|
||||||
auto& target_custody = custody_or_error.value();
|
auto& target_custody = custody_or_error.value();
|
||||||
|
|
||||||
|
if (params.flags & MS_REMOUNT) {
|
||||||
|
// We're not creating a new mount, we're updating an existing one!
|
||||||
|
return VFS::the().remount(target_custody, params.flags & ~MS_REMOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
if (params.flags & MS_BIND) {
|
if (params.flags & MS_BIND) {
|
||||||
// We're doing a bind mount.
|
// We're doing a bind mount.
|
||||||
if (description.is_null())
|
if (description.is_null())
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#define MS_NOSUID (1 << 2)
|
#define MS_NOSUID (1 << 2)
|
||||||
#define MS_BIND (1 << 3)
|
#define MS_BIND (1 << 3)
|
||||||
#define MS_RDONLY (1 << 4)
|
#define MS_RDONLY (1 << 4)
|
||||||
|
#define MS_REMOUNT (1 << 5)
|
||||||
|
|
||||||
#define PERF_EVENT_MALLOC 1
|
#define PERF_EVENT_MALLOC 1
|
||||||
#define PERF_EVENT_FREE 2
|
#define PERF_EVENT_FREE 2
|
||||||
|
|
|
@ -154,6 +154,7 @@ enum {
|
||||||
#define MS_NOSUID (1 << 2)
|
#define MS_NOSUID (1 << 2)
|
||||||
#define MS_BIND (1 << 3)
|
#define MS_BIND (1 << 3)
|
||||||
#define MS_RDONLY (1 << 4)
|
#define MS_RDONLY (1 << 4)
|
||||||
|
#define MS_REMOUNT (1 << 5)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We aren't fully compliant (don't support policies, and don't have a wide
|
* We aren't fully compliant (don't support policies, and don't have a wide
|
||||||
|
|
|
@ -59,6 +59,8 @@ int main(int argc, char** argv)
|
||||||
flags |= MS_NOSUID;
|
flags |= MS_NOSUID;
|
||||||
else if (part == "ro")
|
else if (part == "ro")
|
||||||
flags |= MS_RDONLY;
|
flags |= MS_RDONLY;
|
||||||
|
else if (part == "remount")
|
||||||
|
flags |= MS_REMOUNT;
|
||||||
else if (part == "bind")
|
else if (part == "bind")
|
||||||
fprintf(stderr, "Ignoring -o bind, as it doesn't make sense for chroot\n");
|
fprintf(stderr, "Ignoring -o bind, as it doesn't make sense for chroot\n");
|
||||||
else
|
else
|
||||||
|
|
|
@ -52,6 +52,8 @@ int parse_options(const StringView& options)
|
||||||
flags |= MS_BIND;
|
flags |= MS_BIND;
|
||||||
else if (part == "ro")
|
else if (part == "ro")
|
||||||
flags |= MS_RDONLY;
|
flags |= MS_RDONLY;
|
||||||
|
else if (part == "remount")
|
||||||
|
flags |= MS_REMOUNT;
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Ignoring invalid option: %s\n", part.to_string().characters());
|
fprintf(stderr, "Ignoring invalid option: %s\n", part.to_string().characters());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue