Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c514bed authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull overlayfs fixes from Miklos Szeredi:
 "This contains two regression fixes: one for the xattr API update and
  one for using the mounter's creds in file creation in overlayfs.

  There's also a fix for a bug in handling hard linked AF_UNIX sockets
  that's been there from day one.  This fix is overlayfs only despite
  the fact that it touches code outside the overlay filesystem: d_real()
  is an identity function for all except overlay dentries"

* 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
  ovl: fix uid/gid when creating over whiteout
  ovl: xattr filter fix
  af_unix: fix hard linked sockets on overlay
  vfs: add d_real_inode() helper
parents 38327424 d0e13f5b
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -405,12 +405,21 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
		err = ovl_create_upper(dentry, inode, &stat, link, hardlink);
	} else {
		const struct cred *old_cred;
		struct cred *override_cred;

		old_cred = ovl_override_creds(dentry->d_sb);

		err = ovl_create_over_whiteout(dentry, inode, &stat, link,
					       hardlink);
		err = -ENOMEM;
		override_cred = prepare_creds();
		if (override_cred) {
			override_cred->fsuid = old_cred->fsuid;
			override_cred->fsgid = old_cred->fsgid;
			put_cred(override_creds(override_cred));
			put_cred(override_cred);

			err = ovl_create_over_whiteout(dentry, inode, &stat,
						       link, hardlink);
		}
		revert_creds(old_cred);
	}

+6 −20
Original line number Diff line number Diff line
@@ -238,41 +238,27 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode,
	return err;
}

static bool ovl_need_xattr_filter(struct dentry *dentry,
				  enum ovl_path_type type)
{
	if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER)
		return S_ISDIR(dentry->d_inode->i_mode);
	else
		return false;
}

ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
		     const char *name, void *value, size_t size)
{
	struct path realpath;
	enum ovl_path_type type = ovl_path_real(dentry, &realpath);
	struct dentry *realdentry = ovl_dentry_real(dentry);

	if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
	if (ovl_is_private_xattr(name))
		return -ENODATA;

	return vfs_getxattr(realpath.dentry, name, value, size);
	return vfs_getxattr(realdentry, name, value, size);
}

ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{
	struct path realpath;
	enum ovl_path_type type = ovl_path_real(dentry, &realpath);
	struct dentry *realdentry = ovl_dentry_real(dentry);
	ssize_t res;
	int off;

	res = vfs_listxattr(realpath.dentry, list, size);
	res = vfs_listxattr(realdentry, list, size);
	if (res <= 0 || size == 0)
		return res;

	if (!ovl_need_xattr_filter(dentry, type))
		return res;

	/* filter out private xattrs */
	for (off = 0; off < res;) {
		char *s = list + off;
@@ -302,7 +288,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
		goto out;

	err = -ENODATA;
	if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
	if (ovl_is_private_xattr(name))
		goto out_drop_write;

	if (!OVL_TYPE_UPPER(type)) {
+12 −0
Original line number Diff line number Diff line
@@ -575,5 +575,17 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry,
	return inode;
}

/**
 * d_real_inode - Return the real inode
 * @dentry: The dentry to query
 *
 * If dentry is on an union/overlay, then return the underlying, real inode.
 * Otherwise return d_inode().
 */
static inline struct inode *d_real_inode(struct dentry *dentry)
{
	return d_backing_inode(d_real(dentry));
}


#endif	/* __LINUX_DCACHE_H */
+3 −3
Original line number Diff line number Diff line
@@ -315,7 +315,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
		    &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
		struct dentry *dentry = unix_sk(s)->path.dentry;

		if (dentry && d_backing_inode(dentry) == i) {
		if (dentry && d_real_inode(dentry) == i) {
			sock_hold(s);
			goto found;
		}
@@ -911,7 +911,7 @@ static struct sock *unix_find_other(struct net *net,
		err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
		if (err)
			goto fail;
		inode = d_backing_inode(path.dentry);
		inode = d_real_inode(path.dentry);
		err = inode_permission(inode, MAY_WRITE);
		if (err)
			goto put_fail;
@@ -1048,7 +1048,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
			goto out_up;
		}
		addr->hash = UNIX_HASH_SIZE;
		hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
		hash = d_real_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
		spin_lock(&unix_table_lock);
		u->path = u_path;
		list = &unix_socket_table[hash];