diff options
-rw-r--r-- | fs/overlayfs/dir.c | 13 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 26 | ||||
-rw-r--r-- | include/linux/dcache.h | 12 | ||||
-rw-r--r-- | net/unix/af_unix.c | 6 |
4 files changed, 32 insertions, 25 deletions
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 22f0253a3567..c2a6b0894022 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c | |||
@@ -405,12 +405,21 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev, | |||
405 | err = ovl_create_upper(dentry, inode, &stat, link, hardlink); | 405 | err = ovl_create_upper(dentry, inode, &stat, link, hardlink); |
406 | } else { | 406 | } else { |
407 | const struct cred *old_cred; | 407 | const struct cred *old_cred; |
408 | struct cred *override_cred; | ||
408 | 409 | ||
409 | old_cred = ovl_override_creds(dentry->d_sb); | 410 | old_cred = ovl_override_creds(dentry->d_sb); |
410 | 411 | ||
411 | err = ovl_create_over_whiteout(dentry, inode, &stat, link, | 412 | err = -ENOMEM; |
412 | hardlink); | 413 | override_cred = prepare_creds(); |
414 | if (override_cred) { | ||
415 | override_cred->fsuid = old_cred->fsuid; | ||
416 | override_cred->fsgid = old_cred->fsgid; | ||
417 | put_cred(override_creds(override_cred)); | ||
418 | put_cred(override_cred); | ||
413 | 419 | ||
420 | err = ovl_create_over_whiteout(dentry, inode, &stat, | ||
421 | link, hardlink); | ||
422 | } | ||
414 | revert_creds(old_cred); | 423 | revert_creds(old_cred); |
415 | } | 424 | } |
416 | 425 | ||
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 0ed7c4012437..1dbeab6cf96e 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -238,41 +238,27 @@ out: | |||
238 | return err; | 238 | return err; |
239 | } | 239 | } |
240 | 240 | ||
241 | static bool ovl_need_xattr_filter(struct dentry *dentry, | ||
242 | enum ovl_path_type type) | ||
243 | { | ||
244 | if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER) | ||
245 | return S_ISDIR(dentry->d_inode->i_mode); | ||
246 | else | ||
247 | return false; | ||
248 | } | ||
249 | |||
250 | ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, | 241 | ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, |
251 | const char *name, void *value, size_t size) | 242 | const char *name, void *value, size_t size) |
252 | { | 243 | { |
253 | struct path realpath; | 244 | struct dentry *realdentry = ovl_dentry_real(dentry); |
254 | enum ovl_path_type type = ovl_path_real(dentry, &realpath); | ||
255 | 245 | ||
256 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) | 246 | if (ovl_is_private_xattr(name)) |
257 | return -ENODATA; | 247 | return -ENODATA; |
258 | 248 | ||
259 | return vfs_getxattr(realpath.dentry, name, value, size); | 249 | return vfs_getxattr(realdentry, name, value, size); |
260 | } | 250 | } |
261 | 251 | ||
262 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) | 252 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) |
263 | { | 253 | { |
264 | struct path realpath; | 254 | struct dentry *realdentry = ovl_dentry_real(dentry); |
265 | enum ovl_path_type type = ovl_path_real(dentry, &realpath); | ||
266 | ssize_t res; | 255 | ssize_t res; |
267 | int off; | 256 | int off; |
268 | 257 | ||
269 | res = vfs_listxattr(realpath.dentry, list, size); | 258 | res = vfs_listxattr(realdentry, list, size); |
270 | if (res <= 0 || size == 0) | 259 | if (res <= 0 || size == 0) |
271 | return res; | 260 | return res; |
272 | 261 | ||
273 | if (!ovl_need_xattr_filter(dentry, type)) | ||
274 | return res; | ||
275 | |||
276 | /* filter out private xattrs */ | 262 | /* filter out private xattrs */ |
277 | for (off = 0; off < res;) { | 263 | for (off = 0; off < res;) { |
278 | char *s = list + off; | 264 | char *s = list + off; |
@@ -302,7 +288,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name) | |||
302 | goto out; | 288 | goto out; |
303 | 289 | ||
304 | err = -ENODATA; | 290 | err = -ENODATA; |
305 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) | 291 | if (ovl_is_private_xattr(name)) |
306 | goto out_drop_write; | 292 | goto out_drop_write; |
307 | 293 | ||
308 | if (!OVL_TYPE_UPPER(type)) { | 294 | if (!OVL_TYPE_UPPER(type)) { |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 484c8792da82..f28100f6b556 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -575,5 +575,17 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry, | |||
575 | return inode; | 575 | return inode; |
576 | } | 576 | } |
577 | 577 | ||
578 | /** | ||
579 | * d_real_inode - Return the real inode | ||
580 | * @dentry: The dentry to query | ||
581 | * | ||
582 | * If dentry is on an union/overlay, then return the underlying, real inode. | ||
583 | * Otherwise return d_inode(). | ||
584 | */ | ||
585 | static inline struct inode *d_real_inode(struct dentry *dentry) | ||
586 | { | ||
587 | return d_backing_inode(d_real(dentry)); | ||
588 | } | ||
589 | |||
578 | 590 | ||
579 | #endif /* __LINUX_DCACHE_H */ | 591 | #endif /* __LINUX_DCACHE_H */ |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 80aa6a3e6817..735362c26c8e 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -315,7 +315,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i) | |||
315 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { | 315 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { |
316 | struct dentry *dentry = unix_sk(s)->path.dentry; | 316 | struct dentry *dentry = unix_sk(s)->path.dentry; |
317 | 317 | ||
318 | if (dentry && d_backing_inode(dentry) == i) { | 318 | if (dentry && d_real_inode(dentry) == i) { |
319 | sock_hold(s); | 319 | sock_hold(s); |
320 | goto found; | 320 | goto found; |
321 | } | 321 | } |
@@ -911,7 +911,7 @@ static struct sock *unix_find_other(struct net *net, | |||
911 | err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path); | 911 | err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path); |
912 | if (err) | 912 | if (err) |
913 | goto fail; | 913 | goto fail; |
914 | inode = d_backing_inode(path.dentry); | 914 | inode = d_real_inode(path.dentry); |
915 | err = inode_permission(inode, MAY_WRITE); | 915 | err = inode_permission(inode, MAY_WRITE); |
916 | if (err) | 916 | if (err) |
917 | goto put_fail; | 917 | goto put_fail; |
@@ -1048,7 +1048,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1048 | goto out_up; | 1048 | goto out_up; |
1049 | } | 1049 | } |
1050 | addr->hash = UNIX_HASH_SIZE; | 1050 | addr->hash = UNIX_HASH_SIZE; |
1051 | hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1); | 1051 | hash = d_real_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1); |
1052 | spin_lock(&unix_table_lock); | 1052 | spin_lock(&unix_table_lock); |
1053 | u->path = u_path; | 1053 | u->path = u_path; |
1054 | list = &unix_socket_table[hash]; | 1054 | list = &unix_socket_table[hash]; |