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

capability.c (4171B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AppArmor security module
      4 *
      5 * This file contains AppArmor capability mediation functions
      6 *
      7 * Copyright (C) 1998-2008 Novell/SUSE
      8 * Copyright 2009-2010 Canonical Ltd.
      9 */
     10
     11#include <linux/capability.h>
     12#include <linux/errno.h>
     13#include <linux/gfp.h>
     14#include <linux/security.h>
     15
     16#include "include/apparmor.h"
     17#include "include/capability.h"
     18#include "include/cred.h"
     19#include "include/policy.h"
     20#include "include/audit.h"
     21
     22/*
     23 * Table of capability names: we generate it from capabilities.h.
     24 */
     25#include "capability_names.h"
     26
     27struct aa_sfs_entry aa_sfs_entry_caps[] = {
     28	AA_SFS_FILE_STRING("mask", AA_SFS_CAPS_MASK),
     29	{ }
     30};
     31
     32struct audit_cache {
     33	struct aa_profile *profile;
     34	kernel_cap_t caps;
     35};
     36
     37static DEFINE_PER_CPU(struct audit_cache, audit_cache);
     38
     39/**
     40 * audit_cb - call back for capability components of audit struct
     41 * @ab - audit buffer   (NOT NULL)
     42 * @va - audit struct to audit data from  (NOT NULL)
     43 */
     44static void audit_cb(struct audit_buffer *ab, void *va)
     45{
     46	struct common_audit_data *sa = va;
     47
     48	audit_log_format(ab, " capname=");
     49	audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
     50}
     51
     52/**
     53 * audit_caps - audit a capability
     54 * @sa: audit data
     55 * @profile: profile being tested for confinement (NOT NULL)
     56 * @cap: capability tested
     57 * @error: error code returned by test
     58 *
     59 * Do auditing of capability and handle, audit/complain/kill modes switching
     60 * and duplicate message elimination.
     61 *
     62 * Returns: 0 or sa->error on success,  error code on failure
     63 */
     64static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
     65		      int cap, int error)
     66{
     67	struct audit_cache *ent;
     68	int type = AUDIT_APPARMOR_AUTO;
     69
     70	aad(sa)->error = error;
     71
     72	if (likely(!error)) {
     73		/* test if auditing is being forced */
     74		if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
     75			   !cap_raised(profile->caps.audit, cap)))
     76			return 0;
     77		type = AUDIT_APPARMOR_AUDIT;
     78	} else if (KILL_MODE(profile) ||
     79		   cap_raised(profile->caps.kill, cap)) {
     80		type = AUDIT_APPARMOR_KILL;
     81	} else if (cap_raised(profile->caps.quiet, cap) &&
     82		   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
     83		   AUDIT_MODE(profile) != AUDIT_ALL) {
     84		/* quiet auditing */
     85		return error;
     86	}
     87
     88	/* Do simple duplicate message elimination */
     89	ent = &get_cpu_var(audit_cache);
     90	if (profile == ent->profile && cap_raised(ent->caps, cap)) {
     91		put_cpu_var(audit_cache);
     92		if (COMPLAIN_MODE(profile))
     93			return complain_error(error);
     94		return error;
     95	} else {
     96		aa_put_profile(ent->profile);
     97		ent->profile = aa_get_profile(profile);
     98		cap_raise(ent->caps, cap);
     99	}
    100	put_cpu_var(audit_cache);
    101
    102	return aa_audit(type, profile, sa, audit_cb);
    103}
    104
    105/**
    106 * profile_capable - test if profile allows use of capability @cap
    107 * @profile: profile being enforced    (NOT NULL, NOT unconfined)
    108 * @cap: capability to test if allowed
    109 * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
    110 * @sa: audit data (MAY BE NULL indicating no auditing)
    111 *
    112 * Returns: 0 if allowed else -EPERM
    113 */
    114static int profile_capable(struct aa_profile *profile, int cap,
    115			   unsigned int opts, struct common_audit_data *sa)
    116{
    117	int error;
    118
    119	if (cap_raised(profile->caps.allow, cap) &&
    120	    !cap_raised(profile->caps.denied, cap))
    121		error = 0;
    122	else
    123		error = -EPERM;
    124
    125	if (opts & CAP_OPT_NOAUDIT) {
    126		if (!COMPLAIN_MODE(profile))
    127			return error;
    128		/* audit the cap request in complain mode but note that it
    129		 * should be optional.
    130		 */
    131		aad(sa)->info = "optional: no audit";
    132	}
    133
    134	return audit_caps(sa, profile, cap, error);
    135}
    136
    137/**
    138 * aa_capable - test permission to use capability
    139 * @label: label being tested for capability (NOT NULL)
    140 * @cap: capability to be tested
    141 * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
    142 *
    143 * Look up capability in profile capability set.
    144 *
    145 * Returns: 0 on success, or else an error code.
    146 */
    147int aa_capable(struct aa_label *label, int cap, unsigned int opts)
    148{
    149	struct aa_profile *profile;
    150	int error = 0;
    151	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE);
    152
    153	sa.u.cap = cap;
    154	error = fn_for_each_confined(label, profile,
    155			profile_capable(profile, cap, opts, &sa));
    156
    157	return error;
    158}