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