Commit 3a2a5b27 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'vfs-6.18-rc1.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs mount updates from Christian Brauner:
 "This contains some work around mount api handling:

   - Output the warning message for mnt_too_revealing() triggered during
     fsmount() to the fscontext log. This makes it possible for the
     mount tool to output appropriate warnings on the command line.

     For example, with the newest fsopen()-based mount(8) from
     util-linux, the error messages now look like:

       # mount -t proc proc /tmp
       mount: /tmp: fsmount() failed: VFS: Mount too revealing.
              dmesg(1) may have more information after failed mount system call.

   - Do not consume fscontext log entries when returning -EMSGSIZE

     Userspace generally expects APIs that return -EMSGSIZE to allow for
     them to adjust their buffer size and retry the operation.

     However, the fscontext log would previously clear the message even
     in the -EMSGSIZE case.

     Given that it is very cheap for us to check whether the buffer is
     too small before we remove the message from the ring buffer, let's
     just do that instead.

   - Drop an unused argument from do_remount()"

* tag 'vfs-6.18-rc1.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  vfs: fs/namespace.c: remove ms_flags argument from do_remount
  selftests/filesystems: add basic fscontext log tests
  fscontext: do not consume log entries when returning -EMSGSIZE
  vfs: output mount_too_revealing() errors to fscontext
  docs/vfs: Remove mentions to the old mount API helpers
  fscontext: add custom-prefix log helpers
  fs: Remove mount_bdev
  fs: Remove mount_nodev
parents 6c7ca6a0 1e5f0fb4
Loading
Loading
Loading
Loading
+2 −25
Original line number Diff line number Diff line
@@ -209,31 +209,8 @@ method fills in is the "s_op" field. This is a pointer to a "struct
super_operations" which describes the next level of the filesystem
implementation.

Usually, a filesystem uses one of the generic mount() implementations
and provides a fill_super() callback instead.  The generic variants are:

``mount_bdev``
	mount a filesystem residing on a block device

``mount_nodev``
	mount a filesystem that is not backed by a device

``mount_single``
	mount a filesystem which shares the instance between all mounts

A fill_super() callback implementation has the following arguments:

``struct super_block *sb``
	the superblock structure.  The callback must initialize this
	properly.

``void *data``
	arbitrary mount options, usually comes as an ASCII string (see
	"Mount Options" section)

``int silent``
	whether or not to be silent on error

For more information on mounting (and the new mount API), see
Documentation/filesystems/mount_api.rst.

The Superblock Object
=====================
+38 −32
Original line number Diff line number Diff line
@@ -18,50 +18,56 @@
#include "internal.h"
#include "mount.h"

static inline const char *fetch_message_locked(struct fc_log *log, size_t len,
					       bool *need_free)
{
	const char *p;
	int index;

	if (unlikely(log->head == log->tail))
		return ERR_PTR(-ENODATA);

	index = log->tail & (ARRAY_SIZE(log->buffer) - 1);
	p = log->buffer[index];
	if (unlikely(strlen(p) > len))
		return ERR_PTR(-EMSGSIZE);

	log->buffer[index] = NULL;
	*need_free = log->need_free & (1 << index);
	log->need_free &= ~(1 << index);
	log->tail++;

	return p;
}

/*
 * Allow the user to read back any error, warning or informational messages.
 * Only one message is returned for each read(2) call.
 */
static ssize_t fscontext_read(struct file *file,
			      char __user *_buf, size_t len, loff_t *pos)
{
	struct fs_context *fc = file->private_data;
	struct fc_log *log = fc->log.log;
	unsigned int logsize = ARRAY_SIZE(log->buffer);
	ssize_t ret;
	char *p;
	ssize_t err;
	const char *p __free(kfree) = NULL, *message;
	bool need_free;
	int index, n;
	int n;

	ret = mutex_lock_interruptible(&fc->uapi_mutex);
	if (ret < 0)
		return ret;

	if (log->head == log->tail) {
		mutex_unlock(&fc->uapi_mutex);
		return -ENODATA;
	}

	index = log->tail & (logsize - 1);
	p = log->buffer[index];
	need_free = log->need_free & (1 << index);
	log->buffer[index] = NULL;
	log->need_free &= ~(1 << index);
	log->tail++;
	err = mutex_lock_interruptible(&fc->uapi_mutex);
	if (err < 0)
		return err;
	message = fetch_message_locked(fc->log.log, len, &need_free);
	mutex_unlock(&fc->uapi_mutex);
	if (IS_ERR(message))
		return PTR_ERR(message);

	ret = -EMSGSIZE;
	n = strlen(p);
	if (n > len)
		goto err_free;
	ret = -EFAULT;
	if (copy_to_user(_buf, p, n) != 0)
		goto err_free;
	ret = n;

err_free:
	if (need_free)
		kfree(p);
	return ret;
		p = message;

	n = strlen(message);
	if (copy_to_user(_buf, message, n))
		return -EFAULT;
	return n;
}

static int fscontext_release(struct inode *inode, struct file *file)
+6 −4
Original line number Diff line number Diff line
@@ -3298,7 +3298,7 @@ static int do_reconfigure_mnt(struct path *path, unsigned int mnt_flags)
 * If you've mounted a non-root directory somewhere and want to do remount
 * on it - tough luck.
 */
static int do_remount(struct path *path, int ms_flags, int sb_flags,
static int do_remount(struct path *path, int sb_flags,
		      int mnt_flags, void *data)
{
	int err;
@@ -3736,8 +3736,10 @@ static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
	int error;

	error = security_sb_kern_mount(sb);
	if (!error && mount_too_revealing(sb, &mnt_flags))
	if (!error && mount_too_revealing(sb, &mnt_flags)) {
		errorfcp(fc, "VFS", "Mount too revealing");
		error = -EPERM;
	}

	if (unlikely(error)) {
		fc_drop_locked(fc);
@@ -4121,7 +4123,7 @@ int path_mount(const char *dev_name, struct path *path,
	if ((flags & (MS_REMOUNT | MS_BIND)) == (MS_REMOUNT | MS_BIND))
		return do_reconfigure_mnt(path, mnt_flags);
	if (flags & MS_REMOUNT)
		return do_remount(path, flags, sb_flags, mnt_flags, data_page);
		return do_remount(path, sb_flags, mnt_flags, data_page);
	if (flags & MS_BIND)
		return do_loopback(path, dev_name, flags & MS_REC);
	if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
@@ -4453,7 +4455,7 @@ SYSCALL_DEFINE3(fsmount, int, fs_fd, unsigned int, flags,

	ret = -EPERM;
	if (mount_too_revealing(fc->root->d_sb, &mnt_flags)) {
		pr_warn("VFS: Mount too revealing\n");
		errorfcp(fc, "VFS", "Mount too revealing");
		goto err_unlock;
	}

+0 −63
Original line number Diff line number Diff line
@@ -1716,49 +1716,6 @@ int get_tree_bdev(struct fs_context *fc,
}
EXPORT_SYMBOL(get_tree_bdev);

static int test_bdev_super(struct super_block *s, void *data)
{
	return !(s->s_iflags & SB_I_RETIRED) && s->s_dev == *(dev_t *)data;
}

struct dentry *mount_bdev(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data,
	int (*fill_super)(struct super_block *, void *, int))
{
	struct super_block *s;
	int error;
	dev_t dev;

	error = lookup_bdev(dev_name, &dev);
	if (error)
		return ERR_PTR(error);

	flags |= SB_NOSEC;
	s = sget(fs_type, test_bdev_super, set_bdev_super, flags, &dev);
	if (IS_ERR(s))
		return ERR_CAST(s);

	if (s->s_root) {
		if ((flags ^ s->s_flags) & SB_RDONLY) {
			deactivate_locked_super(s);
			return ERR_PTR(-EBUSY);
		}
	} else {
		error = setup_bdev_super(s, flags, NULL);
		if (!error)
			error = fill_super(s, data, flags & SB_SILENT ? 1 : 0);
		if (error) {
			deactivate_locked_super(s);
			return ERR_PTR(error);
		}

		s->s_flags |= SB_ACTIVE;
	}

	return dget(s->s_root);
}
EXPORT_SYMBOL(mount_bdev);

void kill_block_super(struct super_block *sb)
{
	struct block_device *bdev = sb->s_bdev;
@@ -1773,26 +1730,6 @@ void kill_block_super(struct super_block *sb)
EXPORT_SYMBOL(kill_block_super);
#endif

struct dentry *mount_nodev(struct file_system_type *fs_type,
	int flags, void *data,
	int (*fill_super)(struct super_block *, void *, int))
{
	int error;
	struct super_block *s = sget(fs_type, NULL, set_anon_super, flags, NULL);

	if (IS_ERR(s))
		return ERR_CAST(s);

	error = fill_super(s, data, flags & SB_SILENT ? 1 : 0);
	if (error) {
		deactivate_locked_super(s);
		return ERR_PTR(error);
	}
	s->s_flags |= SB_ACTIVE;
	return dget(s->s_root);
}
EXPORT_SYMBOL(mount_nodev);

/**
 * vfs_get_tree - Get the mountable root
 * @fc: The superblock configuration context.
+0 −6
Original line number Diff line number Diff line
@@ -2713,12 +2713,6 @@ static inline bool is_mgtime(const struct inode *inode)
	return inode->i_opflags & IOP_MGTIME;
}

extern struct dentry *mount_bdev(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data,
	int (*fill_super)(struct super_block *, void *, int));
extern struct dentry *mount_nodev(struct file_system_type *fs_type,
	int flags, void *data,
	int (*fill_super)(struct super_block *, void *, int));
extern struct dentry *mount_subtree(struct vfsmount *mnt, const char *path);
void retire_super(struct super_block *sb);
void generic_shutdown_super(struct super_block *sb);
Loading