1 From eb0a4a47ae89aaa0674ab3180de6a162f3be2ddf Mon Sep 17 00:00:00 2001
2 From: Miklos Szeredi <mszeredi@redhat.com>
3 Date: Fri, 20 May 2016 22:13:45 +0200
4 Subject: af_unix: fix hard linked sockets on overlay
6 From: Miklos Szeredi <mszeredi@redhat.com>
8 commit eb0a4a47ae89aaa0674ab3180de6a162f3be2ddf upstream.
10 Overlayfs uses separate inodes even in the case of hard links on the
11 underlying filesystems. This is a problem for AF_UNIX socket
12 implementation which indexes sockets based on the inode. This resulted in
13 hard linked sockets not working.
15 The fix is to use the real, underlying inode.
22 #include <sys/socket.h>
25 #define SOCK "test-sock"
26 #define SOCK2 "test-sock2"
31 struct sockaddr_un addr = {
32 .sun_family = AF_UNIX,
35 struct sockaddr_un addr2 = {
36 .sun_family = AF_UNIX,
42 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
44 if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
46 if (listen(fd, 0) == -1)
48 if (link(SOCK, SOCK2) == -1)
50 if ((fd2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
52 if (connect(fd2, (struct sockaddr *) &addr2, sizeof(addr2)) == -1)
58 Reported-by: Alexander Morozov <alexandr.morozov@docker.com>
59 Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
60 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
63 net/unix/af_unix.c | 6 +++---
64 1 file changed, 3 insertions(+), 3 deletions(-)
66 --- a/net/unix/af_unix.c
67 +++ b/net/unix/af_unix.c
68 @@ -315,7 +315,7 @@ static struct sock *unix_find_socket_byi
69 &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
70 struct dentry *dentry = unix_sk(s)->path.dentry;
72 - if (dentry && d_backing_inode(dentry) == i) {
73 + if (dentry && d_real_inode(dentry) == i) {
77 @@ -911,7 +911,7 @@ static struct sock *unix_find_other(stru
78 err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
81 - inode = d_backing_inode(path.dentry);
82 + inode = d_real_inode(path.dentry);
83 err = inode_permission(inode, MAY_WRITE);
86 @@ -1048,7 +1048,7 @@ static int unix_bind(struct socket *sock
89 addr->hash = UNIX_HASH_SIZE;
90 - hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
91 + hash = d_real_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
92 spin_lock(&unix_table_lock);
94 list = &unix_socket_table[hash];