/*
* AppArmor security module
*
* This file contains AppArmor policy manipulation functions
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2010 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
*
* AppArmor policy is based around profiles, which contain the rules a
* task is confined by. Every task in the system has a profile attached
* to it determined either by matching "unconfined" tasks against the
* visible set of profiles or by following a profiles attachment rules.
*
* Each profile exists in a profile namespace which is a container of
* visible profiles. Each namespace contains a special "unconfined" profile,
* which doesn't enforce any confinement on a task beyond DAC.
*
* Namespace and profile names can be written together in either
* of two syntaxes.
* :namespace:profile - used by kernel interfaces for easy detection
* namespace://profile - used by policy
*
* Profile names can not start with : or @ or ^ and may not contain \0
*
* Reserved profile names
* unconfined - special automatically generated unconfined profile
* inherit - special name to indicate profile inheritance
* null-XXXX-YYYY - special automatically generated learning profiles
*
* Namespace names may not start with / or @ and may not contain \0 or :
* Reserved namespace names
* user-XXXX - user defined profiles
*
* a // in a profile or namespace name indicates a hierarchical name with the
* name before the // being the parent and the name after the child.
*
* Profile and namespace hierarchies serve two different but similar purposes.
* The namespace contains the set of visible profiles that are considered
* for attachment. The hierarchy of namespaces allows for virtualizing
* the namespace so that for example a chroot can have its own set of profiles
* which may define some local user namespaces.
* The profile hierarchy severs two distinct purposes,
* - it allows for sub profiles or hats, which allows an application to run
* subprograms under its own profile with different restriction than it
* self, and not have it use the system profile.
* eg. if a mail program starts an editor, the policy might make the
* restrictions tighter on the editor tighter than the mail program,
* and definitely different than general editor restrictions
* - it allows for binary hierarchy of profiles, so that execution history
* is preserved. This feature isn't exploited by AppArmor reference policy
* but is allowed. NOTE: this is currently suboptimal because profile
* aliasing is not currently implemented so that a profile for each
* level must be defined.
* eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
* from /bin/bash
*
* A profile or namespace name that can contain one or more // separators
* is referred to as an hname (hierarchical).
* eg. /bin/bash//bin/ls
*
* An fqname is a name that may contain both namespace and profile hnames.
* eg. :ns:/bin/bash//bin/ls
*
* NOTES:
* - locking of profile lists is currently fairly coarse. All profile
* lists within a namespace use the namespace lock.
* FIXME: move profile lists to using rcu_lists
*/
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include "include/apparmor.h"
#include "include/capability.h"
#include "include/context.h"
#include "include/file.h"
#include "include/ipc.h"
#include "include/match.h"
#include "include/path.h"
#include "include/policy.h"
#include "include/policy_unpack.h"
#include "include/resource.h"
/* root profile namespace */
struct aa_namespace *root_ns;
const char *const aa_profile_mode_names[] = {
"enforce",
"complain",
"kill",
"unconfined",
};
/*
* Routines for AppArmor namespaces
*/
static const char *hidden_ns_name = "---";
/**
* aa_ns_visible - test if @view is visible from @curr
* @curr: namespace to treat as the parent (NOT NULL)
* @view: namespace to test if visible from @curr (NOT NULL)
*
* Returns: true if @view is visible from @curr else false
*/
bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view)
{
if (curr == view)
return true;
for ( ; view; view = view->parent) {
if (view->parent == curr)
return true;
}
return false;
}
/**
* aa_na_name - Find the ns name to display for @view from @curr
* @curr - current namespace (NOT NULL)
* @view - namespace attempting to view (NOT NULL)
*
* Returns: name of @view visible from @curr
*/
const char *aa_ns_name(struct aa_namespace *curr, struct aa_namespace *view)
{
/* if view == curr then the namespace name isn't displayed */
if (curr == view)
return "";
if (aa_ns_visible(curr, view)) {
/* at this point if a ns is visible it is in a view ns
* thus the curr ns.hname is a prefix of its name.
* Only output the virtualized portion of the name
* Add + 2 to skip over // separating curr hname prefix
* from the visible tail of the views hname
*/
return view->base.hname + strlen(curr->base.hname) + 2;
} else
return hidden_ns_name;
}
/**
* alloc_namespace - allocate, initialize and return a new namespace
* @prefix: parent namespace name (MAYBE NULL)
* @name: a preallocated name (NOT NULL)
*
* Returns: refcounted namespace or NULL on failure.
*/
static struct aa_namespace *alloc_namespace(const char *prefix,
const char *name)
{
struct aa_namespace *ns;
ns = kzalloc(