Revert "UBUNTU: SAUCE: (no-up) apparmor: Sync to apparmor 3 - alpha 6 snapshot"

This reverts commit 77efcea8b0.
This commit is contained in:
Tim Gardner
2014-09-19 09:09:11 -06:00
parent cd0c514510
commit e08362475d
45 changed files with 1444 additions and 7865 deletions

View File

@@ -4,7 +4,7 @@
* This file contains basic common functions used in AppArmor
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2013 Canonical Ltd.
* 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
@@ -17,11 +17,9 @@
#include <linux/string.h>
#include <linux/vmalloc.h>
#include "include/apparmor.h"
#include "include/audit.h"
#include "include/label.h"
#include "include/perms.h"
#include "include/policy.h"
#include "include/apparmor.h"
/**
* aa_split_fqname - split a fqname into a profile and namespace name
@@ -47,10 +45,8 @@ char *aa_split_fqname(char *fqname, char **ns_name)
*ns_name = skip_spaces(&name[1]);
if (split) {
/* overwrite ':' with \0 */
*split++ = 0;
if (strncmp(split, "//", 2) == 0)
split += 2;
name = skip_spaces(split);
*split = 0;
name = skip_spaces(split + 1);
} else
/* a ns name without a following profile is allowed */
name = NULL;
@@ -68,24 +64,26 @@ char *aa_split_fqname(char *fqname, char **ns_name)
void aa_info_message(const char *str)
{
if (audit_enabled) {
DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, 0);
aad(&sa)->info = str;
struct common_audit_data sa;
struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
sa.aad = &aad;
aad.info = str;
aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
}
printk(KERN_INFO "AppArmor: %s\n", str);
}
/**
* __aa_kvmalloc - do allocation preferring kmalloc but falling back to vmalloc
* @size: how many bytes of memory are required
* @flags: the type of memory to allocate (see kmalloc).
* kvmalloc - do allocation preferring kmalloc but falling back to vmalloc
* @size: size of allocation
*
* Return: allocated buffer or NULL if failed
*
* It is possible that policy being loaded from the user is larger than
* what can be allocated by kmalloc, in those cases fall back to vmalloc.
*/
void *__aa_kvmalloc(size_t size, gfp_t flags)
void *kvmalloc(size_t size)
{
void *buffer = NULL;
@@ -94,12 +92,14 @@ void *__aa_kvmalloc(size_t size, gfp_t flags)
/* do not attempt kmalloc if we need more than 16 pages at once */
if (size <= (16*PAGE_SIZE))
buffer = kmalloc(size, flags | GFP_NOIO | __GFP_NOWARN);
buffer = kmalloc(size, GFP_NOIO | __GFP_NOWARN);
if (!buffer) {
if (flags & __GFP_ZERO)
buffer = vzalloc(size);
else
buffer = vmalloc(size);
/* see kvfree for why size must be at least work_struct size
* when allocated via vmalloc
*/
if (size < sizeof(struct work_struct))
size = sizeof(struct work_struct);
buffer = vmalloc(size);
}
return buffer;
}
@@ -135,263 +135,3 @@ void kvfree(void *buffer)
} else
kfree(buffer);
}
__counted char *aa_str_alloc(int size, gfp_t gfp)
{
struct counted_str *str;
str = kmalloc(sizeof(struct counted_str) + size, gfp);
if (!str)
return NULL;
kref_init(&str->count);
return str->name;
}
void aa_str_kref(struct kref *kref)
{
kfree(container_of(kref, struct counted_str, count));
}
/**
* aa_perm_mask_to_chr - convert a perm mask to its short string
* @mask: permission mask to convert
* @str: character buffer to store string in (at least 10 characters)
*/
void aa_perm_mask_to_chr(u32 mask, char *str)
{
if (mask & AA_EXEC_MMAP)
*str++ = 'm';
if (mask & MAY_READ)
*str++ = 'r';
if (mask & MAY_WRITE)
*str++ = 'w';
else if (mask & MAY_APPEND)
*str++ = 'a';
if (mask & AA_MAY_CREATE)
*str++ = 'c';
if (mask & AA_MAY_DELETE)
*str++ = 'd';
if (mask & AA_MAY_LINK)
*str++ = 'l';
if (mask & AA_MAY_LOCK)
*str++ = 'k';
if (mask & MAY_EXEC)
*str++ = 'x';
*str = '\0';
}
void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask)
{
char str[10];
aa_perm_mask_to_chr(mask, str);
audit_log_format(ab, "\"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\"", str,
mask & AA_MAY_OPEN ? " open" : "",
mask & AA_MAY_RENAME ? " rename" : "",
mask & AA_MAY_META_WRITE ? " metawrite" : "",
mask & AA_MAY_META_READ ? " metaread" : "",
mask & AA_MAY_GET_SECURITY ? " getsecurity" : "",
mask & AA_MAY_SET_SECURITY ? " setsecurity" : "",
mask & AA_MAY_CHMOD ? " chmod" : "",
mask & AA_MAY_CHOWN ? " chown" : "",
mask & AA_MAY_CHGRP ? " chgrp" : "",
mask & AA_MAY_MPROT_WX ? " mprot_wx" : "",
mask & AA_MAY_MPROT_XW ? " mprot_xw" : "",
mask & AA_MAY_SNAPSHOT ? " snapshot" : "",
mask & AA_MAY_STACK ? " stack" : "",
mask & AA_MAY_ONEXEC ? " onexec" : "",
mask & AA_MAY_CHANGE_PROFILE ? " change_profile" : "",
mask & AA_MAY_CHANGEHAT ? " change_hat" : "");
}
/**
* aa_audit_perms_cb - generic callback fn for auditing perms
* @ab: audit buffer (NOT NULL)
* @va: audit struct to audit values of (NOT NULL)
*/
static void aa_audit_perms_cb(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = va;
if (aad(sa)->request) {
audit_log_format(ab, " requested_mask=");
aa_audit_perm_mask(ab, aad(sa)->request);
}
if (aad(sa)->denied) {
audit_log_format(ab, "denied_mask=");
aa_audit_perm_mask(ab, aad(sa)->denied);
}
audit_log_format(ab, " target=");
audit_log_untrustedstring(ab, aad(sa)->target);
}
/**
* aa_apply_modes_to_perms - apply namespace and profile flags to perms
* @profile: that perms where computed from
* @perms: perms to apply mode modifiers to
*
* TODO: split into profile and ns based flags for when accumulating perms
*/
void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms)
{
switch (AUDIT_MODE(profile)) {
case AUDIT_ALL:
perms->audit = ALL_PERMS_MASK;
/* fall through */
case AUDIT_NOQUIET:
perms->quiet = 0;
break;
case AUDIT_QUIET:
perms->audit = 0;
/* fall through */
case AUDIT_QUIET_DENIED:
perms->quiet = ALL_PERMS_MASK;
break;
}
if (KILL_MODE(profile))
perms->kill = ALL_PERMS_MASK;
else if (COMPLAIN_MODE(profile))
perms->complain = ALL_PERMS_MASK;
}
void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
struct aa_perms *perms)
{
perms->deny = 0;
perms->kill = perms->stop = 0;
perms->complain = perms->cond = 0;
perms->hide = 0;
perms->allow = dfa_user_allow(dfa, state);
perms->audit = dfa_user_audit(dfa, state);
perms->quiet = dfa_user_quiet(dfa, state);
}
void aa_profile_match_label(struct aa_profile *profile, const char *label,
int type, struct aa_perms *perms)
{
/* TODO: doesn't yet handle extended types */
unsigned int state;
if (profile->policy.dfa) {
state = aa_dfa_next(profile->policy.dfa,
profile->policy.start[AA_CLASS_LABEL],
type);
state = aa_dfa_match(profile->policy.dfa, state, label);
aa_compute_perms(profile->policy.dfa, state, perms);
} else
memset(perms, 0, sizeof(*perms));
}
int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
u32 request, int type, u32 *deny,
struct common_audit_data *sa)
{
struct aa_perms perms;
aad(sa)->label = &profile->label;
aad(sa)->target = target;
aad(sa)->request = request;
aa_profile_match_label(profile, target->base.hname, type, &perms);
aa_apply_modes_to_perms(profile, &perms);
*deny |= request & perms.deny;
return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb);
}
/**
* aa_check_perms - do audit mode selection based on perms set
* @profile: profile being checked
* @perms: perms computed for the request
* @request: requested perms
* @deny: Returns: explicit deny set
* @sa: initialized audit structure (MAY BE NULL if not auditing)
* @cb: callback fn for tpye specific fields (MAY BE NULL)
*
* Returns: 0 if permission else error code
*
* Note: profile audit modes need to be set before calling by setting the
* perm masks appropriately.
*
* If not auditing then complain mode is not enabled and the
* error code will indicate whether there was an explicit deny
* with a positive value.
*/
int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
u32 request, struct common_audit_data *sa,
void (*cb) (struct audit_buffer *, void *))
{
int type, error;
bool stop = false;
u32 denied = request & (~perms->allow | perms->deny);
if (likely(!denied)) {
/* mask off perms that are not being force audited */
request &= perms->audit;
if (!request || !sa)
return 0;
type = AUDIT_APPARMOR_AUDIT;
error = 0;
} else {
error = -EACCES;
if (denied & perms->kill)
type = AUDIT_APPARMOR_KILL;
else if (denied == (denied & perms->complain))
type = AUDIT_APPARMOR_ALLOWED;
else
type = AUDIT_APPARMOR_DENIED;
if (denied & perms->stop)
stop = true;
if (denied == (denied & perms->hide))
error = -ENOENT;
denied &= ~perms->quiet;
if (type != AUDIT_APPARMOR_ALLOWED && (!sa || !denied))
return error;
}
if (sa) {
aad(sa)->label = &profile->label;
aad(sa)->request = request;
aad(sa)->denied = denied;
aad(sa)->error = error;
aa_audit_msg(type, sa, cb);
}
if (type == AUDIT_APPARMOR_ALLOWED)
error = 0;
return error;
}
const char *aa_imode_name(umode_t mode)
{
switch(mode & S_IFMT) {
case S_IFSOCK:
return "sock";
case S_IFLNK:
return "link";
case S_IFREG:
return "reg";
case S_IFBLK:
return "blkdev";
case S_IFDIR:
return "dir";
case S_IFCHR:
return "chrdev";
case S_IFIFO:
return "fifo";
}
return "unknown";
}
const char *aa_peer_name(struct aa_profile *peer)
{
if (profile_unconfined(peer))
return "unconfined";
return peer->base.hname;
}