1c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen/* 2c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * AppArmor security module 3c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 4c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * This file contains AppArmor functions used to manipulate object security 5c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * contexts. 6c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 7c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * Copyright (C) 1998-2008 Novell/SUSE 8c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * Copyright 2009-2010 Canonical Ltd. 9c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 10c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * This program is free software; you can redistribute it and/or 11c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * modify it under the terms of the GNU General Public License as 12c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * published by the Free Software Foundation, version 2 of the 13c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * License. 14c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 15c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 16c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * AppArmor sets confinement on every task, via the the aa_task_cxt and 17c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * the aa_task_cxt.profile, both of which are required and are not allowed 18c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * to be NULL. The aa_task_cxt is not reference counted and is unique 19c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * to each cred (which is reference count). The profile pointed to by 20c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * the task_cxt is reference counted. 21c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 22c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * TODO 23c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * If a task uses change_hat it currently does not return to the old 24c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * cred or task context but instead creates a new one. Ideally the task 25c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * should return to the previous cred if it has not been modified. 26c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 27c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen */ 28c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 29c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen#include "include/context.h" 30c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen#include "include/policy.h" 31c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 32c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen/** 33c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * aa_alloc_task_context - allocate a new task_cxt 34c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * @flags: gfp flags for allocation 35c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 36c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * Returns: allocated buffer or NULL on failure 37c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen */ 38c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansenstruct aa_task_cxt *aa_alloc_task_context(gfp_t flags) 39c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen{ 40c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return kzalloc(sizeof(struct aa_task_cxt), flags); 41c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen} 42c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 43c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen/** 44c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * aa_free_task_context - free a task_cxt 45c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * @cxt: task_cxt to free (MAYBE NULL) 46c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen */ 47c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansenvoid aa_free_task_context(struct aa_task_cxt *cxt) 48c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen{ 49c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen if (cxt) { 50c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_put_profile(cxt->profile); 51c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_put_profile(cxt->previous); 52c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_put_profile(cxt->onexec); 53c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 54c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen kzfree(cxt); 55c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen } 56c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen} 57c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 58c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen/** 59c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * aa_dup_task_context - duplicate a task context, incrementing reference counts 60c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * @new: a blank task context (NOT NULL) 61c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * @old: the task context to copy (NOT NULL) 62c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen */ 63c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansenvoid aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old) 64c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen{ 65c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen *new = *old; 66c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_get_profile(new->profile); 67c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_get_profile(new->previous); 68c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_get_profile(new->onexec); 69c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen} 70c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 71c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen/** 723cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen * aa_get_task_profile - Get another task's profile 733cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen * @task: task to query (NOT NULL) 743cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen * 753cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen * Returns: counted reference to @task's profile 763cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen */ 773cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansenstruct aa_profile *aa_get_task_profile(struct task_struct *task) 783cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen{ 793cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen struct aa_profile *p; 803cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen 813cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen rcu_read_lock(); 823cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen p = aa_get_profile(__aa_task_profile(task)); 833cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen rcu_read_unlock(); 843cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen 853cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen return p; 863cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen} 873cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen 883cfcc19e0b5390c04cb5bfa4e8fde39395410e61John Johansen/** 89c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * aa_replace_current_profile - replace the current tasks profiles 90c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * @profile: new profile (NOT NULL) 91c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 92c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * Returns: 0 or error on failure 93c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen */ 94c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansenint aa_replace_current_profile(struct aa_profile *profile) 95c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen{ 96214beacaa7b669473bc963af719fa359a8312ea4John Johansen struct aa_task_cxt *cxt = current_cxt(); 97c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen struct cred *new; 98c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen BUG_ON(!profile); 99c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 100c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen if (cxt->profile == profile) 101c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return 0; 102c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 103c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen new = prepare_creds(); 104c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen if (!new) 105c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return -ENOMEM; 106c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 107214beacaa7b669473bc963af719fa359a8312ea4John Johansen cxt = cred_cxt(new); 1087a2871b566f34d980556072943295efd107eb53cJohn Johansen if (unconfined(profile) || (cxt->profile->ns != profile->ns)) 109c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen /* if switching to unconfined or a different profile namespace 110c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * clear out context state 111c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen */ 1127a2871b566f34d980556072943295efd107eb53cJohn Johansen aa_clear_task_cxt_trans(cxt); 1137a2871b566f34d980556072943295efd107eb53cJohn Johansen 114c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen /* be careful switching cxt->profile, when racing replacement it 11577b071b34045a0c65d0e1f85f3d47fd2b8b7a8a1John Johansen * is possible that cxt->profile->replacedby->profile is the reference 11677b071b34045a0c65d0e1f85f3d47fd2b8b7a8a1John Johansen * keeping @profile valid, so make sure to get its reference before 11777b071b34045a0c65d0e1f85f3d47fd2b8b7a8a1John Johansen * dropping the reference on cxt->profile */ 118c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_get_profile(profile); 119c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_put_profile(cxt->profile); 120c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen cxt->profile = profile; 121c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 122c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen commit_creds(new); 123c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return 0; 124c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen} 125c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 126c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen/** 127c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * aa_set_current_onexec - set the tasks change_profile to happen onexec 128c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * @profile: system profile to set at exec (MAYBE NULL to clear value) 129c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 130c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * Returns: 0 or error on failure 131c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen */ 132c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansenint aa_set_current_onexec(struct aa_profile *profile) 133c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen{ 134c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen struct aa_task_cxt *cxt; 135c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen struct cred *new = prepare_creds(); 136c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen if (!new) 137c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return -ENOMEM; 138c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 139214beacaa7b669473bc963af719fa359a8312ea4John Johansen cxt = cred_cxt(new); 140c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_get_profile(profile); 141c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_put_profile(cxt->onexec); 142c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen cxt->onexec = profile; 143c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 144c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen commit_creds(new); 145c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return 0; 146c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen} 147c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 148c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen/** 149c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * aa_set_current_hat - set the current tasks hat 150c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * @profile: profile to set as the current hat (NOT NULL) 151c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * @token: token value that must be specified to change from the hat 152c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 153c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * Do switch of tasks hat. If the task is currently in a hat 154c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * validate the token to match. 155c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 156c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * Returns: 0 or error on failure 157c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen */ 158c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansenint aa_set_current_hat(struct aa_profile *profile, u64 token) 159c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen{ 160c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen struct aa_task_cxt *cxt; 161c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen struct cred *new = prepare_creds(); 162c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen if (!new) 163c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return -ENOMEM; 164c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen BUG_ON(!profile); 165c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 166214beacaa7b669473bc963af719fa359a8312ea4John Johansen cxt = cred_cxt(new); 167c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen if (!cxt->previous) { 168c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen /* transfer refcount */ 169c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen cxt->previous = cxt->profile; 170c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen cxt->token = token; 171c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen } else if (cxt->token == token) { 172c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_put_profile(cxt->profile); 173c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen } else { 174c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen /* previous_profile && cxt->token != token */ 175c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen abort_creds(new); 176c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return -EACCES; 177c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen } 17877b071b34045a0c65d0e1f85f3d47fd2b8b7a8a1John Johansen cxt->profile = aa_get_newest_profile(profile); 179c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen /* clear exec on switching context */ 180c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_put_profile(cxt->onexec); 181c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen cxt->onexec = NULL; 182c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 183c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen commit_creds(new); 184c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return 0; 185c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen} 186c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 187c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen/** 188c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * aa_restore_previous_profile - exit from hat context restoring the profile 189c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * @token: the token that must be matched to exit hat context 190c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 191c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * Attempt to return out of a hat to the previous profile. The token 192c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * must match the stored token value. 193c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * 194c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen * Returns: 0 or error of failure 195c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen */ 196c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansenint aa_restore_previous_profile(u64 token) 197c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen{ 198c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen struct aa_task_cxt *cxt; 199c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen struct cred *new = prepare_creds(); 200c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen if (!new) 201c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return -ENOMEM; 202c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 203214beacaa7b669473bc963af719fa359a8312ea4John Johansen cxt = cred_cxt(new); 204c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen if (cxt->token != token) { 205c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen abort_creds(new); 206c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return -EACCES; 207c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen } 208c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen /* ignore restores when there is no saved profile */ 209c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen if (!cxt->previous) { 210c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen abort_creds(new); 211c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return 0; 212c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen } 213c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 214c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen aa_put_profile(cxt->profile); 21577b071b34045a0c65d0e1f85f3d47fd2b8b7a8a1John Johansen cxt->profile = aa_get_newest_profile(cxt->previous); 216c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen BUG_ON(!cxt->profile); 2177a2871b566f34d980556072943295efd107eb53cJohn Johansen /* clear exec && prev information when restoring to previous context */ 2187a2871b566f34d980556072943295efd107eb53cJohn Johansen aa_clear_task_cxt_trans(cxt); 219c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen 220c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen commit_creds(new); 221c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen return 0; 222c75afcd153f6147d3b094f45a1d87e5df7f4f053John Johansen} 223