/*
* AppArmor security module
*
* This file contains AppArmor LSM hooks.
*
* 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.
*/
#include <linux/lsm_hooks.h>
#include <linux/moduleparam.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/ptrace.h>
#include <linux/ctype.h>
#include <linux/sysctl.h>
#include <linux/audit.h>
#include <linux/user_namespace.h>
#include <net/sock.h>
#include "include/apparmor.h"
#include "include/apparmorfs.h"
#include "include/audit.h"
#include "include/capability.h"
#include "include/cred.h"
#include "include/file.h"
#include "include/ipc.h"
#include "include/net.h"
#include "include/path.h"
#include "include/label.h"
#include "include/policy.h"
#include "include/policy_ns.h"
#include "include/procattr.h"
#include "include/mount.h"
#include "include/secid.h"
/* Flag indicating whether initialization completed */
int apparmor_initialized;
DEFINE_PER_CPU(struct aa_buffers, aa_buffers);
/*
* LSM hook functions
*/
/*
* put the associated labels
*/
static void apparmor_cred_free(struct cred *cred)
{
aa_put_label(cred_label(cred));
cred_label(cred) = NULL;
}
/*
* allocate the apparmor part of blank credentials
*/
static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp)
{
cred_label(cred) = NULL;
return 0;
}
/*
* prepare new cred label for modification by prepare_cred block
*/
static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
gfp_t gfp)
{
cred_label(new) = aa_get_newest_label(cred_label(old));
return 0;
}
/*
* transfer the apparmor data to a blank set of creds
*/
static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
{
cred_label(new) = aa_get_newest_label(cred_label(old));
}
static void apparmor_task_free(struct task_struct *task)
{
aa_free_task_ctx(task_ctx(task));
task_ctx(task) = NULL;
}
static int apparmor_task_alloc(struct task_struct *task,
unsigned long clone_flags)
{
struct aa_task_ctx *new = aa_alloc_task_ctx(GFP_KERNEL);
if (!new)
return -ENOMEM;
aa_dup_task_ctx(new, task_ctx(current));
task_ctx(task) = new;
return 0;
}
static int apparmor_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
struct aa_label *tracer, *tracee;
int error;
tracer = begin_current_label_crit_section();
tracee = aa_get_task_label(child);
error = aa_may_ptrace(tracer, tracee,
(mode & PTRACE_MODE_READ) ? AA_PTRACE_READ
: AA_PTRACE_TRACE);
aa_put_label(tracee);
end_current_label_crit_section(tracer);
return error;
}
static int apparmor_ptrace_traceme(struct task_struct *parent)
{
struct aa_label *tracer, *tracee;
int error;
tracee = begin_current_label_crit_section();
tracer = aa_get_task_label(parent);
error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE);
aa_put_label(tracer);
end_current_label_crit_section(tracee);
return error;
}
/* Derived from security/commoncap.c:cap_capget */
static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
kernel_cap_t *inheritable, kernel_cap_t *permitted)
{
struct aa_label *label;
const struct cred *cred;
rcu_read_lock();
cred = __task_cred(target);
label = aa_get_newest_cred_label(cred);
/*
* cap_capget is stacked ahead of this and will
* initialize effective and permitted.
*/
if (!unconfined(label)) {
struct aa_profile *profile;
struct label_it i;
label_for_each_confined(i, label, profile) {
if (COMPLAIN_MODE(profile))
continue;
*effective = cap_intersect(*effective,
profile->caps.allow);
*permitted = cap_intersect(*permitted,
profile->caps.allow);
}
}
rcu_read_unlock();
aa_put_label(label);
return 0;
}
static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
int cap, int audit)
{
struct aa_label *label;
int error = 0;
label = aa_get_newest_cred_label(cred);
if (!unconfined(label))
error = aa_capable(label, cap, audit);
aa_put_label(label);
return error;
}
/**
* common_perm - basic common permission check wrapper fn for paths
* @op: operation being checked
* @path: path to check permission of (NOT NULL)
* @mask: requested permissions mask
* @cond: conditional in
|