root/security/apparmor/task.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. aa_get_task_label
  2. aa_replace_current_label
  3. aa_set_current_onexec
  4. aa_set_current_hat
  5. aa_restore_previous_label

   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  */
  24 struct 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  */
  41 int 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  */
  93 int 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  */
 115 int 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  */
 155 int 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 }

/* [<][>][^][v][top][bottom][index][help] */