diff --git a/include/linux/unix_diag.h b/include/linux/unix_diag.h index cc4df34d4c14390c4f2ec83185c6fc3f80531d81..3e53adbe9c7f092494c34c5b51dc37068d5cac89 100644 --- a/include/linux/unix_diag.h +++ b/include/linux/unix_diag.h @@ -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 diff --git a/net/unix/diag.c b/net/unix/diag.c index 161ce6c05e3140b1830195317ce6887a38a354f0..83799ef19b49a4d5b66f80c62c7ec71f95b9e255 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -26,6 +26,23 @@ static int sk_diag_dump_name(struct sock *sk, struct sk_buff *nlskb) 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;