linux/security/apparmor/net.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * AppArmor security module
   4 *
   5 * This file contains AppArmor network mediation
   6 *
   7 * Copyright (C) 1998-2008 Novell/SUSE
   8 * Copyright 2009-2017 Canonical Ltd.
   9 */
  10
  11#include "include/apparmor.h"
  12#include "include/audit.h"
  13#include "include/cred.h"
  14#include "include/label.h"
  15#include "include/net.h"
  16#include "include/policy.h"
  17#include "include/secid.h"
  18
  19#include "net_names.h"
  20
  21
  22struct aa_sfs_entry aa_sfs_entry_network[] = {
  23        AA_SFS_FILE_STRING("af_mask",   AA_SFS_AF_MASK),
  24        { }
  25};
  26
  27static const char * const net_mask_names[] = {
  28        "unknown",
  29        "send",
  30        "receive",
  31        "unknown",
  32
  33        "create",
  34        "shutdown",
  35        "connect",
  36        "unknown",
  37
  38        "setattr",
  39        "getattr",
  40        "setcred",
  41        "getcred",
  42
  43        "chmod",
  44        "chown",
  45        "chgrp",
  46        "lock",
  47
  48        "mmap",
  49        "mprot",
  50        "unknown",
  51        "unknown",
  52
  53        "accept",
  54        "bind",
  55        "listen",
  56        "unknown",
  57
  58        "setopt",
  59        "getopt",
  60        "unknown",
  61        "unknown",
  62
  63        "unknown",
  64        "unknown",
  65        "unknown",
  66        "unknown",
  67};
  68
  69
  70/* audit callback for net specific fields */
  71void audit_net_cb(struct audit_buffer *ab, void *va)
  72{
  73        struct common_audit_data *sa = va;
  74
  75        if (address_family_names[sa->u.net->family])
  76                audit_log_format(ab, " family=\"%s\"",
  77                                 address_family_names[sa->u.net->family]);
  78        else
  79                audit_log_format(ab, " family=\"unknown(%d)\"",
  80                                 sa->u.net->family);
  81        if (sock_type_names[aad(sa)->net.type])
  82                audit_log_format(ab, " sock_type=\"%s\"",
  83                                 sock_type_names[aad(sa)->net.type]);
  84        else
  85                audit_log_format(ab, " sock_type=\"unknown(%d)\"",
  86                                 aad(sa)->net.type);
  87        audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
  88
  89        if (aad(sa)->request & NET_PERMS_MASK) {
  90                audit_log_format(ab, " requested_mask=");
  91                aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
  92                                   net_mask_names, NET_PERMS_MASK);
  93
  94                if (aad(sa)->denied & NET_PERMS_MASK) {
  95                        audit_log_format(ab, " denied_mask=");
  96                        aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
  97                                           net_mask_names, NET_PERMS_MASK);
  98                }
  99        }
 100        if (aad(sa)->peer) {
 101                audit_log_format(ab, " peer=");
 102                aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
 103                                FLAGS_NONE, GFP_ATOMIC);
 104        }
 105}
 106
 107/* Generic af perm */
 108int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
 109                       u32 request, u16 family, int type)
 110{
 111        struct aa_perms perms = { };
 112        unsigned int state;
 113        __be16 buffer[2];
 114
 115        AA_BUG(family >= AF_MAX);
 116        AA_BUG(type < 0 || type >= SOCK_MAX);
 117
 118        if (profile_unconfined(profile))
 119                return 0;
 120        state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
 121        if (!state)
 122                return 0;
 123
 124        buffer[0] = cpu_to_be16(family);
 125        buffer[1] = cpu_to_be16((u16) type);
 126        state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer,
 127                                 4);
 128        aa_compute_perms(profile->policy.dfa, state, &perms);
 129        aa_apply_modes_to_perms(profile, &perms);
 130
 131        return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
 132}
 133
 134int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
 135               int type, int protocol)
 136{
 137        struct aa_profile *profile;
 138        DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
 139
 140        return fn_for_each_confined(label, profile,
 141                        aa_profile_af_perm(profile, &sa, request, family,
 142                                           type));
 143}
 144
 145static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
 146                            struct sock *sk)
 147{
 148        int error = 0;
 149
 150        AA_BUG(!label);
 151        AA_BUG(!sk);
 152
 153        if (!unconfined(label)) {
 154                struct aa_profile *profile;
 155                DEFINE_AUDIT_SK(sa, op, sk);
 156
 157                error = fn_for_each_confined(label, profile,
 158                            aa_profile_af_sk_perm(profile, &sa, request, sk));
 159        }
 160
 161        return error;
 162}
 163
 164int aa_sk_perm(const char *op, u32 request, struct sock *sk)
 165{
 166        struct aa_label *label;
 167        int error;
 168
 169        AA_BUG(!sk);
 170        AA_BUG(in_interrupt());
 171
 172        /* TODO: switch to begin_current_label ???? */
 173        label = begin_current_label_crit_section();
 174        error = aa_label_sk_perm(label, op, request, sk);
 175        end_current_label_crit_section(label);
 176
 177        return error;
 178}
 179
 180
 181int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
 182                      struct socket *sock)
 183{
 184        AA_BUG(!label);
 185        AA_BUG(!sock);
 186        AA_BUG(!sock->sk);
 187
 188        return aa_label_sk_perm(label, op, request, sock->sk);
 189}
 190
 191#ifdef CONFIG_NETWORK_SECMARK
 192static int apparmor_secmark_init(struct aa_secmark *secmark)
 193{
 194        struct aa_label *label;
 195
 196        if (secmark->label[0] == '*') {
 197                secmark->secid = AA_SECID_WILDCARD;
 198                return 0;
 199        }
 200
 201        label = aa_label_strn_parse(&root_ns->unconfined->label,
 202                                    secmark->label, strlen(secmark->label),
 203                                    GFP_ATOMIC, false, false);
 204
 205        if (IS_ERR(label))
 206                return PTR_ERR(label);
 207
 208        secmark->secid = label->secid;
 209
 210        return 0;
 211}
 212
 213static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid,
 214                           struct common_audit_data *sa)
 215{
 216        int i, ret;
 217        struct aa_perms perms = { };
 218
 219        if (profile->secmark_count == 0)
 220                return 0;
 221
 222        for (i = 0; i < profile->secmark_count; i++) {
 223                if (!profile->secmark[i].secid) {
 224                        ret = apparmor_secmark_init(&profile->secmark[i]);
 225                        if (ret)
 226                                return ret;
 227                }
 228
 229                if (profile->secmark[i].secid == secid ||
 230                    profile->secmark[i].secid == AA_SECID_WILDCARD) {
 231                        if (profile->secmark[i].deny)
 232                                perms.deny = ALL_PERMS_MASK;
 233                        else
 234                                perms.allow = ALL_PERMS_MASK;
 235
 236                        if (profile->secmark[i].audit)
 237                                perms.audit = ALL_PERMS_MASK;
 238                }
 239        }
 240
 241        aa_apply_modes_to_perms(profile, &perms);
 242
 243        return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
 244}
 245
 246int apparmor_secmark_check(struct aa_label *label, char *op, u32 request,
 247                           u32 secid, const struct sock *sk)
 248{
 249        struct aa_profile *profile;
 250        DEFINE_AUDIT_SK(sa, op, sk);
 251
 252        return fn_for_each_confined(label, profile,
 253                                    aa_secmark_perm(profile, request, secid,
 254                                                    &sa));
 255}
 256#endif
 257