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 * @buffer: buffer to write string to (NOT NULL)
  24 * @mask: permission mask to convert
  25 */
  26static void audit_ptrace_mask(struct audit_buffer *ab, u32 mask)
  27{
  28        switch (mask) {
  29        case MAY_READ:
  30                audit_log_string(ab, "read");
  31                break;
  32        case MAY_WRITE:
  33                audit_log_string(ab, "trace");
  34                break;
  35        case AA_MAY_BE_READ:
  36                audit_log_string(ab, "readby");
  37                break;
  38        case AA_MAY_BE_TRACED:
  39                audit_log_string(ab, "tracedby");
  40                break;
  41        }
  42}
  43
  44/* call back to audit ptrace fields */
  45static void audit_ptrace_cb(struct audit_buffer *ab, void *va)
  46{
  47        struct common_audit_data *sa = va;
  48
  49        if (aad(sa)->request & AA_PTRACE_PERM_MASK) {
  50                audit_log_format(ab, " requested_mask=");
  51                audit_ptrace_mask(ab, aad(sa)->request);
  52
  53                if (aad(sa)->denied & AA_PTRACE_PERM_MASK) {
  54                        audit_log_format(ab, " denied_mask=");
  55                        audit_ptrace_mask(ab, aad(sa)->denied);
  56                }
  57        }
  58        audit_log_format(ab, " peer=");
  59        aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
  60                        FLAGS_NONE, GFP_ATOMIC);
  61}
  62
  63/* assumes check for PROFILE_MEDIATES is already done */
  64/* TODO: conditionals */
  65static int profile_ptrace_perm(struct aa_profile *profile,
  66                             struct aa_label *peer, u32 request,
  67                             struct common_audit_data *sa)
  68{
  69        struct aa_perms perms = { };
  70
  71        aad(sa)->peer = peer;
  72        aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request,
  73                               &perms);
  74        aa_apply_modes_to_perms(profile, &perms);
  75        return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb);
  76}
  77
  78static int profile_tracee_perm(struct aa_profile *tracee,
  79                               struct aa_label *tracer, u32 request,
  80                               struct common_audit_data *sa)
  81{
  82        if (profile_unconfined(tracee) || unconfined(tracer) ||
  83            !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE))
  84                return 0;
  85
  86        return profile_ptrace_perm(tracee, tracer, request, sa);
  87}
  88
  89static int profile_tracer_perm(struct aa_profile *tracer,
  90                               struct aa_label *tracee, u32 request,
  91                               struct common_audit_data *sa)
  92{
  93        if (profile_unconfined(tracer))
  94                return 0;
  95
  96        if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE))
  97                return profile_ptrace_perm(tracer, tracee, request, sa);
  98
  99        /* profile uses the old style capability check for ptrace */
 100        if (&tracer->label == tracee)
 101                return 0;
 102
 103        aad(sa)->label = &tracer->label;
 104        aad(sa)->peer = tracee;
 105        aad(sa)->request = 0;
 106        aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE,
 107                                    CAP_OPT_NONE);
 108
 109        return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb);
 110}
 111
 112/**
 113 * aa_may_ptrace - test if tracer task can trace the tracee
 114 * @tracer: label of the task doing the tracing  (NOT NULL)
 115 * @tracee: task label to be traced
 116 * @request: permission request
 117 *
 118 * Returns: %0 else error code if permission denied or error
 119 */
 120int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
 121                  u32 request)
 122{
 123        struct aa_profile *profile;
 124        u32 xrequest = request << PTRACE_PERM_SHIFT;
 125        DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE);
 126
 127        return xcheck_labels(tracer, tracee, profile,
 128                        profile_tracer_perm(profile, tracee, request, &sa),
 129                        profile_tracee_perm(profile, tracer, xrequest, &sa));
 130}
 131
 132
 133static inline int map_signal_num(int sig)
 134{
 135        if (sig > SIGRTMAX)
 136                return SIGUNKNOWN;
 137        else if (sig >= SIGRTMIN)
 138                return sig - SIGRTMIN + SIGRT_BASE;
 139        else if (sig < MAXMAPPED_SIG)
 140                return sig_map[sig];
 141        return SIGUNKNOWN;
 142}
 143
 144/**
 145 * audit_file_mask - convert mask to permission string
 146 * @buffer: buffer to write string to (NOT NULL)
 147 * @mask: permission mask to convert
 148 */
 149static void audit_signal_mask(struct audit_buffer *ab, u32 mask)
 150{
 151        if (mask & MAY_READ)
 152                audit_log_string(ab, "receive");
 153        if (mask & MAY_WRITE)
 154                audit_log_string(ab, "send");
 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=");
 168                audit_signal_mask(ab, aad(sa)->request);
 169                if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) {
 170                        audit_log_format(ab, " denied_mask=");
 171                        audit_signal_mask(ab, 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