/*
* 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"
#include "include/sid.h"
/* root profile namespace */
struct aa_namespace *root_ns;
const char *profile_mode_names[] = {
"enforce",
"complain",
"kill",
};
/**
* hname_tail - find the last component of an hname
* @name: hname to find the base profile name component of (NOT NULL)
*
* Returns: the tail (base profile name) name component of an hname
*/
static const char *hname_tail(const char *hname)
{
char *split;
hname = strim((char *)hname);
for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
hname = split + 2;
return hname;
}
/**
* policy_init - initialize a policy structure
* @policy: policy to initialize (NOT NULL)
* @prefix: prefix name if any is required. (MAYBE NULL)
* @name: name of the policy, init will make a copy of it (NOT NULL)
*
* Note: this fn creates a copy of strings passed in
*
* Returns: true if policy init successful
*/
static bool policy_init(struct aa_policy *policy, const char *prefix,
const char *name)
{
/* freed by policy_free */
if (prefix) {
policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3,
GFP_KERNEL);
if (policy->hname)
sprintf(policy->hname, "%s//%s", prefix, name);
} else
policy->hname = kstrdup(name, GFP_KERNEL);
if (!policy->hname)
return 0;
/* base.name is a substring of fqname */
policy->name = (char *)hname_tail(policy->hname);
INIT_LIST_HEAD(&policy->list);
INIT_LIST_HEAD(&policy->profiles);
kref_init(&policy->count);
return 1;
}
/**
* policy_destroy - free the elements referenced by @policy
* @policy: policy that is to have its elements freed (NOT NULL)
*/
static void policy_destroy(struct aa_policy *policy)
{
/* still contains profiles -- invalid */
if (!list_empty(&policy->profiles)) {