Commit 74d06fb7 authored by Tyler Hicks's avatar Tyler Hicks Committed by Tim Gardner

UBUNTU: SAUCE: add a sysctl to enable unprivileged user ns AppArmor policy loading

BugLink: http://bugs.launchpad.net/bugs/1379535

Disabled by default until the AppArmor kernel code is deemed safe enough
to handle untrusted policy. Only developers of container technologies
should turn this on until that time.

If this sysctl is set to non-zero and a process with CAP_MAC_ADMIN in
the root namespace has created an AppArmor policy namespace,
unprivileged processes will be able to change to a profile in the
newly created AppArmor policy namespace and, if the profile allows
CAP_MAC_ADMIN and appropriate file permissions, will be able to load
policy in the respective policy namespace.
Signed-off-by: default avatarTyler Hicks <tyhicks@canonical.com>
Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>
parent a3c6147c
......@@ -34,6 +34,8 @@
struct aa_ns;
extern int unprivileged_userns_apparmor_policy;
extern const char *const aa_profile_mode_names[];
#define APPARMOR_MODE_NAMES_MAX_INDEX 4
......
......@@ -23,6 +23,7 @@
#include <linux/sysctl.h>
#include <linux/audit.h>
#include <linux/user_namespace.h>
#include <linux/kmemleak.h>
#include <net/sock.h>
#include "include/af_unix.h"
......@@ -1532,6 +1533,46 @@ static int __init alloc_buffers(void)
return 0;
}
#ifdef CONFIG_SYSCTL
static int apparmor_dointvec(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
if (!policy_admin_capable())
return -EPERM;
if (!apparmor_enabled)
return -EINVAL;
return proc_dointvec(table, write, buffer, lenp, ppos);
}
static struct ctl_path apparmor_sysctl_path[] = {
{ .procname = "kernel", },
{ }
};
static struct ctl_table apparmor_sysctl_table[] = {
{
.procname = "unprivileged_userns_apparmor_policy",
.data = &unprivileged_userns_apparmor_policy,
.maxlen = sizeof(int),
.mode = 0600,
.proc_handler = apparmor_dointvec,
},
{ }
};
static int __init apparmor_init_sysctl(void)
{
return register_sysctl_paths(apparmor_sysctl_path,
apparmor_sysctl_table) ? 0 : -ENOMEM;
}
#else
static inline int apparmor_init_sysctl(void)
{
return 0;
}
#endif /* CONFIG_SYSCTL */
static int __init apparmor_init(void)
{
int error;
......@@ -1554,6 +1595,13 @@ static int __init apparmor_init(void)
goto alloc_out;
}
error = apparmor_init_sysctl();
if (error) {
AA_ERROR("Unable to register sysctls\n");
goto alloc_out;
}
error = alloc_buffers();
if (error) {
AA_ERROR("Unable to allocate work buffers\n");
......
......@@ -90,6 +90,7 @@
#include "include/policy_unpack.h"
#include "include/resource.h"
int unprivileged_userns_apparmor_policy = 0;
/* Note: mode names must be unique in the first character because of
* modechrs used to print modes on compound labels on some interfaces
......@@ -624,7 +625,8 @@ bool policy_admin_capable(void)
if (ns_capable(user_ns, CAP_MAC_ADMIN) &&
(user_ns == &init_user_ns ||
(user_ns->level == 1 && ns != root_ns)))
(unprivileged_userns_apparmor_policy != 0 &&
user_ns->level == 1 && ns != root_ns)))
response = true;
aa_put_ns(ns);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment