Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 #include <linux/module.h>
0003 
0004 #include <linux/inet_diag.h>
0005 #include <linux/sock_diag.h>
0006 
0007 #include <net/inet_sock.h>
0008 #include <net/raw.h>
0009 #include <net/rawv6.h>
0010 
0011 #ifdef pr_fmt
0012 # undef pr_fmt
0013 #endif
0014 
0015 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0016 
0017 static struct raw_hashinfo *
0018 raw_get_hashinfo(const struct inet_diag_req_v2 *r)
0019 {
0020     if (r->sdiag_family == AF_INET) {
0021         return &raw_v4_hashinfo;
0022 #if IS_ENABLED(CONFIG_IPV6)
0023     } else if (r->sdiag_family == AF_INET6) {
0024         return &raw_v6_hashinfo;
0025 #endif
0026     } else {
0027         return ERR_PTR(-EINVAL);
0028     }
0029 }
0030 
0031 /*
0032  * Due to requirement of not breaking user API we can't simply
0033  * rename @pad field in inet_diag_req_v2 structure, instead
0034  * use helper to figure it out.
0035  */
0036 
0037 static bool raw_lookup(struct net *net, struct sock *sk,
0038                const struct inet_diag_req_v2 *req)
0039 {
0040     struct inet_diag_req_raw *r = (void *)req;
0041 
0042     if (r->sdiag_family == AF_INET)
0043         return raw_v4_match(net, sk, r->sdiag_raw_protocol,
0044                     r->id.idiag_dst[0],
0045                     r->id.idiag_src[0],
0046                     r->id.idiag_if, 0);
0047 #if IS_ENABLED(CONFIG_IPV6)
0048     else
0049         return raw_v6_match(net, sk, r->sdiag_raw_protocol,
0050                     (const struct in6_addr *)r->id.idiag_src,
0051                     (const struct in6_addr *)r->id.idiag_dst,
0052                     r->id.idiag_if, 0);
0053 #endif
0054     return false;
0055 }
0056 
0057 static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 *r)
0058 {
0059     struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
0060     struct hlist_nulls_head *hlist;
0061     struct hlist_nulls_node *hnode;
0062     struct sock *sk;
0063     int slot;
0064 
0065     if (IS_ERR(hashinfo))
0066         return ERR_CAST(hashinfo);
0067 
0068     rcu_read_lock();
0069     for (slot = 0; slot < RAW_HTABLE_SIZE; slot++) {
0070         hlist = &hashinfo->ht[slot];
0071         sk_nulls_for_each(sk, hnode, hlist) {
0072             if (raw_lookup(net, sk, r)) {
0073                 /*
0074                  * Grab it and keep until we fill
0075                  * diag message to be reported, so
0076                  * caller should call sock_put then.
0077                  */
0078                 if (refcount_inc_not_zero(&sk->sk_refcnt))
0079                     goto out_unlock;
0080             }
0081         }
0082     }
0083     sk = ERR_PTR(-ENOENT);
0084 out_unlock:
0085     rcu_read_unlock();
0086 
0087     return sk;
0088 }
0089 
0090 static int raw_diag_dump_one(struct netlink_callback *cb,
0091                  const struct inet_diag_req_v2 *r)
0092 {
0093     struct sk_buff *in_skb = cb->skb;
0094     struct sk_buff *rep;
0095     struct sock *sk;
0096     struct net *net;
0097     int err;
0098 
0099     net = sock_net(in_skb->sk);
0100     sk = raw_sock_get(net, r);
0101     if (IS_ERR(sk))
0102         return PTR_ERR(sk);
0103 
0104     rep = nlmsg_new(nla_total_size(sizeof(struct inet_diag_msg)) +
0105             inet_diag_msg_attrs_size() +
0106             nla_total_size(sizeof(struct inet_diag_meminfo)) + 64,
0107             GFP_KERNEL);
0108     if (!rep) {
0109         sock_put(sk);
0110         return -ENOMEM;
0111     }
0112 
0113     err = inet_sk_diag_fill(sk, NULL, rep, cb, r, 0,
0114                 netlink_net_capable(in_skb, CAP_NET_ADMIN));
0115     sock_put(sk);
0116 
0117     if (err < 0) {
0118         kfree_skb(rep);
0119         return err;
0120     }
0121 
0122     err = nlmsg_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid);
0123 
0124     return err;
0125 }
0126 
0127 static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
0128             struct netlink_callback *cb,
0129             const struct inet_diag_req_v2 *r,
0130             struct nlattr *bc, bool net_admin)
0131 {
0132     if (!inet_diag_bc_sk(bc, sk))
0133         return 0;
0134 
0135     return inet_sk_diag_fill(sk, NULL, skb, cb, r, NLM_F_MULTI, net_admin);
0136 }
0137 
0138 static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
0139               const struct inet_diag_req_v2 *r)
0140 {
0141     bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
0142     struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
0143     struct net *net = sock_net(skb->sk);
0144     struct inet_diag_dump_data *cb_data;
0145     struct hlist_nulls_head *hlist;
0146     struct hlist_nulls_node *hnode;
0147     int num, s_num, slot, s_slot;
0148     struct sock *sk = NULL;
0149     struct nlattr *bc;
0150 
0151     if (IS_ERR(hashinfo))
0152         return;
0153 
0154     cb_data = cb->data;
0155     bc = cb_data->inet_diag_nla_bc;
0156     s_slot = cb->args[0];
0157     num = s_num = cb->args[1];
0158 
0159     rcu_read_lock();
0160     for (slot = s_slot; slot < RAW_HTABLE_SIZE; s_num = 0, slot++) {
0161         num = 0;
0162 
0163         hlist = &hashinfo->ht[slot];
0164         sk_nulls_for_each(sk, hnode, hlist) {
0165             struct inet_sock *inet = inet_sk(sk);
0166 
0167             if (!net_eq(sock_net(sk), net))
0168                 continue;
0169             if (num < s_num)
0170                 goto next;
0171             if (sk->sk_family != r->sdiag_family)
0172                 goto next;
0173             if (r->id.idiag_sport != inet->inet_sport &&
0174                 r->id.idiag_sport)
0175                 goto next;
0176             if (r->id.idiag_dport != inet->inet_dport &&
0177                 r->id.idiag_dport)
0178                 goto next;
0179             if (sk_diag_dump(sk, skb, cb, r, bc, net_admin) < 0)
0180                 goto out_unlock;
0181 next:
0182             num++;
0183         }
0184     }
0185 
0186 out_unlock:
0187     rcu_read_unlock();
0188 
0189     cb->args[0] = slot;
0190     cb->args[1] = num;
0191 }
0192 
0193 static void raw_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
0194                   void *info)
0195 {
0196     r->idiag_rqueue = sk_rmem_alloc_get(sk);
0197     r->idiag_wqueue = sk_wmem_alloc_get(sk);
0198 }
0199 
0200 #ifdef CONFIG_INET_DIAG_DESTROY
0201 static int raw_diag_destroy(struct sk_buff *in_skb,
0202                 const struct inet_diag_req_v2 *r)
0203 {
0204     struct net *net = sock_net(in_skb->sk);
0205     struct sock *sk;
0206     int err;
0207 
0208     sk = raw_sock_get(net, r);
0209     if (IS_ERR(sk))
0210         return PTR_ERR(sk);
0211     err = sock_diag_destroy(sk, ECONNABORTED);
0212     sock_put(sk);
0213     return err;
0214 }
0215 #endif
0216 
0217 static const struct inet_diag_handler raw_diag_handler = {
0218     .dump           = raw_diag_dump,
0219     .dump_one       = raw_diag_dump_one,
0220     .idiag_get_info     = raw_diag_get_info,
0221     .idiag_type     = IPPROTO_RAW,
0222     .idiag_info_size    = 0,
0223 #ifdef CONFIG_INET_DIAG_DESTROY
0224     .destroy        = raw_diag_destroy,
0225 #endif
0226 };
0227 
0228 static void __always_unused __check_inet_diag_req_raw(void)
0229 {
0230     /*
0231      * Make sure the two structures are identical,
0232      * except the @pad field.
0233      */
0234 #define __offset_mismatch(m1, m2)           \
0235     (offsetof(struct inet_diag_req_v2, m1) !=   \
0236      offsetof(struct inet_diag_req_raw, m2))
0237 
0238     BUILD_BUG_ON(sizeof(struct inet_diag_req_v2) !=
0239              sizeof(struct inet_diag_req_raw));
0240     BUILD_BUG_ON(__offset_mismatch(sdiag_family, sdiag_family));
0241     BUILD_BUG_ON(__offset_mismatch(sdiag_protocol, sdiag_protocol));
0242     BUILD_BUG_ON(__offset_mismatch(idiag_ext, idiag_ext));
0243     BUILD_BUG_ON(__offset_mismatch(pad, sdiag_raw_protocol));
0244     BUILD_BUG_ON(__offset_mismatch(idiag_states, idiag_states));
0245     BUILD_BUG_ON(__offset_mismatch(id, id));
0246 #undef __offset_mismatch
0247 }
0248 
0249 static int __init raw_diag_init(void)
0250 {
0251     return inet_diag_register(&raw_diag_handler);
0252 }
0253 
0254 static void __exit raw_diag_exit(void)
0255 {
0256     inet_diag_unregister(&raw_diag_handler);
0257 }
0258 
0259 module_init(raw_diag_init);
0260 module_exit(raw_diag_exit);
0261 MODULE_LICENSE("GPL");
0262 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-255 /* AF_INET - IPPROTO_RAW */);
0263 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 10-255 /* AF_INET6 - IPPROTO_RAW */);