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

task.c (4250B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AppArmor security module
      4 *
      5 * This file contains AppArmor task related definitions and mediation
      6 *
      7 * Copyright 2017 Canonical Ltd.
      8 *
      9 * TODO
     10 * If a task uses change_hat it currently does not return to the old
     11 * cred or task context but instead creates a new one.  Ideally the task
     12 * should return to the previous cred if it has not been modified.
     13 */
     14
     15#include "include/cred.h"
     16#include "include/task.h"
     17
     18/**
     19 * aa_get_task_label - Get another task's label
     20 * @task: task to query  (NOT NULL)
     21 *
     22 * Returns: counted reference to @task's label
     23 */
     24struct aa_label *aa_get_task_label(struct task_struct *task)
     25{
     26	struct aa_label *p;
     27
     28	rcu_read_lock();
     29	p = aa_get_newest_label(__aa_task_raw_label(task));
     30	rcu_read_unlock();
     31
     32	return p;
     33}
     34
     35/**
     36 * aa_replace_current_label - replace the current tasks label
     37 * @label: new label  (NOT NULL)
     38 *
     39 * Returns: 0 or error on failure
     40 */
     41int aa_replace_current_label(struct aa_label *label)
     42{
     43	struct aa_label *old = aa_current_raw_label();
     44	struct aa_task_ctx *ctx = task_ctx(current);
     45	struct cred *new;
     46
     47	AA_BUG(!label);
     48
     49	if (old == label)
     50		return 0;
     51
     52	if (current_cred() != current_real_cred())
     53		return -EBUSY;
     54
     55	new  = prepare_creds();
     56	if (!new)
     57		return -ENOMEM;
     58
     59	if (ctx->nnp && label_is_stale(ctx->nnp)) {
     60		struct aa_label *tmp = ctx->nnp;
     61
     62		ctx->nnp = aa_get_newest_label(tmp);
     63		aa_put_label(tmp);
     64	}
     65	if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
     66		/*
     67		 * if switching to unconfined or a different label namespace
     68		 * clear out context state
     69		 */
     70		aa_clear_task_ctx_trans(task_ctx(current));
     71
     72	/*
     73	 * be careful switching cred label, when racing replacement it
     74	 * is possible that the cred labels's->proxy->label is the reference
     75	 * keeping @label valid, so make sure to get its reference before
     76	 * dropping the reference on the cred's label
     77	 */
     78	aa_get_label(label);
     79	aa_put_label(cred_label(new));
     80	set_cred_label(new, label);
     81
     82	commit_creds(new);
     83	return 0;
     84}
     85
     86
     87/**
     88 * aa_set_current_onexec - set the tasks change_profile to happen onexec
     89 * @label: system label to set at exec  (MAYBE NULL to clear value)
     90 * @stack: whether stacking should be done
     91 * Returns: 0 or error on failure
     92 */
     93int aa_set_current_onexec(struct aa_label *label, bool stack)
     94{
     95	struct aa_task_ctx *ctx = task_ctx(current);
     96
     97	aa_get_label(label);
     98	aa_put_label(ctx->onexec);
     99	ctx->onexec = label;
    100	ctx->token = stack;
    101
    102	return 0;
    103}
    104
    105/**
    106 * aa_set_current_hat - set the current tasks hat
    107 * @label: label to set as the current hat  (NOT NULL)
    108 * @token: token value that must be specified to change from the hat
    109 *
    110 * Do switch of tasks hat.  If the task is currently in a hat
    111 * validate the token to match.
    112 *
    113 * Returns: 0 or error on failure
    114 */
    115int aa_set_current_hat(struct aa_label *label, u64 token)
    116{
    117	struct aa_task_ctx *ctx = task_ctx(current);
    118	struct cred *new;
    119
    120	new = prepare_creds();
    121	if (!new)
    122		return -ENOMEM;
    123	AA_BUG(!label);
    124
    125	if (!ctx->previous) {
    126		/* transfer refcount */
    127		ctx->previous = cred_label(new);
    128		ctx->token = token;
    129	} else if (ctx->token == token) {
    130		aa_put_label(cred_label(new));
    131	} else {
    132		/* previous_profile && ctx->token != token */
    133		abort_creds(new);
    134		return -EACCES;
    135	}
    136
    137	set_cred_label(new, aa_get_newest_label(label));
    138	/* clear exec on switching context */
    139	aa_put_label(ctx->onexec);
    140	ctx->onexec = NULL;
    141
    142	commit_creds(new);
    143	return 0;
    144}
    145
    146/**
    147 * aa_restore_previous_label - exit from hat context restoring previous label
    148 * @token: the token that must be matched to exit hat context
    149 *
    150 * Attempt to return out of a hat to the previous label.  The token
    151 * must match the stored token value.
    152 *
    153 * Returns: 0 or error of failure
    154 */
    155int aa_restore_previous_label(u64 token)
    156{
    157	struct aa_task_ctx *ctx = task_ctx(current);
    158	struct cred *new;
    159
    160	if (ctx->token != token)
    161		return -EACCES;
    162	/* ignore restores when there is no saved label */
    163	if (!ctx->previous)
    164		return 0;
    165
    166	new = prepare_creds();
    167	if (!new)
    168		return -ENOMEM;
    169
    170	aa_put_label(cred_label(new));
    171	set_cred_label(new, aa_get_newest_label(ctx->previous));
    172	AA_BUG(!cred_label(new));
    173	/* clear exec && prev information when restoring to previous context */
    174	aa_clear_task_ctx_trans(ctx);
    175
    176	commit_creds(new);
    177
    178	return 0;
    179}