linux/security/apparmor/audit.c
<<
>>
Prefs
   1/*
   2 * AppArmor security module
   3 *
   4 * This file contains AppArmor auditing functions
   5 *
   6 * Copyright (C) 1998-2008 Novell/SUSE
   7 * Copyright 2009-2010 Canonical Ltd.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation, version 2 of the
  12 * License.
  13 */
  14
  15#include <linux/audit.h>
  16#include <linux/socket.h>
  17
  18#include "include/apparmor.h"
  19#include "include/audit.h"
  20#include "include/policy.h"
  21#include "include/policy_ns.h"
  22#include "include/secid.h"
  23
  24const char *const audit_mode_names[] = {
  25        "normal",
  26        "quiet_denied",
  27        "quiet",
  28        "noquiet",
  29        "all"
  30};
  31
  32static const char *const aa_audit_type[] = {
  33        "AUDIT",
  34        "ALLOWED",
  35        "DENIED",
  36        "HINT",
  37        "STATUS",
  38        "ERROR",
  39        "KILLED",
  40        "AUTO"
  41};
  42
  43/*
  44 * Currently AppArmor auditing is fed straight into the audit framework.
  45 *
  46 * TODO:
  47 * netlink interface for complain mode
  48 * user auditing, - send user auditing to netlink interface
  49 * system control of whether user audit messages go to system log
  50 */
  51
  52/**
  53 * audit_base - core AppArmor function.
  54 * @ab: audit buffer to fill (NOT NULL)
  55 * @ca: audit structure containing data to audit (NOT NULL)
  56 *
  57 * Record common AppArmor audit data from @sa
  58 */
  59static void audit_pre(struct audit_buffer *ab, void *ca)
  60{
  61        struct common_audit_data *sa = ca;
  62
  63        if (aa_g_audit_header) {
  64                audit_log_format(ab, "apparmor=\"%s\"",
  65                                 aa_audit_type[aad(sa)->type]);
  66        }
  67
  68        if (aad(sa)->op) {
  69                audit_log_format(ab, " operation=\"%s\"", aad(sa)->op);
  70        }
  71
  72        if (aad(sa)->info) {
  73                audit_log_format(ab, " info=\"%s\"", aad(sa)->info);
  74                if (aad(sa)->error)
  75                        audit_log_format(ab, " error=%d", aad(sa)->error);
  76        }
  77
  78        if (aad(sa)->label) {
  79                struct aa_label *label = aad(sa)->label;
  80
  81                if (label_isprofile(label)) {
  82                        struct aa_profile *profile = labels_profile(label);
  83
  84                        if (profile->ns != root_ns) {
  85                                audit_log_format(ab, " namespace=");
  86                                audit_log_untrustedstring(ab,
  87                                                       profile->ns->base.hname);
  88                        }
  89                        audit_log_format(ab, " profile=");
  90                        audit_log_untrustedstring(ab, profile->base.hname);
  91                } else {
  92                        audit_log_format(ab, " label=");
  93                        aa_label_xaudit(ab, root_ns, label, FLAG_VIEW_SUBNS,
  94                                        GFP_ATOMIC);
  95                }
  96        }
  97
  98        if (aad(sa)->name) {
  99                audit_log_format(ab, " name=");
 100                audit_log_untrustedstring(ab, aad(sa)->name);
 101        }
 102}
 103
 104/**
 105 * aa_audit_msg - Log a message to the audit subsystem
 106 * @sa: audit event structure (NOT NULL)
 107 * @cb: optional callback fn for type specific fields (MAYBE NULL)
 108 */
 109void aa_audit_msg(int type, struct common_audit_data *sa,
 110                  void (*cb) (struct audit_buffer *, void *))
 111{
 112        aad(sa)->type = type;
 113        common_lsm_audit(sa, audit_pre, cb);
 114}
 115
 116/**
 117 * aa_audit - Log a profile based audit event to the audit subsystem
 118 * @type: audit type for the message
 119 * @profile: profile to check against (NOT NULL)
 120 * @sa: audit event (NOT NULL)
 121 * @cb: optional callback fn for type specific fields (MAYBE NULL)
 122 *
 123 * Handle default message switching based off of audit mode flags
 124 *
 125 * Returns: error on failure
 126 */
 127int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
 128             void (*cb) (struct audit_buffer *, void *))
 129{
 130        AA_BUG(!profile);
 131
 132        if (type == AUDIT_APPARMOR_AUTO) {
 133                if (likely(!aad(sa)->error)) {
 134                        if (AUDIT_MODE(profile) != AUDIT_ALL)
 135                                return 0;
 136                        type = AUDIT_APPARMOR_AUDIT;
 137                } else if (COMPLAIN_MODE(profile))
 138                        type = AUDIT_APPARMOR_ALLOWED;
 139                else
 140                        type = AUDIT_APPARMOR_DENIED;
 141        }
 142        if (AUDIT_MODE(profile) == AUDIT_QUIET ||
 143            (type == AUDIT_APPARMOR_DENIED &&
 144             AUDIT_MODE(profile) == AUDIT_QUIET))
 145                return aad(sa)->error;
 146
 147        if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
 148                type = AUDIT_APPARMOR_KILL;
 149
 150        aad(sa)->label = &profile->label;
 151
 152        aa_audit_msg(type, sa, cb);
 153
 154        if (aad(sa)->type == AUDIT_APPARMOR_KILL)
 155                (void)send_sig_info(SIGKILL, NULL,
 156                        sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
 157                                    sa->u.tsk : current);
 158
 159        if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED)
 160                return complain_error(aad(sa)->error);
 161
 162        return aad(sa)->error;
 163}
 164
 165struct aa_audit_rule {
 166        struct aa_label *label;
 167};
 168
 169void aa_audit_rule_free(void *vrule)
 170{
 171        struct aa_audit_rule *rule = vrule;
 172
 173        if (rule) {
 174                if (!IS_ERR(rule->label))
 175                        aa_put_label(rule->label);
 176                kfree(rule);
 177        }
 178}
 179
 180int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 181{
 182        struct aa_audit_rule *rule;
 183
 184        switch (field) {
 185        case AUDIT_SUBJ_ROLE:
 186                if (op != Audit_equal && op != Audit_not_equal)
 187                        return -EINVAL;
 188                break;
 189        default:
 190                return -EINVAL;
 191        }
 192
 193        rule = kzalloc(sizeof(struct aa_audit_rule), GFP_KERNEL);
 194
 195        if (!rule)
 196                return -ENOMEM;
 197
 198        /* Currently rules are treated as coming from the root ns */
 199        rule->label = aa_label_parse(&root_ns->unconfined->label, rulestr,
 200                                     GFP_KERNEL, true, false);
 201        if (IS_ERR(rule->label)) {
 202                aa_audit_rule_free(rule);
 203                return PTR_ERR(rule->label);
 204        }
 205
 206        *vrule = rule;
 207        return 0;
 208}
 209
 210int aa_audit_rule_known(struct audit_krule *rule)
 211{
 212        int i;
 213
 214        for (i = 0; i < rule->field_count; i++) {
 215                struct audit_field *f = &rule->fields[i];
 216
 217                switch (f->type) {
 218                case AUDIT_SUBJ_ROLE:
 219                        return 1;
 220                }
 221        }
 222
 223        return 0;
 224}
 225
 226int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
 227{
 228        struct aa_audit_rule *rule = vrule;
 229        struct aa_label *label;
 230        int found = 0;
 231
 232        label = aa_secid_to_label(sid);
 233
 234        if (!label)
 235                return -ENOENT;
 236
 237        if (aa_label_is_subset(label, rule->label))
 238                found = 1;
 239
 240        switch (field) {
 241        case AUDIT_SUBJ_ROLE:
 242                switch (op) {
 243                case Audit_equal:
 244                        return found;
 245                case Audit_not_equal:
 246                        return !found;
 247                }
 248        }
 249        return 0;
 250}
 251