Commit 9c514bed authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs

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
...@@ -405,12 +405,21 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev, ...@@ -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); err = ovl_create_upper(dentry, inode, &stat, link, hardlink);
} else { } else {
const struct cred *old_cred; const struct cred *old_cred;
struct cred *override_cred;
old_cred = ovl_override_creds(dentry->d_sb); old_cred = ovl_override_creds(dentry->d_sb);
err = ovl_create_over_whiteout(dentry, inode, &stat, link, err = -ENOMEM;
hardlink); 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); revert_creds(old_cred);
} }
......
...@@ -238,41 +238,27 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode, ...@@ -238,41 +238,27 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode,
return err; 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, ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size) const char *name, void *value, size_t size)
{ {
struct path realpath; struct dentry *realdentry = ovl_dentry_real(dentry);
enum ovl_path_type type = ovl_path_real(dentry, &realpath);
if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) if (ovl_is_private_xattr(name))
return -ENODATA; 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) ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{ {
struct path realpath; struct dentry *realdentry = ovl_dentry_real(dentry);
enum ovl_path_type type = ovl_path_real(dentry, &realpath);
ssize_t res; ssize_t res;
int off; int off;
res = vfs_listxattr(realpath.dentry, list, size); res = vfs_listxattr(realdentry, list, size);
if (res <= 0 || size == 0) if (res <= 0 || size == 0)
return res; return res;
if (!ovl_need_xattr_filter(dentry, type))
return res;
/* filter out private xattrs */ /* filter out private xattrs */
for (off = 0; off < res;) { for (off = 0; off < res;) {
char *s = list + off; char *s = list + off;
...@@ -302,7 +288,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name) ...@@ -302,7 +288,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
goto out; goto out;
err = -ENODATA; err = -ENODATA;
if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) if (ovl_is_private_xattr(name))
goto out_drop_write; goto out_drop_write;
if (!OVL_TYPE_UPPER(type)) { if (!OVL_TYPE_UPPER(type)) {
......
...@@ -575,5 +575,17 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry, ...@@ -575,5 +575,17 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry,
return inode; 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 */ #endif /* __LINUX_DCACHE_H */
...@@ -315,7 +315,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i) ...@@ -315,7 +315,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
&unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
struct dentry *dentry = unix_sk(s)->path.dentry; 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); sock_hold(s);
goto found; goto found;
} }
...@@ -911,7 +911,7 @@ static struct sock *unix_find_other(struct net *net, ...@@ -911,7 +911,7 @@ static struct sock *unix_find_other(struct net *net,
err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path); err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
if (err) if (err)
goto fail; goto fail;
inode = d_backing_inode(path.dentry); inode = d_real_inode(path.dentry);
err = inode_permission(inode, MAY_WRITE); err = inode_permission(inode, MAY_WRITE);
if (err) if (err)
goto put_fail; goto put_fail;
...@@ -1048,7 +1048,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -1048,7 +1048,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
goto out_up; goto out_up;
} }
addr->hash = UNIX_HASH_SIZE; 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); spin_lock(&unix_table_lock);
u->path = u_path; u->path = u_path;
list = &unix_socket_table[hash]; list = &unix_socket_table[hash];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment