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

nf_conntrack_timeout.c (3432B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
      4 * (C) 2012 by Vyatta Inc. <http://www.vyatta.com>
      5 */
      6
      7#include <linux/types.h>
      8#include <linux/netfilter.h>
      9#include <linux/skbuff.h>
     10#include <linux/vmalloc.h>
     11#include <linux/stddef.h>
     12#include <linux/err.h>
     13#include <linux/percpu.h>
     14#include <linux/kernel.h>
     15#include <linux/netdevice.h>
     16#include <linux/slab.h>
     17#include <linux/export.h>
     18
     19#include <net/netfilter/nf_conntrack.h>
     20#include <net/netfilter/nf_conntrack_core.h>
     21#include <net/netfilter/nf_conntrack_extend.h>
     22#include <net/netfilter/nf_conntrack_l4proto.h>
     23#include <net/netfilter/nf_conntrack_timeout.h>
     24
     25const struct nf_ct_timeout_hooks *nf_ct_timeout_hook __read_mostly;
     26EXPORT_SYMBOL_GPL(nf_ct_timeout_hook);
     27
     28static int untimeout(struct nf_conn *ct, void *timeout)
     29{
     30	struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct);
     31
     32	if (timeout_ext && (!timeout || timeout_ext->timeout == timeout))
     33		RCU_INIT_POINTER(timeout_ext->timeout, NULL);
     34
     35	/* We are not intended to delete this conntrack. */
     36	return 0;
     37}
     38
     39void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout)
     40{
     41	struct nf_ct_iter_data iter_data = {
     42		.net	= net,
     43		.data	= timeout,
     44	};
     45
     46	nf_ct_iterate_cleanup_net(untimeout, &iter_data);
     47}
     48EXPORT_SYMBOL_GPL(nf_ct_untimeout);
     49
     50static void __nf_ct_timeout_put(struct nf_ct_timeout *timeout)
     51{
     52	const struct nf_ct_timeout_hooks *h = rcu_dereference(nf_ct_timeout_hook);
     53
     54	if (h)
     55		h->timeout_put(timeout);
     56}
     57
     58int nf_ct_set_timeout(struct net *net, struct nf_conn *ct,
     59		      u8 l3num, u8 l4num, const char *timeout_name)
     60{
     61	const struct nf_ct_timeout_hooks *h;
     62	struct nf_ct_timeout *timeout;
     63	struct nf_conn_timeout *timeout_ext;
     64	const char *errmsg = NULL;
     65	int ret = 0;
     66
     67	rcu_read_lock();
     68	h = rcu_dereference(nf_ct_timeout_hook);
     69	if (!h) {
     70		ret = -ENOENT;
     71		errmsg = "Timeout policy base is empty";
     72		goto out;
     73	}
     74
     75	timeout = h->timeout_find_get(net, timeout_name);
     76	if (!timeout) {
     77		ret = -ENOENT;
     78		pr_info_ratelimited("No such timeout policy \"%s\"\n",
     79				    timeout_name);
     80		goto out;
     81	}
     82
     83	if (timeout->l3num != l3num) {
     84		ret = -EINVAL;
     85		pr_info_ratelimited("Timeout policy `%s' can only be used by "
     86				    "L%d protocol number %d\n",
     87				    timeout_name, 3, timeout->l3num);
     88		goto err_put_timeout;
     89	}
     90	/* Make sure the timeout policy matches any existing protocol tracker,
     91	 * otherwise default to generic.
     92	 */
     93	if (timeout->l4proto->l4proto != l4num) {
     94		ret = -EINVAL;
     95		pr_info_ratelimited("Timeout policy `%s' can only be used by "
     96				    "L%d protocol number %d\n",
     97				    timeout_name, 4, timeout->l4proto->l4proto);
     98		goto err_put_timeout;
     99	}
    100	timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
    101	if (!timeout_ext) {
    102		ret = -ENOMEM;
    103		goto err_put_timeout;
    104	}
    105
    106	rcu_read_unlock();
    107	return ret;
    108
    109err_put_timeout:
    110	__nf_ct_timeout_put(timeout);
    111out:
    112	rcu_read_unlock();
    113	if (errmsg)
    114		pr_info_ratelimited("%s\n", errmsg);
    115	return ret;
    116}
    117EXPORT_SYMBOL_GPL(nf_ct_set_timeout);
    118
    119void nf_ct_destroy_timeout(struct nf_conn *ct)
    120{
    121	struct nf_conn_timeout *timeout_ext;
    122	const struct nf_ct_timeout_hooks *h;
    123
    124	rcu_read_lock();
    125	h = rcu_dereference(nf_ct_timeout_hook);
    126
    127	if (h) {
    128		timeout_ext = nf_ct_timeout_find(ct);
    129		if (timeout_ext) {
    130			h->timeout_put(timeout_ext->timeout);
    131			RCU_INIT_POINTER(timeout_ext->timeout, NULL);
    132		}
    133	}
    134	rcu_read_unlock();
    135}
    136EXPORT_SYMBOL_GPL(nf_ct_destroy_timeout);