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
  22#include "net_names.h"
  23
  24
  25struct aa_sfs_entry aa_sfs_entry_network[] = {
  26        AA_SFS_FILE_STRING("af_mask",   AA_SFS_AF_MASK),
  27        { }
  28};
  29
  30static const char * const net_mask_names[] = {
  31        "unknown",
  32        "send",
  33        "receive",
  34        "unknown",
  35
  36        "create",
  37        "shutdown",
  38        "connect",
  39        "unknown",
  40
  41        "setattr",
  42        "getattr",
  43        "setcred",
  44        "getcred",
  45
  46        "chmod",
  47        "chown",
  48        "chgrp",
  49        "lock",
  50
  51        "mmap",
  52        "mprot",
  53        "unknown",
  54        "unknown",
  55
  56        "accept",
  57        "bind",
  58        "listen",
  59        "unknown",
  60
  61        "setopt",
  62        "getopt",
  63        "unknown",
  64        "unknown",
  65
  66        "unknown",
  67        "unknown",
  68        "unknown",
  69        "unknown",
  70};
  71
  72
  73/* audit callback for net specific fields */
  74void audit_net_cb(struct audit_buffer *ab, void *va)
  75{
  76        struct common_audit_data *sa = va;
  77
  78        audit_log_format(ab, " family=");
  79        if (address_family_names[sa->u.net->family])
  80                audit_log_string(ab, address_family_names[sa->u.net->family]);
  81        else
  82                audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
  83        audit_log_format(ab, " sock_type=");
  84        if (sock_type_names[aad(sa)->net.type])
  85                audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
  86        else
  87                audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
  88        audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
  89
  90        if (aad(sa)->request & NET_PERMS_MASK) {
  91                audit_log_format(ab, " requested_mask=");
  92                aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
  93                                   net_mask_names, NET_PERMS_MASK);
  94
  95                if (aad(sa)->denied & NET_PERMS_MASK) {
  96                        audit_log_format(ab, " denied_mask=");
  97                        aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
  98                                           net_mask_names, NET_PERMS_MASK);
  99                }
 100        }
 101        if (aad(sa)->peer) {
 102                audit_log_format(ab, " peer=");
 103                aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
 104                                FLAGS_NONE, GFP_ATOMIC);
 105        }
 106}
 107
 108/* Generic af perm */
 109int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
 110                       u32 request, u16 family, int type)
 111{
 112        struct aa_perms perms = { };
 113        unsigned int state;
 114        __be16 buffer[2];
 115
 116        AA_BUG(family >= AF_MAX);
 117        AA_BUG(type < 0 || type >= SOCK_MAX);
 118
 119        if (profile_unconfined(profile))
 120                return 0;
 121        state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
 122        if (!state)
 123                return 0;
 124
 125        buffer[0] = cpu_to_be16(family);
 126        buffer[1] = cpu_to_be16((u16) type);
 127        state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer,
 128                                 4);
 129        aa_compute_perms(profile->policy.dfa, state, &perms);
 130        aa_apply_modes_to_perms(profile, &perms);
 131
 132        return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
 133}
 134
 135int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
 136               int type, int protocol)
 137{
 138        struct aa_profile *profile;
 139        DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
 140
 141        return fn_for_each_confined(label, profile,
 142                        aa_profile_af_perm(profile, &sa, request, family,
 143                                           type));
 144}
 145
 146static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
 147                            struct sock *sk)
 148{
 149        struct aa_profile *profile;
 150        DEFINE_AUDIT_SK(sa, op, sk);
 151
 152        AA_BUG(!label);
 153        AA_BUG(!sk);
 154
 155        if (unconfined(label))
 156                return 0;
 157
 158        return fn_for_each_confined(label, profile,
 159                        aa_profile_af_sk_perm(profile, &sa, request, sk));
 160}
 161
 162int aa_sk_perm(const char *op, u32 request, struct sock *sk)
 163{
 164        struct aa_label *label;
 165        int error;
 166
 167        AA_BUG(!sk);
 168        AA_BUG(in_interrupt());
 169
 170        /* TODO: switch to begin_current_label ???? */
 171        label = begin_current_label_crit_section();
 172        error = aa_label_sk_perm(label, op, request, sk);
 173        end_current_label_crit_section(label);
 174
 175        return error;
 176}
 177
 178
 179int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
 180                      struct socket *sock)
 181{
 182        AA_BUG(!label);
 183        AA_BUG(!sock);
 184        AA_BUG(!sock->sk);
 185
 186        return aa_label_sk_perm(label, op, request, sock->sk);
 187}
 188