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_labels.c (1777B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * test/set flag bits stored in conntrack extension area.
      4 *
      5 * (C) 2013 Astaro GmbH & Co KG
      6 */
      7
      8#include <linux/export.h>
      9#include <linux/types.h>
     10
     11#include <net/netfilter/nf_conntrack_ecache.h>
     12#include <net/netfilter/nf_conntrack_labels.h>
     13
     14static DEFINE_SPINLOCK(nf_connlabels_lock);
     15
     16static int replace_u32(u32 *address, u32 mask, u32 new)
     17{
     18	u32 old, tmp;
     19
     20	do {
     21		old = *address;
     22		tmp = (old & mask) ^ new;
     23		if (old == tmp)
     24			return 0;
     25	} while (cmpxchg(address, old, tmp) != old);
     26
     27	return 1;
     28}
     29
     30int nf_connlabels_replace(struct nf_conn *ct,
     31			  const u32 *data,
     32			  const u32 *mask, unsigned int words32)
     33{
     34	struct nf_conn_labels *labels;
     35	unsigned int size, i;
     36	int changed = 0;
     37	u32 *dst;
     38
     39	labels = nf_ct_labels_find(ct);
     40	if (!labels)
     41		return -ENOSPC;
     42
     43	size = sizeof(labels->bits);
     44	if (size < (words32 * sizeof(u32)))
     45		words32 = size / sizeof(u32);
     46
     47	dst = (u32 *) labels->bits;
     48	for (i = 0; i < words32; i++)
     49		changed |= replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]);
     50
     51	size /= sizeof(u32);
     52	for (i = words32; i < size; i++) /* pad */
     53		replace_u32(&dst[i], 0, 0);
     54
     55	if (changed)
     56		nf_conntrack_event_cache(IPCT_LABEL, ct);
     57	return 0;
     58}
     59EXPORT_SYMBOL_GPL(nf_connlabels_replace);
     60
     61int nf_connlabels_get(struct net *net, unsigned int bits)
     62{
     63	if (BIT_WORD(bits) >= NF_CT_LABELS_MAX_SIZE / sizeof(long))
     64		return -ERANGE;
     65
     66	spin_lock(&nf_connlabels_lock);
     67	net->ct.labels_used++;
     68	spin_unlock(&nf_connlabels_lock);
     69
     70	BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE / sizeof(long) >= U8_MAX);
     71
     72	return 0;
     73}
     74EXPORT_SYMBOL_GPL(nf_connlabels_get);
     75
     76void nf_connlabels_put(struct net *net)
     77{
     78	spin_lock(&nf_connlabels_lock);
     79	net->ct.labels_used--;
     80	spin_unlock(&nf_connlabels_lock);
     81}
     82EXPORT_SYMBOL_GPL(nf_connlabels_put);