unix_diag: Unix inode info NLA
authorPavel Emelyanov <xemul@parallels.com>
Thu, 15 Dec 2011 02:45:43 +0000 (02:45 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 16 Dec 2011 18:48:28 +0000 (13:48 -0500)
Actually, the socket path if it's not anonymous doesn't give
a clue to which file the socket is bound to. Even if the path
is absolute, it can be unlinked and then new socket can be
bound to it.

With this NLA it's possible to check which file a particular
socket is really bound to.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/unix_diag.h
net/unix/diag.c

index cc4df34d4c14390c4f2ec83185c6fc3f80531d81..3e53adbe9c7f092494c34c5b51dc37068d5cac89 100644 (file)
@@ -12,6 +12,7 @@ struct unix_diag_req {
 };
 
 #define UDIAG_SHOW_NAME                0x00000001      /* show name (not path) */
+#define UDIAG_SHOW_VFS         0x00000002      /* show VFS inode info */
 
 struct unix_diag_msg {
        __u8    udiag_family;
@@ -25,8 +26,14 @@ struct unix_diag_msg {
 
 enum {
        UNIX_DIAG_NAME,
+       UNIX_DIAG_VFS,
 
        UNIX_DIAG_MAX,
 };
 
+struct unix_diag_vfs {
+       __u32   udiag_vfs_ino;
+       __u32   udiag_vfs_dev;
+};
+
 #endif
index 161ce6c05e3140b1830195317ce6887a38a354f0..83799ef19b49a4d5b66f80c62c7ec71f95b9e255 100644 (file)
@@ -26,6 +26,23 @@ rtattr_failure:
        return -EMSGSIZE;
 }
 
+static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb)
+{
+       struct dentry *dentry = unix_sk(sk)->dentry;
+       struct unix_diag_vfs *uv;
+
+       if (dentry) {
+               uv = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_VFS, sizeof(*uv));
+               uv->udiag_vfs_ino = dentry->d_inode->i_ino;
+               uv->udiag_vfs_dev = dentry->d_sb->s_dev;
+       }
+
+       return 0;
+
+rtattr_failure:
+       return -EMSGSIZE;
+}
+
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req,
                u32 pid, u32 seq, u32 flags, int sk_ino)
 {
@@ -48,6 +65,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
                        sk_diag_dump_name(sk, skb))
                goto nlmsg_failure;
 
+       if ((req->udiag_show & UDIAG_SHOW_VFS) &&
+                       sk_diag_dump_vfs(sk, skb))
+               goto nlmsg_failure;
+
        nlh->nlmsg_len = skb_tail_pointer(skb) - b;
        return skb->len;