linux/security/apparmor/ipc.c
<<
>>
Prefs
   1/*
   2 * AppArmor security module
   3 *
   4 * This file contains AppArmor ipc mediation
   5 *
   6 * Copyright (C) 1998-2008 Novell/SUSE
   7 * Copyright 2009-2017 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/gfp.h>
  16#include <linux/ptrace.h>
  17
  18#include "include/audit.h"
  19#include "include/capability.h"
  20#include "include/cred.h"
  21#include "include/policy.h"
  22#include "include/ipc.h"
  23#include "include/sig_names.h"
  24
  25/**
  26 * audit_ptrace_mask - convert mask to permission string
  27 * @buffer: buffer to write string to (NOT NULL)
  28 * @mask: permission mask to convert
  29 */
  30static void audit_ptrace_mask(struct audit_buffer *ab, u32 mask)
  31{
  32        switch (mask) {
  33        case MAY_READ:
  34                audit_log_string(ab, "read");
  35                break;
  36        case MAY_WRITE:
  37                audit_log_string(ab, "trace");
  38                break;
  39        case AA_MAY_BE_READ:
  40                audit_log_string(ab, "readby");
  41                break;
  42        case AA_MAY_BE_TRACED:
  43                audit_log_string(ab, "tracedby");
  44                break;
  45        }
  46}
  47
  48/* call back to audit ptrace fields */
  49static void audit_ptrace_cb(struct audit_buffer *ab, void *va)
  50{
  51        struct common_audit_data *sa = va;
  52
  53        if (aad(sa)->request & AA_PTRACE_PERM_MASK) {
  54                audit_log_format(ab, " requested_mask=");
  55                audit_ptrace_mask(ab, aad(sa)->request);
  56
  57                if (aad(sa)->denied & AA_PTRACE_PERM_MASK) {
  58                        audit_log_format(ab, " denied_mask=");
  59                        audit_ptrace_mask(ab, aad(sa)->denied);
  60                }
  61        }
  62        audit_log_format(ab, " peer=");
  63        aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
  64                        FLAGS_NONE, GFP_ATOMIC);
  65}
  66
  67/* assumes check for PROFILE_MEDIATES is already done */
  68/* TODO: conditionals */
  69static int profile_ptrace_perm(struct aa_profile *profile,
  70                             struct aa_label *peer, u32 request,
  71                             struct common_audit_data *sa)
  72{
  73        struct aa_perms perms = { };
  74
  75        aad(sa)->peer = peer;
  76        aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request,
  77                               &perms);
  78        aa_apply_modes_to_perms(profile, &perms);
  79        return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb);
  80}
  81
  82static int profile_tracee_perm(struct aa_profile *tracee,
  83                               struct aa_label *tracer, u32 request,
  84                               struct common_audit_data *sa)
  85{
  86        if (profile_unconfined(tracee) || unconfined(tracer) ||
  87            !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE))
  88                return 0;
  89
  90        return profile_ptrace_perm(tracee, tracer, request, sa);
  91}
  92
  93static int profile_tracer_perm(struct aa_profile *tracer,
  94                               struct aa_label *tracee, u32 request,
  95                               struct common_audit_data *sa)
  96{
  97        if (profile_unconfined(tracer))
  98                return 0;
  99
 100        if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE))
 101                return profile_ptrace_perm(tracer, tracee, request, sa);
 102
 103        /* profile uses the old style capability check for ptrace */
 104        if (&tracer->label == tracee)
 105                return 0;
 106
 107        aad(sa)->label = &tracer->label;
 108        aad(sa)->peer = tracee;
 109        aad(sa)->request = 0;
 110        aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 1);
 111
 112        return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb);
 113}
 114
 115/**
 116 * aa_may_ptrace - test if tracer task can trace the tracee
 117 * @tracer: label of the task doing the tracing  (NOT NULL)
 118 * @tracee: task label to be traced
 119 * @request: permission request
 120 *
 121 * Returns: %0 else error code if permission denied or error
 122 */
 123int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
 124                  u32 request)
 125{
 126        struct aa_profile *profile;
 127        u32 xrequest = request << PTRACE_PERM_SHIFT;
 128        DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE);
 129
 130        return xcheck_labels(tracer, tracee, profile,
 131                        profile_tracer_perm(profile, tracee, request, &sa),
 132                        profile_tracee_perm(profile, tracer, xrequest, &sa));
 133}
 134
 135
 136static inline int map_signal_num(int sig)
 137{
 138        if (sig > SIGRTMAX)
 139                return SIGUNKNOWN;
 140        else if (sig >= SIGRTMIN)
 141                return sig - SIGRTMIN + SIGRT_BASE;
 142        else if (sig < MAXMAPPED_SIG)
 143                return sig_map[sig];
 144        return SIGUNKNOWN;
 145}
 146
 147/**
 148 * audit_file_mask - convert mask to permission string
 149 * @buffer: buffer to write string to (NOT NULL)
 150 * @mask: permission mask to convert
 151 */
 152static void audit_signal_mask(struct audit_buffer *ab, u32 mask)
 153{
 154        if (mask & MAY_READ)
 155                audit_log_string(ab, "receive");
 156        if (mask & MAY_WRITE)
 157                audit_log_string(ab, "send");
 158}
 159
 160/**
 161 * audit_cb - call back for signal specific audit fields
 162 * @ab: audit_buffer  (NOT NULL)
 163 * @va: audit struct to audit values of  (NOT NULL)
 164 */
 165static void audit_signal_cb(struct audit_buffer *ab, void *va)
 166{
 167        struct common_audit_data *sa = va;
 168
 169        if (aad(sa)->request & AA_SIGNAL_PERM_MASK) {
 170                audit_log_format(ab, " requested_mask=");
 171                audit_signal_mask(ab, aad(sa)->request);
 172                if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) {
 173                        audit_log_format(ab, " denied_mask=");
 174                        audit_signal_mask(ab, aad(sa)->denied);
 175                }
 176        }
 177        if (aad(sa)->signal == SIGUNKNOWN)
 178                audit_log_format(ab, "signal=unknown(%d)",
 179                                 aad(sa)->unmappedsig);
 180        else if (aad(sa)->signal < MAXMAPPED_SIGNAME)
 181                audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]);
 182        else
 183                audit_log_format(ab, " signal=rtmin+%d",
 184                                 aad(sa)->signal - SIGRT_BASE);
 185        audit_log_format(ab, " peer=");
 186        aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
 187                        FLAGS_NONE, GFP_ATOMIC);
 188}
 189
 190static int profile_signal_perm(struct aa_profile *profile,
 191                               struct aa_label *peer, u32 request,
 192                               struct common_audit_data *sa)
 193{
 194        struct aa_perms perms;
 195        unsigned int state;
 196
 197        if (profile_unconfined(profile) ||
 198            !PROFILE_MEDIATES(profile, AA_CLASS_SIGNAL))
 199                return 0;
 200
 201        aad(sa)->peer = peer;
 202        /* TODO: secondary cache check <profile, profile, perm> */
 203        state = aa_dfa_next(profile->policy.dfa,
 204                            profile->policy.start[AA_CLASS_SIGNAL],
 205                            aad(sa)->signal);
 206        aa_label_match(profile, peer, state, false, request, &perms);
 207        aa_apply_modes_to_perms(profile, &perms);
 208        return aa_check_perms(profile, &perms, request, sa, audit_signal_cb);
 209}
 210
 211int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig)
 212{
 213        struct aa_profile *profile;
 214        DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SIGNAL);
 215
 216        aad(&sa)->signal = map_signal_num(sig);
 217        aad(&sa)->unmappedsig = sig;
 218        return xcheck_labels(sender, target, profile,
 219                        profile_signal_perm(profile, target, MAY_WRITE, &sa),
 220                        profile_signal_perm(profile, sender, MAY_READ, &sa));
 221}
 222