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

secid.c (3518B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AppArmor security module
      4 *
      5 * This file contains AppArmor security identifier (secid) manipulation fns
      6 *
      7 * Copyright 2009-2017 Canonical Ltd.
      8 *
      9 * AppArmor allocates a unique secid for every label used. If a label
     10 * is replaced it receives the secid of the label it is replacing.
     11 */
     12
     13#include <linux/errno.h>
     14#include <linux/err.h>
     15#include <linux/gfp.h>
     16#include <linux/idr.h>
     17#include <linux/slab.h>
     18#include <linux/spinlock.h>
     19
     20#include "include/cred.h"
     21#include "include/lib.h"
     22#include "include/secid.h"
     23#include "include/label.h"
     24#include "include/policy_ns.h"
     25
     26/*
     27 * secids - do not pin labels with a refcount. They rely on the label
     28 * properly updating/freeing them
     29 */
     30#define AA_FIRST_SECID 2
     31
     32static DEFINE_IDR(aa_secids);
     33static DEFINE_SPINLOCK(secid_lock);
     34
     35/*
     36 * TODO: allow policy to reserve a secid range?
     37 * TODO: add secid pinning
     38 * TODO: use secid_update in label replace
     39 */
     40
     41/**
     42 * aa_secid_update - update a secid mapping to a new label
     43 * @secid: secid to update
     44 * @label: label the secid will now map to
     45 */
     46void aa_secid_update(u32 secid, struct aa_label *label)
     47{
     48	unsigned long flags;
     49
     50	spin_lock_irqsave(&secid_lock, flags);
     51	idr_replace(&aa_secids, label, secid);
     52	spin_unlock_irqrestore(&secid_lock, flags);
     53}
     54
     55/**
     56 *
     57 * see label for inverse aa_label_to_secid
     58 */
     59struct aa_label *aa_secid_to_label(u32 secid)
     60{
     61	struct aa_label *label;
     62
     63	rcu_read_lock();
     64	label = idr_find(&aa_secids, secid);
     65	rcu_read_unlock();
     66
     67	return label;
     68}
     69
     70int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
     71{
     72	/* TODO: cache secctx and ref count so we don't have to recreate */
     73	struct aa_label *label = aa_secid_to_label(secid);
     74	int len;
     75
     76	AA_BUG(!seclen);
     77
     78	if (!label)
     79		return -EINVAL;
     80
     81	if (secdata)
     82		len = aa_label_asxprint(secdata, root_ns, label,
     83					FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
     84					FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT,
     85					GFP_ATOMIC);
     86	else
     87		len = aa_label_snxprint(NULL, 0, root_ns, label,
     88					FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
     89					FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT);
     90	if (len < 0)
     91		return -ENOMEM;
     92
     93	*seclen = len;
     94
     95	return 0;
     96}
     97
     98int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
     99{
    100	struct aa_label *label;
    101
    102	label = aa_label_strn_parse(&root_ns->unconfined->label, secdata,
    103				    seclen, GFP_KERNEL, false, false);
    104	if (IS_ERR(label))
    105		return PTR_ERR(label);
    106	*secid = label->secid;
    107
    108	return 0;
    109}
    110
    111void apparmor_release_secctx(char *secdata, u32 seclen)
    112{
    113	kfree(secdata);
    114}
    115
    116/**
    117 * aa_alloc_secid - allocate a new secid for a profile
    118 * @label: the label to allocate a secid for
    119 * @gfp: memory allocation flags
    120 *
    121 * Returns: 0 with @label->secid initialized
    122 *          <0 returns error with @label->secid set to AA_SECID_INVALID
    123 */
    124int aa_alloc_secid(struct aa_label *label, gfp_t gfp)
    125{
    126	unsigned long flags;
    127	int ret;
    128
    129	idr_preload(gfp);
    130	spin_lock_irqsave(&secid_lock, flags);
    131	ret = idr_alloc(&aa_secids, label, AA_FIRST_SECID, 0, GFP_ATOMIC);
    132	spin_unlock_irqrestore(&secid_lock, flags);
    133	idr_preload_end();
    134
    135	if (ret < 0) {
    136		label->secid = AA_SECID_INVALID;
    137		return ret;
    138	}
    139
    140	AA_BUG(ret == AA_SECID_INVALID);
    141	label->secid = ret;
    142	return 0;
    143}
    144
    145/**
    146 * aa_free_secid - free a secid
    147 * @secid: secid to free
    148 */
    149void aa_free_secid(u32 secid)
    150{
    151	unsigned long flags;
    152
    153	spin_lock_irqsave(&secid_lock, flags);
    154	idr_remove(&aa_secids, secid);
    155	spin_unlock_irqrestore(&secid_lock, flags);
    156}
    157
    158void aa_secids_init(void)
    159{
    160	idr_init_base(&aa_secids, AA_FIRST_SECID);
    161}