cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

netfilter_netdev.h (4057B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _NETFILTER_NETDEV_H_
      3#define _NETFILTER_NETDEV_H_
      4
      5#include <linux/netfilter.h>
      6#include <linux/netdevice.h>
      7
      8#ifdef CONFIG_NETFILTER_INGRESS
      9static inline bool nf_hook_ingress_active(const struct sk_buff *skb)
     10{
     11#ifdef CONFIG_JUMP_LABEL
     12	if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_INGRESS]))
     13		return false;
     14#endif
     15	return rcu_access_pointer(skb->dev->nf_hooks_ingress);
     16}
     17
     18/* caller must hold rcu_read_lock */
     19static inline int nf_hook_ingress(struct sk_buff *skb)
     20{
     21	struct nf_hook_entries *e = rcu_dereference(skb->dev->nf_hooks_ingress);
     22	struct nf_hook_state state;
     23	int ret;
     24
     25	/* Must recheck the ingress hook head, in the event it became NULL
     26	 * after the check in nf_hook_ingress_active evaluated to true.
     27	 */
     28	if (unlikely(!e))
     29		return 0;
     30
     31	nf_hook_state_init(&state, NF_NETDEV_INGRESS,
     32			   NFPROTO_NETDEV, skb->dev, NULL, NULL,
     33			   dev_net(skb->dev), NULL);
     34	ret = nf_hook_slow(skb, &state, e, 0);
     35	if (ret == 0)
     36		return -1;
     37
     38	return ret;
     39}
     40
     41#else /* CONFIG_NETFILTER_INGRESS */
     42static inline int nf_hook_ingress_active(struct sk_buff *skb)
     43{
     44	return 0;
     45}
     46
     47static inline int nf_hook_ingress(struct sk_buff *skb)
     48{
     49	return 0;
     50}
     51#endif /* CONFIG_NETFILTER_INGRESS */
     52
     53#ifdef CONFIG_NETFILTER_EGRESS
     54static inline bool nf_hook_egress_active(void)
     55{
     56#ifdef CONFIG_JUMP_LABEL
     57	if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_EGRESS]))
     58		return false;
     59#endif
     60	return true;
     61}
     62
     63/**
     64 * nf_hook_egress - classify packets before transmission
     65 * @skb: packet to be classified
     66 * @rc: result code which shall be returned by __dev_queue_xmit() on failure
     67 * @dev: netdev whose egress hooks shall be applied to @skb
     68 *
     69 * Returns @skb on success or %NULL if the packet was consumed or filtered.
     70 * Caller must hold rcu_read_lock.
     71 *
     72 * On ingress, packets are classified first by tc, then by netfilter.
     73 * On egress, the order is reversed for symmetry.  Conceptually, tc and
     74 * netfilter can be thought of as layers, with netfilter layered above tc:
     75 * When tc redirects a packet to another interface, netfilter is not applied
     76 * because the packet is on the tc layer.
     77 *
     78 * The nf_skip_egress flag controls whether netfilter is applied on egress.
     79 * It is updated by __netif_receive_skb_core() and __dev_queue_xmit() when the
     80 * packet passes through tc and netfilter.  Because __dev_queue_xmit() may be
     81 * called recursively by tunnel drivers such as vxlan, the flag is reverted to
     82 * false after sch_handle_egress().  This ensures that netfilter is applied
     83 * both on the overlay and underlying network.
     84 */
     85static inline struct sk_buff *nf_hook_egress(struct sk_buff *skb, int *rc,
     86					     struct net_device *dev)
     87{
     88	struct nf_hook_entries *e;
     89	struct nf_hook_state state;
     90	int ret;
     91
     92#ifdef CONFIG_NETFILTER_SKIP_EGRESS
     93	if (skb->nf_skip_egress)
     94		return skb;
     95#endif
     96
     97	e = rcu_dereference_check(dev->nf_hooks_egress, rcu_read_lock_bh_held());
     98	if (!e)
     99		return skb;
    100
    101	nf_hook_state_init(&state, NF_NETDEV_EGRESS,
    102			   NFPROTO_NETDEV, NULL, dev, NULL,
    103			   dev_net(dev), NULL);
    104
    105	/* nf assumes rcu_read_lock, not just read_lock_bh */
    106	rcu_read_lock();
    107	ret = nf_hook_slow(skb, &state, e, 0);
    108	rcu_read_unlock();
    109
    110	if (ret == 1) {
    111		return skb;
    112	} else if (ret < 0) {
    113		*rc = NET_XMIT_DROP;
    114		return NULL;
    115	} else { /* ret == 0 */
    116		*rc = NET_XMIT_SUCCESS;
    117		return NULL;
    118	}
    119}
    120#else /* CONFIG_NETFILTER_EGRESS */
    121static inline bool nf_hook_egress_active(void)
    122{
    123	return false;
    124}
    125
    126static inline struct sk_buff *nf_hook_egress(struct sk_buff *skb, int *rc,
    127					     struct net_device *dev)
    128{
    129	return skb;
    130}
    131#endif /* CONFIG_NETFILTER_EGRESS */
    132
    133static inline void nf_skip_egress(struct sk_buff *skb, bool skip)
    134{
    135#ifdef CONFIG_NETFILTER_SKIP_EGRESS
    136	skb->nf_skip_egress = skip;
    137#endif
    138}
    139
    140static inline void nf_hook_netdev_init(struct net_device *dev)
    141{
    142#ifdef CONFIG_NETFILTER_INGRESS
    143	RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL);
    144#endif
    145#ifdef CONFIG_NETFILTER_EGRESS
    146	RCU_INIT_POINTER(dev->nf_hooks_egress, NULL);
    147#endif
    148}
    149
    150#endif /* _NETFILTER_NETDEV_H_ */