1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/types.h> 3 #include <linux/spinlock.h> 4 #include <linux/sock_diag.h> 5 #include <linux/unix_diag.h> 6 #include <linux/skbuff.h> 7 #include <linux/module.h> 8 #include <net/netlink.h> 9 #include <net/af_unix.h> 10 #include <net/tcp_states.h> 11 12 static int sk_diag_dump_name(struct sock *sk, struct sk_buff *nlskb) 13 { 14 /* might or might not have unix_table_lock */ 15 struct unix_address *addr = smp_load_acquire(&unix_sk(sk)->addr); 16 17 if (!addr) 18 return 0; 19 20 return nla_put(nlskb, UNIX_DIAG_NAME, addr->len - sizeof(short), 21 addr->name->sun_path); 22 } 23 24 static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb) 25 { 26 struct dentry *dentry = unix_sk(sk)->path.dentry; 27 28 if (dentry) { 29 struct unix_diag_vfs uv = { 30 .udiag_vfs_ino = d_backing_inode(dentry)->i_ino, 31 .udiag_vfs_dev = dentry->d_sb->s_dev, 32 }; 33 34 return nla_put(nlskb, UNIX_DIAG_VFS, sizeof(uv), &uv); 35 } 36 37 return 0; 38 } 39 40 static int sk_diag_dump_peer(struct sock *sk, struct sk_buff *nlskb) 41 { 42 struct sock *peer; 43 int ino; 44 45 peer = unix_peer_get(sk); 46 if (peer) { 47 unix_state_lock(peer); 48 ino = sock_i_ino(peer); 49 unix_state_unlock(peer); 50 sock_put(peer); 51 52 return nla_put_u32(nlskb, UNIX_DIAG_PEER, ino); 53 } 54 55 return 0; 56 } 57 58 static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb) 59 { 60 struct sk_buff *skb; 61 struct nlattr *attr; 62 u32 *buf; 63 int i; 64 65 if (sk->sk_state == TCP_LISTEN) { 66 spin_lock(&sk->sk_receive_queue.lock); 67 68 attr = nla_reserve(nlskb, UNIX_DIAG_ICONS, 69 sk->sk_receive_queue.qlen * sizeof(u32)); 70 if (!attr) 71 goto errout; 72 73 buf = nla_data(attr); 74 i = 0; 75 skb_queue_walk(&sk->sk_receive_queue, skb) { 76 struct sock *req, *peer; 77 78 req = skb->sk; 79 /* 80 * The state lock is outer for the same sk's 81 * queue lock. With the other's queue locked it's 82 * OK to lock the state. 83 */ 84 unix_state_lock_nested(req); 85 peer = unix_sk(req)->peer; 86 buf[i++] = (peer ? sock_i_ino(peer) : 0); 87 unix_state_unlock(req); 88 } 89 spin_unlock(&sk->sk_receive_queue.lock); 90 } 91 92 return 0; 93 94 errout: 95 spin_unlock(&sk->sk_receive_queue.lock); 96 return -EMSGSIZE; 97 } 98 99 static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb) 100 { 101 struct unix_diag_rqlen rql; 102 103 if (sk->sk_state == TCP_LISTEN) { 104 rql.udiag_rqueue = sk->sk_receive_queue.qlen; 105 rql.udiag_wqueue = sk->sk_max_ack_backlog; 106 } else { 107 rql.udiag_rqueue = (u32) unix_inq_len(sk); 108 rql.udiag_wqueue = (u32) unix_outq_len(sk); 109 } 110 111 return nla_put(nlskb, UNIX_DIAG_RQLEN, sizeof(rql), &rql); 112 } 113 114 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, 115 u32 portid, u32 seq, u32 flags, int sk_ino) 116 { 117 struct nlmsghdr *nlh; 118 struct unix_diag_msg *rep; 119 120 nlh = nlmsg_put(skb, portid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep), 121 flags); 122 if (!nlh) 123 return -EMSGSIZE; 124 125 rep = nlmsg_data(nlh); 126 rep->udiag_family = AF_UNIX; 127 rep->udiag_type = sk->sk_type; 128 rep->udiag_state = sk->sk_state; 129 rep->pad = 0; 130 rep->udiag_ino = sk_ino; 131 sock_diag_save_cookie(sk, rep->udiag_cookie); 132 133 if ((req->udiag_show & UDIAG_SHOW_NAME) && 134 sk_diag_dump_name(sk, skb)) 135 goto out_nlmsg_trim; 136 137 if ((req->udiag_show & UDIAG_SHOW_VFS) && 138 sk_diag_dump_vfs(sk, skb)) 139 goto out_nlmsg_trim; 140 141 if ((req->udiag_show & UDIAG_SHOW_PEER) && 142 sk_diag_dump_peer(sk, skb)) 143 goto out_nlmsg_trim; 144 145 if ((req->udiag_show & UDIAG_SHOW_ICONS) && 146 sk_diag_dump_icons(sk, skb)) 147 goto out_nlmsg_trim; 148 149 if ((req->udiag_show & UDIAG_SHOW_RQLEN) && 150 sk_diag_show_rqlen(sk, skb)) 151 goto out_nlmsg_trim; 152 153 if ((req->udiag_show & UDIAG_SHOW_MEMINFO) && 154 sock_diag_put_meminfo(sk, skb, UNIX_DIAG_MEMINFO)) 155 goto out_nlmsg_trim; 156 157 if (nla_put_u8(skb, UNIX_DIAG_SHUTDOWN, sk->sk_shutdown)) 158 goto out_nlmsg_trim; 159 160 nlmsg_end(skb, nlh); 161 return 0; 162 163 out_nlmsg_trim: 164 nlmsg_cancel(skb, nlh); 165 return -EMSGSIZE; 166 } 167 168 static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, 169 u32 portid, u32 seq, u32 flags) 170 { 171 int sk_ino; 172 173 unix_state_lock(sk); 174 sk_ino = sock_i_ino(sk); 175 unix_state_unlock(sk); 176 177 if (!sk_ino) 178 return 0; 179 180 return sk_diag_fill(sk, skb, req, portid, seq, flags, sk_ino); 181 } 182 183 static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) 184 { 185 struct unix_diag_req *req; 186 int num, s_num, slot, s_slot; 187 struct net *net = sock_net(skb->sk); 188 189 req = nlmsg_data(cb->nlh); 190 191 s_slot = cb->args[0]; 192 num = s_num = cb->args[1]; 193 194 spin_lock(&unix_table_lock); 195 for (slot = s_slot; 196 slot < ARRAY_SIZE(unix_socket_table); 197 s_num = 0, slot++) { 198 struct sock *sk; 199 200 num = 0; 201 sk_for_each(sk, &unix_socket_table[slot]) { 202 if (!net_eq(sock_net(sk), net)) 203 continue; 204 if (num < s_num) 205 goto next; 206 if (!(req->udiag_states & (1 << sk->sk_state))) 207 goto next; 208 if (sk_diag_dump(sk, skb, req, 209 NETLINK_CB(cb->skb).portid, 210 cb->nlh->nlmsg_seq, 211 NLM_F_MULTI) < 0) 212 goto done; 213 next: 214 num++; 215 } 216 } 217 done: 218 spin_unlock(&unix_table_lock); 219 cb->args[0] = slot; 220 cb->args[1] = num; 221 222 return skb->len; 223 } 224 225 static struct sock *unix_lookup_by_ino(unsigned int ino) 226 { 227 int i; 228 struct sock *sk; 229 230 spin_lock(&unix_table_lock); 231 for (i = 0; i < ARRAY_SIZE(unix_socket_table); i++) { 232 sk_for_each(sk, &unix_socket_table[i]) 233 if (ino == sock_i_ino(sk)) { 234 sock_hold(sk); 235 spin_unlock(&unix_table_lock); 236 237 return sk; 238 } 239 } 240 241 spin_unlock(&unix_table_lock); 242 return NULL; 243 } 244 245 static int unix_diag_get_exact(struct sk_buff *in_skb, 246 const struct nlmsghdr *nlh, 247 struct unix_diag_req *req) 248 { 249 int err = -EINVAL; 250 struct sock *sk; 251 struct sk_buff *rep; 252 unsigned int extra_len; 253 struct net *net = sock_net(in_skb->sk); 254 255 if (req->udiag_ino == 0) 256 goto out_nosk; 257 258 sk = unix_lookup_by_ino(req->udiag_ino); 259 err = -ENOENT; 260 if (sk == NULL) 261 goto out_nosk; 262 if (!net_eq(sock_net(sk), net)) 263 goto out; 264 265 err = sock_diag_check_cookie(sk, req->udiag_cookie); 266 if (err) 267 goto out; 268 269 extra_len = 256; 270 again: 271 err = -ENOMEM; 272 rep = nlmsg_new(sizeof(struct unix_diag_msg) + extra_len, GFP_KERNEL); 273 if (!rep) 274 goto out; 275 276 err = sk_diag_fill(sk, rep, req, NETLINK_CB(in_skb).portid, 277 nlh->nlmsg_seq, 0, req->udiag_ino); 278 if (err < 0) { 279 nlmsg_free(rep); 280 extra_len += 256; 281 if (extra_len >= PAGE_SIZE) 282 goto out; 283 284 goto again; 285 } 286 err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid, 287 MSG_DONTWAIT); 288 if (err > 0) 289 err = 0; 290 out: 291 if (sk) 292 sock_put(sk); 293 out_nosk: 294 return err; 295 } 296 297 static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) 298 { 299 int hdrlen = sizeof(struct unix_diag_req); 300 struct net *net = sock_net(skb->sk); 301 302 if (nlmsg_len(h) < hdrlen) 303 return -EINVAL; 304 305 if (h->nlmsg_flags & NLM_F_DUMP) { 306 struct netlink_dump_control c = { 307 .dump = unix_diag_dump, 308 }; 309 return netlink_dump_start(net->diag_nlsk, skb, h, &c); 310 } else 311 return unix_diag_get_exact(skb, h, nlmsg_data(h)); 312 } 313 314 static const struct sock_diag_handler unix_diag_handler = { 315 .family = AF_UNIX, 316 .dump = unix_diag_handler_dump, 317 }; 318 319 static int __init unix_diag_init(void) 320 { 321 return sock_diag_register(&unix_diag_handler); 322 } 323 324 static void __exit unix_diag_exit(void) 325 { 326 sock_diag_unregister(&unix_diag_handler); 327 } 328 329 module_init(unix_diag_init); 330 module_exit(unix_diag_exit); 331 MODULE_LICENSE("GPL"); 332 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 1 /* AF_LOCAL */); 333