Commit 2eb7f03a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'vfs-6.16-rc5.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs fixes from Christian Brauner:

 - Fix a regression caused by the anonymous inode rework. Making them
   regular files causes various places in the kernel to tip over
   starting with io_uring.

   Revert to the former status quo and port our assertion to be based on
   checking the inode so we don't lose the valuable VFS_*_ON_*()
   assertions that have already helped discover weird behavior our
   outright bugs.

 - Fix the the upper bound calculation in fuse_fill_write_pages()

 - Fix priority inversion issues in the eventpoll code

 - Make secretmen use anon_inode_make_secure_inode() to avoid bypassing
   the LSM layer

 - Fix a netfs hang due to missing case in final DIO read result
   collection

 - Fix a double put of the netfs_io_request struct

 - Provide some helpers to abstract out NETFS_RREQ_IN_PROGRESS flag
   wrangling

 - Fix infinite looping in netfs_wait_for_pause/request()

 - Fix a netfs ref leak on an extra subrequest inserted into a request's
   list of subreqs

 - Fix various cifs RPC callbacks to set NETFS_SREQ_NEED_RETRY if a
   subrequest fails retriably

 - Fix a cifs warning in the workqueue code when reconnecting a channel

 - Fix the updating of i_size in netfs to avoid a race between testing
   if we should have extended the file with a DIO write and changing
   i_size

 - Merge the places in netfs that update i_size on write

 - Fix coredump socket selftests

* tag 'vfs-6.16-rc5.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  anon_inode: rework assertions
  netfs: Update tracepoints in a number of ways
  netfs: Renumber the NETFS_RREQ_* flags to make traces easier to read
  netfs: Merge i_size update functions
  netfs: Fix i_size updating
  smb: client: set missing retry flag in cifs_writev_callback()
  smb: client: set missing retry flag in cifs_readv_callback()
  smb: client: set missing retry flag in smb2_writev_callback()
  netfs: Fix ref leak on inserted extra subreq in write retry
  netfs: Fix looping in wait functions
  netfs: Provide helpers to perform NETFS_RREQ_IN_PROGRESS flag wangling
  netfs: Fix double put of request
  netfs: Fix hang due to missing case in final DIO read result collection
  eventpoll: Fix priority inversion problem
  fuse: fix fuse_fill_write_pages() upper bound calculation
  fs: export anon_inode_make_secure_inode() and fix secretmem LSM bypass
  selftests/coredump: Fix "socket_detect_userspace_client" test failure
parents 4c06e63b 1e7ab6f6
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -98,14 +98,25 @@ static struct file_system_type anon_inode_fs_type = {
	.kill_sb	= kill_anon_super,
};

static struct inode *anon_inode_make_secure_inode(
	const char *name,
/**
 * anon_inode_make_secure_inode - allocate an anonymous inode with security context
 * @sb:		[in]	Superblock to allocate from
 * @name:	[in]	Name of the class of the newfile (e.g., "secretmem")
 * @context_inode:
 *		[in]	Optional parent inode for security inheritance
 *
 * The function ensures proper security initialization through the LSM hook
 * security_inode_init_security_anon().
 *
 * Return:	Pointer to new inode on success, ERR_PTR on failure.
 */
struct inode *anon_inode_make_secure_inode(struct super_block *sb, const char *name,
					   const struct inode *context_inode)
{
	struct inode *inode;
	int error;

	inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
	inode = alloc_anon_inode(sb);
	if (IS_ERR(inode))
		return inode;
	inode->i_flags &= ~S_PRIVATE;
@@ -118,6 +129,7 @@ static struct inode *anon_inode_make_secure_inode(
	}
	return inode;
}
EXPORT_SYMBOL_GPL_FOR_MODULES(anon_inode_make_secure_inode, "kvm");

static struct file *__anon_inode_getfile(const char *name,
					 const struct file_operations *fops,
@@ -132,7 +144,8 @@ static struct file *__anon_inode_getfile(const char *name,
		return ERR_PTR(-ENOENT);

	if (make_inode) {
		inode =	anon_inode_make_secure_inode(name, context_inode);
		inode =	anon_inode_make_secure_inode(anon_inode_mnt->mnt_sb,
						     name, context_inode);
		if (IS_ERR(inode)) {
			file = ERR_CAST(inode);
			goto err;
+134 −324

File changed.

Preview size limit exceeded, changes collapsed.

+7 −2
Original line number Diff line number Diff line
@@ -114,6 +114,9 @@ static inline void put_binfmt(struct linux_binfmt * fmt)

bool path_noexec(const struct path *path)
{
	/* If it's an anonymous inode make sure that we catch any shenanigans. */
	VFS_WARN_ON_ONCE(IS_ANON_FILE(d_inode(path->dentry)) &&
			 !(path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC));
	return (path->mnt->mnt_flags & MNT_NOEXEC) ||
	       (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
}
@@ -781,13 +784,15 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
	if (IS_ERR(file))
		return file;

	if (path_noexec(&file->f_path))
		return ERR_PTR(-EACCES);

	/*
	 * In the past the regular type check was here. It moved to may_open() in
	 * 633fb6ac3980 ("exec: move S_ISREG() check earlier"). Since then it is
	 * an invariant that all non-regular files error out before we get here.
	 */
	if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) ||
	    path_noexec(&file->f_path))
	if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)))
		return ERR_PTR(-EACCES);

	err = exe_file_deny_write_access(file);
+2 −3
Original line number Diff line number Diff line
@@ -1147,7 +1147,7 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
				     struct address_space *mapping,
				     struct iov_iter *ii, loff_t pos,
				     unsigned int max_pages)
				     unsigned int max_folios)
{
	struct fuse_args_pages *ap = &ia->ap;
	struct fuse_conn *fc = get_fuse_conn(mapping->host);
@@ -1157,12 +1157,11 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
	int err = 0;

	num = min(iov_iter_count(ii), fc->max_write);
	num = min(num, max_pages << PAGE_SHIFT);

	ap->args.in_pages = true;
	ap->descs[0].offset = offset;

	while (num) {
	while (num && ap->num_folios < max_folios) {
		size_t tmp;
		struct folio *folio;
		pgoff_t index = pos >> PAGE_SHIFT;
+3 −5
Original line number Diff line number Diff line
@@ -1649,12 +1649,10 @@ struct inode *alloc_anon_inode(struct super_block *s)
	 */
	inode->i_state = I_DIRTY;
	/*
	 * Historically anonymous inodes didn't have a type at all and
	 * userspace has come to rely on this. Internally they're just
	 * regular files but S_IFREG is masked off when reporting
	 * information to userspace.
	 * Historically anonymous inodes don't have a type at all and
	 * userspace has come to rely on this.
	 */
	inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
	inode->i_mode = S_IRUSR | S_IWUSR;
	inode->i_uid = current_fsuid();
	inode->i_gid = current_fsgid();
	inode->i_flags |= S_PRIVATE | S_ANON_INODE;
Loading