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
This commit is contained in:
Коммит
9c514bedbe
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -238,41 +238,27 @@ out:
|
|||
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)) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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];
|
||||
|
|
Загрузка…
Ссылка в новой задаче