Commit 67012e8209df95a8290d135753ff5145431a666e

Authored by John Johansen
Committed by James Morris
1 parent cdff264264

AppArmor: basic auditing infrastructure.

Update lsm_audit for AppArmor specific data, and add the core routines for
AppArmor uses for auditing.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: James Morris <jmorris@namei.org>

Showing 3 changed files with 365 additions and 0 deletions Side-by-side Diff

include/linux/lsm_audit.h
... ... @@ -99,6 +99,33 @@
99 99 int result;
100 100 } selinux_audit_data;
101 101 #endif
  102 +#ifdef CONFIG_SECURITY_APPARMOR
  103 + struct {
  104 + int error;
  105 + int op;
  106 + int type;
  107 + void *profile;
  108 + const char *name;
  109 + const char *info;
  110 + union {
  111 + void *target;
  112 + struct {
  113 + long pos;
  114 + void *target;
  115 + } iface;
  116 + struct {
  117 + int rlim;
  118 + unsigned long max;
  119 + } rlim;
  120 + struct {
  121 + const char *target;
  122 + u32 request;
  123 + u32 denied;
  124 + uid_t ouid;
  125 + } fs;
  126 + };
  127 + } apparmor_audit_data;
  128 +#endif
102 129 };
103 130 /* these callback will be implemented by a specific LSM */
104 131 void (*lsm_pre_audit)(struct audit_buffer *, void *);
security/apparmor/audit.c
  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 +
  22 +const char *op_table[] = {
  23 + "null",
  24 +
  25 + "sysctl",
  26 + "capable",
  27 +
  28 + "unlink",
  29 + "mkdir",
  30 + "rmdir",
  31 + "mknod",
  32 + "truncate",
  33 + "link",
  34 + "symlink",
  35 + "rename_src",
  36 + "rename_dest",
  37 + "chmod",
  38 + "chown",
  39 + "getattr",
  40 + "open",
  41 +
  42 + "file_perm",
  43 + "file_lock",
  44 + "file_mmap",
  45 + "file_mprotect",
  46 +
  47 + "create",
  48 + "post_create",
  49 + "bind",
  50 + "connect",
  51 + "listen",
  52 + "accept",
  53 + "sendmsg",
  54 + "recvmsg",
  55 + "getsockname",
  56 + "getpeername",
  57 + "getsockopt",
  58 + "setsockopt",
  59 + "socket_shutdown",
  60 +
  61 + "ptrace",
  62 +
  63 + "exec",
  64 + "change_hat",
  65 + "change_profile",
  66 + "change_onexec",
  67 +
  68 + "setprocattr",
  69 + "setrlimit",
  70 +
  71 + "profile_replace",
  72 + "profile_load",
  73 + "profile_remove"
  74 +};
  75 +
  76 +const char *audit_mode_names[] = {
  77 + "normal",
  78 + "quiet_denied",
  79 + "quiet",
  80 + "noquiet",
  81 + "all"
  82 +};
  83 +
  84 +static char *aa_audit_type[] = {
  85 + "AUDIT",
  86 + "ALLOWED",
  87 + "DENIED",
  88 + "HINT",
  89 + "STATUS",
  90 + "ERROR",
  91 + "KILLED"
  92 +};
  93 +
  94 +/*
  95 + * Currently AppArmor auditing is fed straight into the audit framework.
  96 + *
  97 + * TODO:
  98 + * netlink interface for complain mode
  99 + * user auditing, - send user auditing to netlink interface
  100 + * system control of whether user audit messages go to system log
  101 + */
  102 +
  103 +/**
  104 + * audit_base - core AppArmor function.
  105 + * @ab: audit buffer to fill (NOT NULL)
  106 + * @ca: audit structure containing data to audit (NOT NULL)
  107 + *
  108 + * Record common AppArmor audit data from @sa
  109 + */
  110 +static void audit_pre(struct audit_buffer *ab, void *ca)
  111 +{
  112 + struct common_audit_data *sa = ca;
  113 + struct task_struct *tsk = sa->tsk ? sa->tsk : current;
  114 +
  115 + if (aa_g_audit_header) {
  116 + audit_log_format(ab, "apparmor=");
  117 + audit_log_string(ab, aa_audit_type[sa->aad.type]);
  118 + }
  119 +
  120 + if (sa->aad.op) {
  121 + audit_log_format(ab, " operation=");
  122 + audit_log_string(ab, op_table[sa->aad.op]);
  123 + }
  124 +
  125 + if (sa->aad.info) {
  126 + audit_log_format(ab, " info=");
  127 + audit_log_string(ab, sa->aad.info);
  128 + if (sa->aad.error)
  129 + audit_log_format(ab, " error=%d", sa->aad.error);
  130 + }
  131 +
  132 + if (sa->aad.profile) {
  133 + struct aa_profile *profile = sa->aad.profile;
  134 + pid_t pid;
  135 + rcu_read_lock();
  136 + pid = tsk->real_parent->pid;
  137 + rcu_read_unlock();
  138 + audit_log_format(ab, " parent=%d", pid);
  139 + if (profile->ns != root_ns) {
  140 + audit_log_format(ab, " namespace=");
  141 + audit_log_untrustedstring(ab, profile->ns->base.hname);
  142 + }
  143 + audit_log_format(ab, " profile=");
  144 + audit_log_untrustedstring(ab, profile->base.hname);
  145 + }
  146 +
  147 + if (sa->aad.name) {
  148 + audit_log_format(ab, " name=");
  149 + audit_log_untrustedstring(ab, sa->aad.name);
  150 + }
  151 +}
  152 +
  153 +/**
  154 + * aa_audit_msg - Log a message to the audit subsystem
  155 + * @sa: audit event structure (NOT NULL)
  156 + * @cb: optional callback fn for type specific fields (MAYBE NULL)
  157 + */
  158 +void aa_audit_msg(int type, struct common_audit_data *sa,
  159 + void (*cb) (struct audit_buffer *, void *))
  160 +{
  161 + sa->aad.type = type;
  162 + sa->lsm_pre_audit = audit_pre;
  163 + sa->lsm_post_audit = cb;
  164 + common_lsm_audit(sa);
  165 +}
  166 +
  167 +/**
  168 + * aa_audit - Log a profile based audit event to the audit subsystem
  169 + * @type: audit type for the message
  170 + * @profile: profile to check against (NOT NULL)
  171 + * @gfp: allocation flags to use
  172 + * @sa: audit event (NOT NULL)
  173 + * @cb: optional callback fn for type specific fields (MAYBE NULL)
  174 + *
  175 + * Handle default message switching based off of audit mode flags
  176 + *
  177 + * Returns: error on failure
  178 + */
  179 +int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
  180 + struct common_audit_data *sa,
  181 + void (*cb) (struct audit_buffer *, void *))
  182 +{
  183 + BUG_ON(!profile);
  184 +
  185 + if (type == AUDIT_APPARMOR_AUTO) {
  186 + if (likely(!sa->aad.error)) {
  187 + if (AUDIT_MODE(profile) != AUDIT_ALL)
  188 + return 0;
  189 + type = AUDIT_APPARMOR_AUDIT;
  190 + } else if (COMPLAIN_MODE(profile))
  191 + type = AUDIT_APPARMOR_ALLOWED;
  192 + else
  193 + type = AUDIT_APPARMOR_DENIED;
  194 + }
  195 + if (AUDIT_MODE(profile) == AUDIT_QUIET ||
  196 + (type == AUDIT_APPARMOR_DENIED &&
  197 + AUDIT_MODE(profile) == AUDIT_QUIET))
  198 + return sa->aad.error;
  199 +
  200 + if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
  201 + type = AUDIT_APPARMOR_KILL;
  202 +
  203 + if (!unconfined(profile))
  204 + sa->aad.profile = profile;
  205 +
  206 + aa_audit_msg(type, sa, cb);
  207 +
  208 + if (sa->aad.type == AUDIT_APPARMOR_KILL)
  209 + (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
  210 +
  211 + if (sa->aad.type == AUDIT_APPARMOR_ALLOWED)
  212 + return complain_error(sa->aad.error);
  213 +
  214 + return sa->aad.error;
  215 +}
security/apparmor/include/audit.h
  1 +/*
  2 + * AppArmor security module
  3 + *
  4 + * This file contains AppArmor auditing function definitions.
  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 +#ifndef __AA_AUDIT_H
  16 +#define __AA_AUDIT_H
  17 +
  18 +#include <linux/audit.h>
  19 +#include <linux/fs.h>
  20 +#include <linux/lsm_audit.h>
  21 +#include <linux/sched.h>
  22 +#include <linux/slab.h>
  23 +
  24 +#include "file.h"
  25 +
  26 +struct aa_profile;
  27 +
  28 +extern const char *audit_mode_names[];
  29 +#define AUDIT_MAX_INDEX 5
  30 +
  31 +#define AUDIT_APPARMOR_AUTO 0 /* auto choose audit message type */
  32 +
  33 +enum audit_mode {
  34 + AUDIT_NORMAL, /* follow normal auditing of accesses */
  35 + AUDIT_QUIET_DENIED, /* quiet all denied access messages */
  36 + AUDIT_QUIET, /* quiet all messages */
  37 + AUDIT_NOQUIET, /* do not quiet audit messages */
  38 + AUDIT_ALL /* audit all accesses */
  39 +};
  40 +
  41 +enum audit_type {
  42 + AUDIT_APPARMOR_AUDIT,
  43 + AUDIT_APPARMOR_ALLOWED,
  44 + AUDIT_APPARMOR_DENIED,
  45 + AUDIT_APPARMOR_HINT,
  46 + AUDIT_APPARMOR_STATUS,
  47 + AUDIT_APPARMOR_ERROR,
  48 + AUDIT_APPARMOR_KILL
  49 +};
  50 +
  51 +extern const char *op_table[];
  52 +enum aa_ops {
  53 + OP_NULL,
  54 +
  55 + OP_SYSCTL,
  56 + OP_CAPABLE,
  57 +
  58 + OP_UNLINK,
  59 + OP_MKDIR,
  60 + OP_RMDIR,
  61 + OP_MKNOD,
  62 + OP_TRUNC,
  63 + OP_LINK,
  64 + OP_SYMLINK,
  65 + OP_RENAME_SRC,
  66 + OP_RENAME_DEST,
  67 + OP_CHMOD,
  68 + OP_CHOWN,
  69 + OP_GETATTR,
  70 + OP_OPEN,
  71 +
  72 + OP_FPERM,
  73 + OP_FLOCK,
  74 + OP_FMMAP,
  75 + OP_FMPROT,
  76 +
  77 + OP_CREATE,
  78 + OP_POST_CREATE,
  79 + OP_BIND,
  80 + OP_CONNECT,
  81 + OP_LISTEN,
  82 + OP_ACCEPT,
  83 + OP_SENDMSG,
  84 + OP_RECVMSG,
  85 + OP_GETSOCKNAME,
  86 + OP_GETPEERNAME,
  87 + OP_GETSOCKOPT,
  88 + OP_SETSOCKOPT,
  89 + OP_SOCK_SHUTDOWN,
  90 +
  91 + OP_PTRACE,
  92 +
  93 + OP_EXEC,
  94 + OP_CHANGE_HAT,
  95 + OP_CHANGE_PROFILE,
  96 + OP_CHANGE_ONEXEC,
  97 +
  98 + OP_SETPROCATTR,
  99 + OP_SETRLIMIT,
  100 +
  101 + OP_PROF_REPL,
  102 + OP_PROF_LOAD,
  103 + OP_PROF_RM,
  104 +};
  105 +
  106 +
  107 +/* define a short hand for apparmor_audit_data portion of common_audit_data */
  108 +#define aad apparmor_audit_data
  109 +
  110 +void aa_audit_msg(int type, struct common_audit_data *sa,
  111 + void (*cb) (struct audit_buffer *, void *));
  112 +int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
  113 + struct common_audit_data *sa,
  114 + void (*cb) (struct audit_buffer *, void *));
  115 +
  116 +static inline int complain_error(int error)
  117 +{
  118 + if (error == -EPERM || error == -EACCES)
  119 + return 0;
  120 + return error;
  121 +}
  122 +
  123 +#endif /* __AA_AUDIT_H */