aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@parallels.com>2011-12-14 21:45:43 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-16 13:48:28 -0500
commit5f7b0569460b7d8d01ca776430a00505a68b7584 (patch)
treef67c5033fb1fe17b45e4b45cbbb162428216f37d
parentf5248b48a64c221dd6157ab9cbee5a36ee45e6ed (diff)
unix_diag: Unix inode info NLA
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>
-rw-r--r--include/linux/unix_diag.h7
-rw-r--r--net/unix/diag.c21
2 files changed, 28 insertions, 0 deletions
diff --git a/include/linux/unix_diag.h b/include/linux/unix_diag.h
index cc4df34d4c14..3e53adbe9c7f 100644
--- a/include/linux/unix_diag.h
+++ b/include/linux/unix_diag.h
@@ -12,6 +12,7 @@ struct unix_diag_req {
12}; 12};
13 13
14#define UDIAG_SHOW_NAME 0x00000001 /* show name (not path) */ 14#define UDIAG_SHOW_NAME 0x00000001 /* show name (not path) */
15#define UDIAG_SHOW_VFS 0x00000002 /* show VFS inode info */
15 16
16struct unix_diag_msg { 17struct unix_diag_msg {
17 __u8 udiag_family; 18 __u8 udiag_family;
@@ -25,8 +26,14 @@ struct unix_diag_msg {
25 26
26enum { 27enum {
27 UNIX_DIAG_NAME, 28 UNIX_DIAG_NAME,
29 UNIX_DIAG_VFS,
28 30
29 UNIX_DIAG_MAX, 31 UNIX_DIAG_MAX,
30}; 32};
31 33
34struct unix_diag_vfs {
35 __u32 udiag_vfs_ino;
36 __u32 udiag_vfs_dev;
37};
38
32#endif 39#endif
diff --git a/net/unix/diag.c b/net/unix/diag.c
index 161ce6c05e31..83799ef19b49 100644
--- a/net/unix/diag.c
+++ b/net/unix/diag.c
@@ -26,6 +26,23 @@ rtattr_failure:
26 return -EMSGSIZE; 26 return -EMSGSIZE;
27} 27}
28 28
29static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb)
30{
31 struct dentry *dentry = unix_sk(sk)->dentry;
32 struct unix_diag_vfs *uv;
33
34 if (dentry) {
35 uv = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_VFS, sizeof(*uv));
36 uv->udiag_vfs_ino = dentry->d_inode->i_ino;
37 uv->udiag_vfs_dev = dentry->d_sb->s_dev;
38 }
39
40 return 0;
41
42rtattr_failure:
43 return -EMSGSIZE;
44}
45
29static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, 46static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req,
30 u32 pid, u32 seq, u32 flags, int sk_ino) 47 u32 pid, u32 seq, u32 flags, int sk_ino)
31{ 48{
@@ -48,6 +65,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
48 sk_diag_dump_name(sk, skb)) 65 sk_diag_dump_name(sk, skb))
49 goto nlmsg_failure; 66 goto nlmsg_failure;
50 67
68 if ((req->udiag_show & UDIAG_SHOW_VFS) &&
69 sk_diag_dump_vfs(sk, skb))
70 goto nlmsg_failure;
71
51 nlh->nlmsg_len = skb_tail_pointer(skb) - b; 72 nlh->nlmsg_len = skb_tail_pointer(skb) - b;
52 return skb->len; 73 return skb->len;
53 74