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

resource.c (5156B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AppArmor security module
      4 *
      5 * This file contains AppArmor resource mediation and attachment
      6 *
      7 * Copyright (C) 1998-2008 Novell/SUSE
      8 * Copyright 2009-2010 Canonical Ltd.
      9 */
     10
     11#include <linux/audit.h>
     12#include <linux/security.h>
     13
     14#include "include/audit.h"
     15#include "include/cred.h"
     16#include "include/resource.h"
     17#include "include/policy.h"
     18
     19/*
     20 * Table of rlimit names: we generate it from resource.h.
     21 */
     22#include "rlim_names.h"
     23
     24struct aa_sfs_entry aa_sfs_entry_rlimit[] = {
     25	AA_SFS_FILE_STRING("mask", AA_SFS_RLIMIT_MASK),
     26	{ }
     27};
     28
     29/* audit callback for resource specific fields */
     30static void audit_cb(struct audit_buffer *ab, void *va)
     31{
     32	struct common_audit_data *sa = va;
     33
     34	audit_log_format(ab, " rlimit=%s value=%lu",
     35			 rlim_names[aad(sa)->rlim.rlim], aad(sa)->rlim.max);
     36	if (aad(sa)->peer) {
     37		audit_log_format(ab, " peer=");
     38		aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
     39				FLAGS_NONE, GFP_ATOMIC);
     40	}
     41}
     42
     43/**
     44 * audit_resource - audit setting resource limit
     45 * @profile: profile being enforced  (NOT NULL)
     46 * @resource: rlimit being auditing
     47 * @value: value being set
     48 * @error: error value
     49 *
     50 * Returns: 0 or sa->error else other error code on failure
     51 */
     52static int audit_resource(struct aa_profile *profile, unsigned int resource,
     53			  unsigned long value, struct aa_label *peer,
     54			  const char *info, int error)
     55{
     56	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SETRLIMIT);
     57
     58	aad(&sa)->rlim.rlim = resource;
     59	aad(&sa)->rlim.max = value;
     60	aad(&sa)->peer = peer;
     61	aad(&sa)->info = info;
     62	aad(&sa)->error = error;
     63
     64	return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_cb);
     65}
     66
     67/**
     68 * aa_map_resouce - map compiled policy resource to internal #
     69 * @resource: flattened policy resource number
     70 *
     71 * Returns: resource # for the current architecture.
     72 *
     73 * rlimit resource can vary based on architecture, map the compiled policy
     74 * resource # to the internal representation for the architecture.
     75 */
     76int aa_map_resource(int resource)
     77{
     78	return rlim_map[resource];
     79}
     80
     81static int profile_setrlimit(struct aa_profile *profile, unsigned int resource,
     82			     struct rlimit *new_rlim)
     83{
     84	int e = 0;
     85
     86	if (profile->rlimits.mask & (1 << resource) && new_rlim->rlim_max >
     87	    profile->rlimits.limits[resource].rlim_max)
     88		e = -EACCES;
     89	return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL,
     90			      e);
     91}
     92
     93/**
     94 * aa_task_setrlimit - test permission to set an rlimit
     95 * @label - label confining the task  (NOT NULL)
     96 * @task - task the resource is being set on
     97 * @resource - the resource being set
     98 * @new_rlim - the new resource limit  (NOT NULL)
     99 *
    100 * Control raising the processes hard limit.
    101 *
    102 * Returns: 0 or error code if setting resource failed
    103 */
    104int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
    105		      unsigned int resource, struct rlimit *new_rlim)
    106{
    107	struct aa_profile *profile;
    108	struct aa_label *peer;
    109	int error = 0;
    110
    111	rcu_read_lock();
    112	peer = aa_get_newest_cred_label(__task_cred(task));
    113	rcu_read_unlock();
    114
    115	/* TODO: extend resource control to handle other (non current)
    116	 * profiles.  AppArmor rules currently have the implicit assumption
    117	 * that the task is setting the resource of a task confined with
    118	 * the same profile or that the task setting the resource of another
    119	 * task has CAP_SYS_RESOURCE.
    120	 */
    121
    122	if (label != peer &&
    123	    aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0)
    124		error = fn_for_each(label, profile,
    125				audit_resource(profile, resource,
    126					       new_rlim->rlim_max, peer,
    127					       "cap_sys_resource", -EACCES));
    128	else
    129		error = fn_for_each_confined(label, profile,
    130				profile_setrlimit(profile, resource, new_rlim));
    131	aa_put_label(peer);
    132
    133	return error;
    134}
    135
    136/**
    137 * __aa_transition_rlimits - apply new profile rlimits
    138 * @old_l: old label on task  (NOT NULL)
    139 * @new_l: new label with rlimits to apply  (NOT NULL)
    140 */
    141void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l)
    142{
    143	unsigned int mask = 0;
    144	struct rlimit *rlim, *initrlim;
    145	struct aa_profile *old, *new;
    146	struct label_it i;
    147
    148	old = labels_profile(old_l);
    149	new = labels_profile(new_l);
    150
    151	/* for any rlimits the profile controlled, reset the soft limit
    152	 * to the lesser of the tasks hard limit and the init tasks soft limit
    153	 */
    154	label_for_each_confined(i, old_l, old) {
    155		if (old->rlimits.mask) {
    156			int j;
    157
    158			for (j = 0, mask = 1; j < RLIM_NLIMITS; j++,
    159				     mask <<= 1) {
    160				if (old->rlimits.mask & mask) {
    161					rlim = current->signal->rlim + j;
    162					initrlim = init_task.signal->rlim + j;
    163					rlim->rlim_cur = min(rlim->rlim_max,
    164							    initrlim->rlim_cur);
    165				}
    166			}
    167		}
    168	}
    169
    170	/* set any new hard limits as dictated by the new profile */
    171	label_for_each_confined(i, new_l, new) {
    172		int j;
    173
    174		if (!new->rlimits.mask)
    175			continue;
    176		for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, mask <<= 1) {
    177			if (!(new->rlimits.mask & mask))
    178				continue;
    179
    180			rlim = current->signal->rlim + j;
    181			rlim->rlim_max = min(rlim->rlim_max,
    182					     new->rlimits.limits[j].rlim_max);
    183			/* soft limit should not exceed hard limit */
    184			rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
    185		}
    186	}
    187}