Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * vsock sock_diag(7) module
0004  *
0005  * Copyright (C) 2017 Red Hat, Inc.
0006  * Author: Stefan Hajnoczi <stefanha@redhat.com>
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/sock_diag.h>
0011 #include <linux/vm_sockets_diag.h>
0012 #include <net/af_vsock.h>
0013 
0014 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
0015             u32 portid, u32 seq, u32 flags)
0016 {
0017     struct vsock_sock *vsk = vsock_sk(sk);
0018     struct vsock_diag_msg *rep;
0019     struct nlmsghdr *nlh;
0020 
0021     nlh = nlmsg_put(skb, portid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep),
0022             flags);
0023     if (!nlh)
0024         return -EMSGSIZE;
0025 
0026     rep = nlmsg_data(nlh);
0027     rep->vdiag_family = AF_VSOCK;
0028 
0029     /* Lock order dictates that sk_lock is acquired before
0030      * vsock_table_lock, so we cannot lock here.  Simply don't take
0031      * sk_lock; sk is guaranteed to stay alive since vsock_table_lock is
0032      * held.
0033      */
0034     rep->vdiag_type = sk->sk_type;
0035     rep->vdiag_state = sk->sk_state;
0036     rep->vdiag_shutdown = sk->sk_shutdown;
0037     rep->vdiag_src_cid = vsk->local_addr.svm_cid;
0038     rep->vdiag_src_port = vsk->local_addr.svm_port;
0039     rep->vdiag_dst_cid = vsk->remote_addr.svm_cid;
0040     rep->vdiag_dst_port = vsk->remote_addr.svm_port;
0041     rep->vdiag_ino = sock_i_ino(sk);
0042 
0043     sock_diag_save_cookie(sk, rep->vdiag_cookie);
0044 
0045     return 0;
0046 }
0047 
0048 static int vsock_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
0049 {
0050     struct vsock_diag_req *req;
0051     struct vsock_sock *vsk;
0052     unsigned int bucket;
0053     unsigned int last_i;
0054     unsigned int table;
0055     struct net *net;
0056     unsigned int i;
0057 
0058     req = nlmsg_data(cb->nlh);
0059     net = sock_net(skb->sk);
0060 
0061     /* State saved between calls: */
0062     table = cb->args[0];
0063     bucket = cb->args[1];
0064     i = last_i = cb->args[2];
0065 
0066     /* TODO VMCI pending sockets? */
0067 
0068     spin_lock_bh(&vsock_table_lock);
0069 
0070     /* Bind table (locally created sockets) */
0071     if (table == 0) {
0072         while (bucket < ARRAY_SIZE(vsock_bind_table)) {
0073             struct list_head *head = &vsock_bind_table[bucket];
0074 
0075             i = 0;
0076             list_for_each_entry(vsk, head, bound_table) {
0077                 struct sock *sk = sk_vsock(vsk);
0078 
0079                 if (!net_eq(sock_net(sk), net))
0080                     continue;
0081                 if (i < last_i)
0082                     goto next_bind;
0083                 if (!(req->vdiag_states & (1 << sk->sk_state)))
0084                     goto next_bind;
0085                 if (sk_diag_fill(sk, skb,
0086                          NETLINK_CB(cb->skb).portid,
0087                          cb->nlh->nlmsg_seq,
0088                          NLM_F_MULTI) < 0)
0089                     goto done;
0090 next_bind:
0091                 i++;
0092             }
0093             last_i = 0;
0094             bucket++;
0095         }
0096 
0097         table++;
0098         bucket = 0;
0099     }
0100 
0101     /* Connected table (accepted connections) */
0102     while (bucket < ARRAY_SIZE(vsock_connected_table)) {
0103         struct list_head *head = &vsock_connected_table[bucket];
0104 
0105         i = 0;
0106         list_for_each_entry(vsk, head, connected_table) {
0107             struct sock *sk = sk_vsock(vsk);
0108 
0109             /* Skip sockets we've already seen above */
0110             if (__vsock_in_bound_table(vsk))
0111                 continue;
0112 
0113             if (!net_eq(sock_net(sk), net))
0114                 continue;
0115             if (i < last_i)
0116                 goto next_connected;
0117             if (!(req->vdiag_states & (1 << sk->sk_state)))
0118                 goto next_connected;
0119             if (sk_diag_fill(sk, skb,
0120                      NETLINK_CB(cb->skb).portid,
0121                      cb->nlh->nlmsg_seq,
0122                      NLM_F_MULTI) < 0)
0123                 goto done;
0124 next_connected:
0125             i++;
0126         }
0127         last_i = 0;
0128         bucket++;
0129     }
0130 
0131 done:
0132     spin_unlock_bh(&vsock_table_lock);
0133 
0134     cb->args[0] = table;
0135     cb->args[1] = bucket;
0136     cb->args[2] = i;
0137 
0138     return skb->len;
0139 }
0140 
0141 static int vsock_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
0142 {
0143     int hdrlen = sizeof(struct vsock_diag_req);
0144     struct net *net = sock_net(skb->sk);
0145 
0146     if (nlmsg_len(h) < hdrlen)
0147         return -EINVAL;
0148 
0149     if (h->nlmsg_flags & NLM_F_DUMP) {
0150         struct netlink_dump_control c = {
0151             .dump = vsock_diag_dump,
0152         };
0153         return netlink_dump_start(net->diag_nlsk, skb, h, &c);
0154     }
0155 
0156     return -EOPNOTSUPP;
0157 }
0158 
0159 static const struct sock_diag_handler vsock_diag_handler = {
0160     .family = AF_VSOCK,
0161     .dump = vsock_diag_handler_dump,
0162 };
0163 
0164 static int __init vsock_diag_init(void)
0165 {
0166     return sock_diag_register(&vsock_diag_handler);
0167 }
0168 
0169 static void __exit vsock_diag_exit(void)
0170 {
0171     sock_diag_unregister(&vsock_diag_handler);
0172 }
0173 
0174 module_init(vsock_diag_init);
0175 module_exit(vsock_diag_exit);
0176 MODULE_LICENSE("GPL");
0177 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG,
0178                    40 /* AF_VSOCK */);