[PATCH 1/3] Make listen() on an unbound UNIX socket return EDESTADDRREQ.

Subsystems: networking [general], networking [unix sockets], the rest

STALE3847d

3 messages, 1 author, 2016-03-03 · open the first message on its own page

[PATCH 1/3] Make listen() on an unbound UNIX socket return EDESTADDRREQ.

From: Ed Schouten <hidden>
Date: 2016-03-03 11:23:08

If a UNIX socket does not have an address associated with it, it may
either be that a socket has been created through socket() and is still
in its initial state, or it has connected to a peer (e.g. by using
socketpair()). In both those cases listen() should fail.

Though the condition used to test for condition this is all right, POSIX
requires that two different error codes are returned: EINVAL if already
connected and EDESTADDRREQ if not bound.

Reference:
http://pubs.opengroup.org/onlinepubs/009695399/functions/listen.html

Signed-off-by: Ed Schouten <redacted>
---
 net/unix/af_unix.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index f75f847..d810815 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -609,9 +609,9 @@ static int unix_listen(struct socket *sock, int backlog)
 	err = -EOPNOTSUPP;
 	if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
 		goto out;	/* Only stream/seqpacket sockets accept */
-	err = -EINVAL;
+	err = unix_peer(sk) == NULL ? -EDESTADDRREQ : -EINVAL;
 	if (!u->addr)
-		goto out;	/* No listens on an unbound socket */
+		goto out;	/* No listen on a connected or unbound socket */
 	unix_state_lock(sk);
 	if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
 		goto out_unlock;
-- 
2.5.0

[PATCH 2/3] Let open() on a UNIX socket return EOPNOTSUPP.

From: Ed Schouten <hidden>
Date: 2016-03-03 11:23:12

The POSIX article on open() is slightly confusing that it states which
error code needs to be returned when opened on a stale FIFO, character
device or block device (ENXIO), but fails to explicitly mention which
code should be returned when trying to open a UNIX socket. This is only
mentioned in a different chapter of the standard (EOPNOTSUPP).

While discussing this matter with the Austin Group, it turns out most
other systems (BSDs, HP-UX, Solaris) do return EOPNOTSUPP. The open()
article has since been extended to require this. Let's go ahead and stay
in sync with the rest.

References:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
http://austingroupbugs.net/view.php?id=943

Signed-off-by: Ed Schouten <redacted>
---
 fs/inode.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/fs/inode.c b/fs/inode.c
index 69b8b52..6e63ca7 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1911,8 +1911,15 @@ void __init inode_init(void)
 		INIT_HLIST_HEAD(&inode_hashtable[loop]);
 }
 
+static int no_open_sock(struct inode *inode, struct file *file)
+{
+	return -EOPNOTSUPP;
+}
+
 void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
 {
+	static const struct file_operations sock_fops = {.open = no_open_sock};
+
 	inode->i_mode = mode;
 	if (S_ISCHR(mode)) {
 		inode->i_fop = &def_chr_fops;
@@ -1923,7 +1930,11 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
 	} else if (S_ISFIFO(mode))
 		inode->i_fop = &pipefifo_fops;
 	else if (S_ISSOCK(mode))
-		;	/* leave it no_open_fops */
+		/*
+		 * open() on a socket needs to return EOPNOTSUPP,
+		 * whereas the default inode operations return ENXIO.
+		 */
+		inode->i_fop = &sock_fops;
 	else
 		printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
 				  " inode %s:%lu\n", mode, inode->i_sb->s_id,
-- 
2.5.0

[PATCH 3/3] Return ENOTCONN when trying to recv() on an unconnected UNIX socket.

From: Ed Schouten <hidden>
Date: 2016-03-03 11:23:13

Both POSIX and our manual pages state that if send() or recv() is called
on an unconnected socket, ENOTCONN should be returned. It looks like our
implementation of send() already does this, but recv() does not.

Reference:
http://pubs.opengroup.org/onlinepubs/009695399/functions/send.html

Signed-off-by: Ed Schouten <redacted>
---
 net/unix/af_unix.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d810815..824dd63 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2283,7 +2283,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
 	unsigned int last_len;
 
 	if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
-		err = -EINVAL;
+		err = -ENOTCONN;
 		goto out;
 	}
 
-- 
2.5.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help