Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 #include <linux/module.h>
0003 #include <linux/sock_diag.h>
0004 #include <linux/net.h>
0005 #include <linux/netdevice.h>
0006 #include <linux/packet_diag.h>
0007 #include <linux/percpu.h>
0008 #include <net/net_namespace.h>
0009 #include <net/sock.h>
0010 
0011 #include "internal.h"
0012 
0013 static int pdiag_put_info(const struct packet_sock *po, struct sk_buff *nlskb)
0014 {
0015     struct packet_diag_info pinfo;
0016 
0017     pinfo.pdi_index = po->ifindex;
0018     pinfo.pdi_version = po->tp_version;
0019     pinfo.pdi_reserve = po->tp_reserve;
0020     pinfo.pdi_copy_thresh = po->copy_thresh;
0021     pinfo.pdi_tstamp = po->tp_tstamp;
0022 
0023     pinfo.pdi_flags = 0;
0024     if (po->running)
0025         pinfo.pdi_flags |= PDI_RUNNING;
0026     if (po->auxdata)
0027         pinfo.pdi_flags |= PDI_AUXDATA;
0028     if (po->origdev)
0029         pinfo.pdi_flags |= PDI_ORIGDEV;
0030     if (po->has_vnet_hdr)
0031         pinfo.pdi_flags |= PDI_VNETHDR;
0032     if (po->tp_loss)
0033         pinfo.pdi_flags |= PDI_LOSS;
0034 
0035     return nla_put(nlskb, PACKET_DIAG_INFO, sizeof(pinfo), &pinfo);
0036 }
0037 
0038 static int pdiag_put_mclist(const struct packet_sock *po, struct sk_buff *nlskb)
0039 {
0040     struct nlattr *mca;
0041     struct packet_mclist *ml;
0042 
0043     mca = nla_nest_start_noflag(nlskb, PACKET_DIAG_MCLIST);
0044     if (!mca)
0045         return -EMSGSIZE;
0046 
0047     rtnl_lock();
0048     for (ml = po->mclist; ml; ml = ml->next) {
0049         struct packet_diag_mclist *dml;
0050 
0051         dml = nla_reserve_nohdr(nlskb, sizeof(*dml));
0052         if (!dml) {
0053             rtnl_unlock();
0054             nla_nest_cancel(nlskb, mca);
0055             return -EMSGSIZE;
0056         }
0057 
0058         dml->pdmc_index = ml->ifindex;
0059         dml->pdmc_type = ml->type;
0060         dml->pdmc_alen = ml->alen;
0061         dml->pdmc_count = ml->count;
0062         BUILD_BUG_ON(sizeof(dml->pdmc_addr) != sizeof(ml->addr));
0063         memcpy(dml->pdmc_addr, ml->addr, sizeof(ml->addr));
0064     }
0065 
0066     rtnl_unlock();
0067     nla_nest_end(nlskb, mca);
0068 
0069     return 0;
0070 }
0071 
0072 static int pdiag_put_ring(struct packet_ring_buffer *ring, int ver, int nl_type,
0073         struct sk_buff *nlskb)
0074 {
0075     struct packet_diag_ring pdr;
0076 
0077     if (!ring->pg_vec)
0078         return 0;
0079 
0080     pdr.pdr_block_size = ring->pg_vec_pages << PAGE_SHIFT;
0081     pdr.pdr_block_nr = ring->pg_vec_len;
0082     pdr.pdr_frame_size = ring->frame_size;
0083     pdr.pdr_frame_nr = ring->frame_max + 1;
0084 
0085     if (ver > TPACKET_V2) {
0086         pdr.pdr_retire_tmo = ring->prb_bdqc.retire_blk_tov;
0087         pdr.pdr_sizeof_priv = ring->prb_bdqc.blk_sizeof_priv;
0088         pdr.pdr_features = ring->prb_bdqc.feature_req_word;
0089     } else {
0090         pdr.pdr_retire_tmo = 0;
0091         pdr.pdr_sizeof_priv = 0;
0092         pdr.pdr_features = 0;
0093     }
0094 
0095     return nla_put(nlskb, nl_type, sizeof(pdr), &pdr);
0096 }
0097 
0098 static int pdiag_put_rings_cfg(struct packet_sock *po, struct sk_buff *skb)
0099 {
0100     int ret;
0101 
0102     mutex_lock(&po->pg_vec_lock);
0103     ret = pdiag_put_ring(&po->rx_ring, po->tp_version,
0104             PACKET_DIAG_RX_RING, skb);
0105     if (!ret)
0106         ret = pdiag_put_ring(&po->tx_ring, po->tp_version,
0107                 PACKET_DIAG_TX_RING, skb);
0108     mutex_unlock(&po->pg_vec_lock);
0109 
0110     return ret;
0111 }
0112 
0113 static int pdiag_put_fanout(struct packet_sock *po, struct sk_buff *nlskb)
0114 {
0115     int ret = 0;
0116 
0117     mutex_lock(&fanout_mutex);
0118     if (po->fanout) {
0119         u32 val;
0120 
0121         val = (u32)po->fanout->id | ((u32)po->fanout->type << 16);
0122         ret = nla_put_u32(nlskb, PACKET_DIAG_FANOUT, val);
0123     }
0124     mutex_unlock(&fanout_mutex);
0125 
0126     return ret;
0127 }
0128 
0129 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
0130             struct packet_diag_req *req,
0131             bool may_report_filterinfo,
0132             struct user_namespace *user_ns,
0133             u32 portid, u32 seq, u32 flags, int sk_ino)
0134 {
0135     struct nlmsghdr *nlh;
0136     struct packet_diag_msg *rp;
0137     struct packet_sock *po = pkt_sk(sk);
0138 
0139     nlh = nlmsg_put(skb, portid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rp), flags);
0140     if (!nlh)
0141         return -EMSGSIZE;
0142 
0143     rp = nlmsg_data(nlh);
0144     rp->pdiag_family = AF_PACKET;
0145     rp->pdiag_type = sk->sk_type;
0146     rp->pdiag_num = ntohs(po->num);
0147     rp->pdiag_ino = sk_ino;
0148     sock_diag_save_cookie(sk, rp->pdiag_cookie);
0149 
0150     if ((req->pdiag_show & PACKET_SHOW_INFO) &&
0151             pdiag_put_info(po, skb))
0152         goto out_nlmsg_trim;
0153 
0154     if ((req->pdiag_show & PACKET_SHOW_INFO) &&
0155         nla_put_u32(skb, PACKET_DIAG_UID,
0156             from_kuid_munged(user_ns, sock_i_uid(sk))))
0157         goto out_nlmsg_trim;
0158 
0159     if ((req->pdiag_show & PACKET_SHOW_MCLIST) &&
0160             pdiag_put_mclist(po, skb))
0161         goto out_nlmsg_trim;
0162 
0163     if ((req->pdiag_show & PACKET_SHOW_RING_CFG) &&
0164             pdiag_put_rings_cfg(po, skb))
0165         goto out_nlmsg_trim;
0166 
0167     if ((req->pdiag_show & PACKET_SHOW_FANOUT) &&
0168             pdiag_put_fanout(po, skb))
0169         goto out_nlmsg_trim;
0170 
0171     if ((req->pdiag_show & PACKET_SHOW_MEMINFO) &&
0172         sock_diag_put_meminfo(sk, skb, PACKET_DIAG_MEMINFO))
0173         goto out_nlmsg_trim;
0174 
0175     if ((req->pdiag_show & PACKET_SHOW_FILTER) &&
0176         sock_diag_put_filterinfo(may_report_filterinfo, sk, skb,
0177                      PACKET_DIAG_FILTER))
0178         goto out_nlmsg_trim;
0179 
0180     nlmsg_end(skb, nlh);
0181     return 0;
0182 
0183 out_nlmsg_trim:
0184     nlmsg_cancel(skb, nlh);
0185     return -EMSGSIZE;
0186 }
0187 
0188 static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
0189 {
0190     int num = 0, s_num = cb->args[0];
0191     struct packet_diag_req *req;
0192     struct net *net;
0193     struct sock *sk;
0194     bool may_report_filterinfo;
0195 
0196     net = sock_net(skb->sk);
0197     req = nlmsg_data(cb->nlh);
0198     may_report_filterinfo = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
0199 
0200     mutex_lock(&net->packet.sklist_lock);
0201     sk_for_each(sk, &net->packet.sklist) {
0202         if (!net_eq(sock_net(sk), net))
0203             continue;
0204         if (num < s_num)
0205             goto next;
0206 
0207         if (sk_diag_fill(sk, skb, req,
0208                  may_report_filterinfo,
0209                  sk_user_ns(NETLINK_CB(cb->skb).sk),
0210                  NETLINK_CB(cb->skb).portid,
0211                  cb->nlh->nlmsg_seq, NLM_F_MULTI,
0212                  sock_i_ino(sk)) < 0)
0213             goto done;
0214 next:
0215         num++;
0216     }
0217 done:
0218     mutex_unlock(&net->packet.sklist_lock);
0219     cb->args[0] = num;
0220 
0221     return skb->len;
0222 }
0223 
0224 static int packet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
0225 {
0226     int hdrlen = sizeof(struct packet_diag_req);
0227     struct net *net = sock_net(skb->sk);
0228     struct packet_diag_req *req;
0229 
0230     if (nlmsg_len(h) < hdrlen)
0231         return -EINVAL;
0232 
0233     req = nlmsg_data(h);
0234     /* Make it possible to support protocol filtering later */
0235     if (req->sdiag_protocol)
0236         return -EINVAL;
0237 
0238     if (h->nlmsg_flags & NLM_F_DUMP) {
0239         struct netlink_dump_control c = {
0240             .dump = packet_diag_dump,
0241         };
0242         return netlink_dump_start(net->diag_nlsk, skb, h, &c);
0243     } else
0244         return -EOPNOTSUPP;
0245 }
0246 
0247 static const struct sock_diag_handler packet_diag_handler = {
0248     .family = AF_PACKET,
0249     .dump = packet_diag_handler_dump,
0250 };
0251 
0252 static int __init packet_diag_init(void)
0253 {
0254     return sock_diag_register(&packet_diag_handler);
0255 }
0256 
0257 static void __exit packet_diag_exit(void)
0258 {
0259     sock_diag_unregister(&packet_diag_handler);
0260 }
0261 
0262 module_init(packet_diag_init);
0263 module_exit(packet_diag_exit);
0264 MODULE_LICENSE("GPL");
0265 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 17 /* AF_PACKET */);