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