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

addr.c (3974B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* net/atm/addr.c - Local ATM address registry */
      3
      4/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
      5
      6#include <linux/atm.h>
      7#include <linux/atmdev.h>
      8#include <linux/slab.h>
      9#include <linux/uaccess.h>
     10
     11#include "signaling.h"
     12#include "addr.h"
     13
     14static int check_addr(const struct sockaddr_atmsvc *addr)
     15{
     16	int i;
     17
     18	if (addr->sas_family != AF_ATMSVC)
     19		return -EAFNOSUPPORT;
     20	if (!*addr->sas_addr.pub)
     21		return *addr->sas_addr.prv ? 0 : -EINVAL;
     22	for (i = 1; i < ATM_E164_LEN + 1; i++)	/* make sure it's \0-terminated */
     23		if (!addr->sas_addr.pub[i])
     24			return 0;
     25	return -EINVAL;
     26}
     27
     28static int identical(const struct sockaddr_atmsvc *a, const struct sockaddr_atmsvc *b)
     29{
     30	if (*a->sas_addr.prv)
     31		if (memcmp(a->sas_addr.prv, b->sas_addr.prv, ATM_ESA_LEN))
     32			return 0;
     33	if (!*a->sas_addr.pub)
     34		return !*b->sas_addr.pub;
     35	if (!*b->sas_addr.pub)
     36		return 0;
     37	return !strcmp(a->sas_addr.pub, b->sas_addr.pub);
     38}
     39
     40static void notify_sigd(const struct atm_dev *dev)
     41{
     42	struct sockaddr_atmpvc pvc;
     43
     44	pvc.sap_addr.itf = dev->number;
     45	sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL);
     46}
     47
     48void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype)
     49{
     50	unsigned long flags;
     51	struct atm_dev_addr *this, *p;
     52	struct list_head *head;
     53
     54	spin_lock_irqsave(&dev->lock, flags);
     55	if (atype == ATM_ADDR_LECS)
     56		head = &dev->lecs;
     57	else
     58		head = &dev->local;
     59	list_for_each_entry_safe(this, p, head, entry) {
     60		list_del(&this->entry);
     61		kfree(this);
     62	}
     63	spin_unlock_irqrestore(&dev->lock, flags);
     64	if (head == &dev->local)
     65		notify_sigd(dev);
     66}
     67
     68int atm_add_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
     69		 enum atm_addr_type_t atype)
     70{
     71	unsigned long flags;
     72	struct atm_dev_addr *this;
     73	struct list_head *head;
     74	int error;
     75
     76	error = check_addr(addr);
     77	if (error)
     78		return error;
     79	spin_lock_irqsave(&dev->lock, flags);
     80	if (atype == ATM_ADDR_LECS)
     81		head = &dev->lecs;
     82	else
     83		head = &dev->local;
     84	list_for_each_entry(this, head, entry) {
     85		if (identical(&this->addr, addr)) {
     86			spin_unlock_irqrestore(&dev->lock, flags);
     87			return -EEXIST;
     88		}
     89	}
     90	this = kmalloc(sizeof(struct atm_dev_addr), GFP_ATOMIC);
     91	if (!this) {
     92		spin_unlock_irqrestore(&dev->lock, flags);
     93		return -ENOMEM;
     94	}
     95	this->addr = *addr;
     96	list_add(&this->entry, head);
     97	spin_unlock_irqrestore(&dev->lock, flags);
     98	if (head == &dev->local)
     99		notify_sigd(dev);
    100	return 0;
    101}
    102
    103int atm_del_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
    104		 enum atm_addr_type_t atype)
    105{
    106	unsigned long flags;
    107	struct atm_dev_addr *this;
    108	struct list_head *head;
    109	int error;
    110
    111	error = check_addr(addr);
    112	if (error)
    113		return error;
    114	spin_lock_irqsave(&dev->lock, flags);
    115	if (atype == ATM_ADDR_LECS)
    116		head = &dev->lecs;
    117	else
    118		head = &dev->local;
    119	list_for_each_entry(this, head, entry) {
    120		if (identical(&this->addr, addr)) {
    121			list_del(&this->entry);
    122			spin_unlock_irqrestore(&dev->lock, flags);
    123			kfree(this);
    124			if (head == &dev->local)
    125				notify_sigd(dev);
    126			return 0;
    127		}
    128	}
    129	spin_unlock_irqrestore(&dev->lock, flags);
    130	return -ENOENT;
    131}
    132
    133int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf,
    134		 size_t size, enum atm_addr_type_t atype)
    135{
    136	unsigned long flags;
    137	struct atm_dev_addr *this;
    138	struct list_head *head;
    139	int total = 0, error;
    140	struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
    141
    142	spin_lock_irqsave(&dev->lock, flags);
    143	if (atype == ATM_ADDR_LECS)
    144		head = &dev->lecs;
    145	else
    146		head = &dev->local;
    147	list_for_each_entry(this, head, entry)
    148	    total += sizeof(struct sockaddr_atmsvc);
    149	tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
    150	if (!tmp_buf) {
    151		spin_unlock_irqrestore(&dev->lock, flags);
    152		return -ENOMEM;
    153	}
    154	list_for_each_entry(this, head, entry)
    155	    memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc));
    156	spin_unlock_irqrestore(&dev->lock, flags);
    157	error = total > size ? -E2BIG : total;
    158	if (copy_to_user(buf, tmp_buf, total < size ? total : size))
    159		error = -EFAULT;
    160	kfree(tmp_buf);
    161	return error;
    162}