netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/1] net/unix: Allow Unix sockets to be treated like normal files
@ 2010-10-28  2:24 x
  2010-10-28  2:32 ` David Miller
  0 siblings, 1 reply; 3+ messages in thread
From: x @ 2010-10-28  2:24 UTC (permalink / raw)
  To: netdev; +Cc: Dave Miller, Jeff Hansen

From: Jeff Hansen <x@jeffhansen.com>

Resent.  Is there anything else I need to do for this patch to get reviewed
and/or merged?  Any comments by anyone?

This allows Unix sockets to be opened, written, read, and closed, like
normal files.  This can be especially handy from, for example, a shell
script that wants to send a short message to a Unix socket, but doesn't
want to and/or cannot create the socket itself.

This will try to open the Unix socket first in SOCK_DGRAM mode, then
SOCK_STREAM mode if that fails.

Signed-off-by: Jeff Hansen <x@jeffhansen.com>
---
 net/unix/Kconfig   |   10 +++++
 net/unix/af_unix.c |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/net/unix/Kconfig b/net/unix/Kconfig
index 5a69733..68df4f1 100644
--- a/net/unix/Kconfig
+++ b/net/unix/Kconfig
@@ -19,3 +19,13 @@ config UNIX
 
 	  Say Y unless you know what you are doing.
 
+config UNIX_FOPS
+	boolean "Allow Unix sockets to be treated like normal files"
+	depends on UNIX
+	---help---
+	  If you say Y here, Unix sockets may be opened, written, read, and
+	  closed, like normal files.  This is handy for sending short commands
+	  to Unix sockets (i.e. from shell scripts), without having to create
+	  a Unix socket.
+
+	  Say Y unless you know what you are doing.
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 0ebc777..b5a6655 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -798,6 +798,114 @@ fail:
 	return NULL;
 }
 
+#ifdef CONFIG_UNIX_FOPS
+static int unix_open(struct inode *inode, struct file *filp)
+{
+	int err;
+	struct socket *sock = NULL;
+	struct dentry *dentry = filp->f_dentry;
+	struct sockaddr_un sunaddr = { 0 };
+	char *p;
+
+	if (!filp)
+		return -ENXIO;
+	dentry = filp->f_dentry;
+
+	if (!dentry || !dentry->d_parent)
+		return -ENXIO;
+
+	if (filp->private_data)
+		return -EBUSY;
+
+	sunaddr.sun_family = AF_UNIX;
+	p = d_path(&filp->f_path, sunaddr.sun_path, sizeof(sunaddr.sun_path));
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+	memmove(sunaddr.sun_path, p, p[sizeof(sunaddr.sun_path) - 1] ?
+		sizeof(sunaddr.sun_path) : strlen(p));
+
+	err = sock_create(PF_UNIX, SOCK_DGRAM, 0, &sock);
+	if (err)
+		return err;
+
+	err = unix_dgram_connect(sock, (struct sockaddr *)&sunaddr,
+				 sizeof(sunaddr), 0);
+	if (err) {
+		sock_release(sock);
+
+		err = sock_create(PF_UNIX, SOCK_STREAM, 0, &sock);
+		if (err)
+			return err;
+
+		err = unix_stream_connect(sock, (struct sockaddr *)&sunaddr,
+					  sizeof(sunaddr), 0);
+
+		if (err)
+			return err;
+	}
+	filp->private_data = sock;
+
+	return err;
+}
+
+static int unix_frelease(struct inode *inode, struct file *filp)
+{
+	if (!filp->private_data)
+		return -ENXIO;
+
+	sock_release(filp->private_data);
+	filp->private_data = NULL;
+	return 0;
+}
+
+static ssize_t unix_readwrite(struct file *filp, void *buf,
+	size_t _len, loff_t *ppos, int do_write)
+{
+	struct socket *sock = filp->private_data;
+	int len = (int)_len, err;
+	struct kvec iov = {
+		.iov_base = buf,
+		.iov_len = len,
+	};
+	struct msghdr msg = {
+		/* NB: struct iovec and kvec are equal */
+		.msg_iov = (struct iovec *)&iov,
+		.msg_iovlen = 1,
+	};
+
+	if (!sock)
+		return -ENXIO;
+	if (_len > 0xffffffffLL)
+		return -E2BIG;
+
+	err = do_write ? sock_sendmsg(sock, &msg, len) :
+			 sock_recvmsg(sock, &msg, len, 0);
+	if (err > 0 && ppos)
+		*ppos += err;
+
+	return err;
+}
+
+static ssize_t unix_write(struct file *filp, const char __user *buf,
+	size_t _len, loff_t *ppos)
+{
+	return unix_readwrite(filp, (void *)buf, _len, ppos, 0);
+}
+
+static ssize_t unix_read(struct file *filp, const char __user *buf,
+	size_t _len, loff_t *ppos)
+{
+	return unix_readwrite(filp, (void *)buf, _len, ppos, 0);
+}
+
+const struct file_operations unix_sock_fops = {
+	.owner = THIS_MODULE,
+	.open = unix_open,
+	.release = unix_frelease,
+	.write = unix_write,
+	.read = unix_read,
+};
+#endif /* CONFIG_UNIX_FOPS */
 
 static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
@@ -874,6 +982,11 @@ out_mknod_drop_write:
 		mnt_drop_write(nd.path.mnt);
 		if (err)
 			goto out_mknod_dput;
+
+#ifdef CONFIG_UNIX_FOPS
+		dentry->d_inode->i_fop = &unix_sock_fops;
+#endif
+
 		mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
 		dput(nd.path.dentry);
 		nd.path.dentry = dentry;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/1] net/unix: Allow Unix sockets to be treated like normal files
  2010-10-28  2:24 [PATCH 1/1] net/unix: Allow Unix sockets to be treated like normal files x
@ 2010-10-28  2:32 ` David Miller
  2010-10-28  2:50   ` Jeff Hansen
  0 siblings, 1 reply; 3+ messages in thread
From: David Miller @ 2010-10-28  2:32 UTC (permalink / raw)
  To: x; +Cc: netdev

From: x@jeffhansen.com
Date: Thu, 28 Oct 2010 02:24:29 +0000

> Resent.  Is there anything else I need to do for this patch to get reviewed
> and/or merged?  Any comments by anyone?

I don't like this idea at all.

I remember there is a reason why similar things are not allowed for
sockets, it causes all sorts of problems although I forget the exact
details.

Take a look at net/socket.c:sock_no_open(), for example.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/1] net/unix: Allow Unix sockets to be treated like normal files
  2010-10-28  2:32 ` David Miller
@ 2010-10-28  2:50   ` Jeff Hansen
  0 siblings, 0 replies; 3+ messages in thread
From: Jeff Hansen @ 2010-10-28  2:50 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

  Dave,

I agree that on larger systems this doesn't really make sense, but on 
embedded platforms this can save some code space since applications can 
get rid of their FIFO listeners and have strictly socket listeners.  
That's why I made it an option that could be disabled by default.

Do you know who originally suggested that "creepy crawlies" are 
introduced by allowing sockets to be opened?  I'd be interested to know 
how this could affect security, if at all.

-Jeff

On 10/27/2010 08:32 PM, David Miller wrote:
> From: x@jeffhansen.com
> Date: Thu, 28 Oct 2010 02:24:29 +0000
>
>> Resent.  Is there anything else I need to do for this patch to get reviewed
>> and/or merged?  Any comments by anyone?
> I don't like this idea at all.
>
> I remember there is a reason why similar things are not allowed for
> sockets, it causes all sorts of problems although I forget the exact
> details.
>
> Take a look at net/socket.c:sock_no_open(), for example.
>


-- 
---------------------------------------------------
"If someone's gotta do it, it might as well be me."
                 x@jeffhansen.com


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-10-28  2:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-28  2:24 [PATCH 1/1] net/unix: Allow Unix sockets to be treated like normal files x
2010-10-28  2:32 ` David Miller
2010-10-28  2:50   ` Jeff Hansen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).