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