linux/security/apparmor/context.c
<<
>>
Prefs
   1/*
   2 * AppArmor security module
   3 *
   4 * This file contains AppArmor functions used to manipulate object security
   5 * contexts.
   6 *
   7 * Copyright (C) 1998-2008 Novell/SUSE
   8 * Copyright 2009-2010 Canonical Ltd.
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License as
  12 * published by the Free Software Foundation, version 2 of the
  13 * License.
  14 *
  15 *
  16 * AppArmor sets confinement on every task, via the the aa_task_cxt and
  17 * the aa_task_cxt.profile, both of which are required and are not allowed
  18 * to be NULL.  The aa_task_cxt is not reference counted and is unique
  19 * to each cred (which is reference count).  The profile pointed to by
  20 * the task_cxt is reference counted.
  21 *
  22 * TODO
  23 * If a task uses change_hat it currently does not return to the old
  24 * cred or task context but instead creates a new one.  Ideally the task
  25 * should return to the previous cred if it has not been modified.
  26 *
  27 */
  28
  29#include "include/context.h"
  30#include "include/policy.h"
  31
  32/**
  33 * aa_alloc_task_context - allocate a new task_cxt
  34 * @flags: gfp flags for allocation
  35 *
  36 * Returns: allocated buffer or NULL on failure
  37 */
  38struct aa_task_cxt *aa_alloc_task_context(gfp_t flags)
  39{
  40        return kzalloc(sizeof(struct aa_task_cxt), flags);
  41}
  42
  43/**
  44 * aa_free_task_context - free a task_cxt
  45 * @cxt: task_cxt to free (MAYBE NULL)
  46 */
  47void aa_free_task_context(struct aa_task_cxt *cxt)
  48{
  49        if (cxt) {
  50                aa_put_profile(cxt->profile);
  51                aa_put_profile(cxt->previous);
  52                aa_put_profile(cxt->onexec);
  53
  54                kzfree(cxt);
  55        }
  56}
  57
  58/**
  59 * aa_dup_task_context - duplicate a task context, incrementing reference counts
  60 * @new: a blank task context      (NOT NULL)
  61 * @old: the task context to copy  (NOT NULL)
  62 */
  63void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
  64{
  65        *new = *old;
  66        aa_get_profile(new->profile);
  67        aa_get_profile(new->previous);
  68        aa_get_profile(new->onexec);
  69}
  70
  71/**
  72 * aa_replace_current_profile - replace the current tasks profiles
  73 * @profile: new profile  (NOT NULL)
  74 *
  75 * Returns: 0 or error on failure
  76 */
  77int aa_replace_current_profile(struct aa_profile *profile)
  78{
  79        struct aa_task_cxt *cxt = current_cred()->security;
  80        struct cred *new;
  81        BUG_ON(!profile);
  82
  83        if (cxt->profile == profile)
  84                return 0;
  85
  86        new  = prepare_creds();
  87        if (!new)
  88                return -ENOMEM;
  89
  90        cxt = new->security;
  91        if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
  92                /* if switching to unconfined or a different profile namespace
  93                 * clear out context state
  94                 */
  95                aa_put_profile(cxt->previous);
  96                aa_put_profile(cxt->onexec);
  97                cxt->previous = NULL;
  98                cxt->onexec = NULL;
  99                cxt->token = 0;
 100        }
 101        /* be careful switching cxt->profile, when racing replacement it
 102         * is possible that cxt->profile->replacedby is the reference keeping
 103         * @profile valid, so make sure to get its reference before dropping
 104         * the reference on cxt->profile */
 105        aa_get_profile(profile);
 106        aa_put_profile(cxt->profile);
 107        cxt->profile = profile;
 108
 109        commit_creds(new);
 110        return 0;
 111}
 112
 113/**
 114 * aa_set_current_onexec - set the tasks change_profile to happen onexec
 115 * @profile: system profile to set at exec  (MAYBE NULL to clear value)
 116 *
 117 * Returns: 0 or error on failure
 118 */
 119int aa_set_current_onexec(struct aa_profile *profile)
 120{
 121        struct aa_task_cxt *cxt;
 122        struct cred *new = prepare_creds();
 123        if (!new)
 124                return -ENOMEM;
 125
 126        cxt = new->security;
 127        aa_get_profile(profile);
 128        aa_put_profile(cxt->onexec);
 129        cxt->onexec = profile;
 130
 131        commit_creds(new);
 132        return 0;
 133}
 134
 135/**
 136 * aa_set_current_hat - set the current tasks hat
 137 * @profile: profile to set as the current hat  (NOT NULL)
 138 * @token: token value that must be specified to change from the hat
 139 *
 140 * Do switch of tasks hat.  If the task is currently in a hat
 141 * validate the token to match.
 142 *
 143 * Returns: 0 or error on failure
 144 */
 145int aa_set_current_hat(struct aa_profile *profile, u64 token)
 146{
 147        struct aa_task_cxt *cxt;
 148        struct cred *new = prepare_creds();
 149        if (!new)
 150                return -ENOMEM;
 151        BUG_ON(!profile);
 152
 153        cxt = new->security;
 154        if (!cxt->previous) {
 155                /* transfer refcount */
 156                cxt->previous = cxt->profile;
 157                cxt->token = token;
 158        } else if (cxt->token == token) {
 159                aa_put_profile(cxt->profile);
 160        } else {
 161                /* previous_profile && cxt->token != token */
 162                abort_creds(new);
 163                return -EACCES;
 164        }
 165        cxt->profile = aa_get_profile(aa_newest_version(profile));
 166        /* clear exec on switching context */
 167        aa_put_profile(cxt->onexec);
 168        cxt->onexec = NULL;
 169
 170        commit_creds(new);
 171        return 0;
 172}
 173
 174/**
 175 * aa_restore_previous_profile - exit from hat context restoring the profile
 176 * @token: the token that must be matched to exit hat context
 177 *
 178 * Attempt to return out of a hat to the previous profile.  The token
 179 * must match the stored token value.
 180 *
 181 * Returns: 0 or error of failure
 182 */
 183int aa_restore_previous_profile(u64 token)
 184{
 185        struct aa_task_cxt *cxt;
 186        struct cred *new = prepare_creds();
 187        if (!new)
 188                return -ENOMEM;
 189
 190        cxt = new->security;
 191        if (cxt->token != token) {
 192                abort_creds(new);
 193                return -EACCES;
 194        }
 195        /* ignore restores when there is no saved profile */
 196        if (!cxt->previous) {
 197                abort_creds(new);
 198                return 0;
 199        }
 200
 201        aa_put_profile(cxt->profile);
 202        cxt->profile = aa_newest_version(cxt->previous);
 203        BUG_ON(!cxt->profile);
 204        if (unlikely(cxt->profile != cxt->previous)) {
 205                aa_get_profile(cxt->profile);
 206                aa_put_profile(cxt->previous);
 207        }
 208        /* clear exec && prev information when restoring to previous context */
 209        cxt->previous = NULL;
 210        cxt->token = 0;
 211        aa_put_profile(cxt->onexec);
 212        cxt->onexec = NULL;
 213
 214        commit_creds(new);
 215        return 0;
 216}
 217
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.