Files
ubports_kernel_google_msm/security/apparmor/net.c
John Johansen 1992ec6ce4 UBUNTU: SAUCE: (no-up) apparmor: Sync to apparmor 3 - alpha 4 snapshot
This is a sync and squash to the apparmor 3 alpha 4 development snapshot
backported from 3.12. The set of patches in this squash are available
is the aa3.0-presquash branch of the dev tree.

Several of the patches in the squash have been submitted upstream.
Several more will be submitted soon, and other parts are still in
active review and development.

This squash will be updated to remove patches as they are pulled
into the upstream tree, and add new patches as they become available
to the stable apparmor dev branch.

In addition to the apparmor 3 sync this contains the backport patch
series for the 3.4 manta kernel
- apparmor: 3.10 backport revert no delay vfree()
- apparmor: 3.8 backport provide file_inode helper 496ad9aa
- apparmor: 3.6 backport revert uapi for capnames 43c422ed
- apparmor: 3.6 backport revert uapi for resnames 8a1ab315
- apparmor: 3.6 backport define kuid_t d2b31ca64
- apparmor: 3.6 backport kuid_t support for audit 2db81452
- apparmor: 3.6 backport remove const from sb_mount 808d4e3c
- apparmor: 3.4 backport revert file_mmap e5467859
- apparmor: 3.4 backport cap_mmap_addr d007794a
- apparmor: 3.4 backport fake no_new_privs 259e5e6c
- apparmor: 3.4 backport revert task audi_data 0972c74e
- apparmor: 3.4 backport alias file_open 83d49856
- UBUNTU: SAUCE: (no-up) apparmor: update config options

Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
2014-01-09 07:43:54 -07:00

170 lines
4.3 KiB
C

/*
* AppArmor security module
*
* This file contains AppArmor network mediation
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2012 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*/
#include "include/apparmor.h"
#include "include/audit.h"
#include "include/context.h"
#include "include/net.h"
#include "include/label.h"
#include "include/policy.h"
#include "net_names.h"
struct aa_fs_entry aa_fs_entry_network[] = {
AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
{ }
};
/* audit callback for net specific fields */
static void audit_cb(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = va;
audit_log_format(ab, " family=");
if (address_family_names[sa->u.net->family]) {
audit_log_string(ab, address_family_names[sa->u.net->family]);
} else {
audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
}
audit_log_format(ab, " sock_type=");
if (sock_type_names[aad(sa)->net.type]) {
audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
} else {
audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
}
audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
}
/**
* audit_net - audit network access
* @profile: profile being enforced (NOT NULL)
* @op: operation being checked
* @family: network family
* @type: network type
* @protocol: network protocol
* @sk: socket auditing is being applied to
* @error: error code for failure else 0
*
* Returns: %0 or sa->error else other errorcode on failure
*/
static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
int protocol, struct sock *sk, int error)
{
int audit_type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
struct apparmor_audit_data aad = { };
struct lsm_network_audit net = { };
if (sk) {
sa.type = LSM_AUDIT_DATA_NET;
} else {
sa.type = LSM_AUDIT_DATA_NONE;
}
/* todo fill in socket addr info */
aad_set(&sa, &aad);
sa.u.net = &net;
sa.u.net->family = family;
sa.u.net->sk = sk;
aad.op = op,
aad.net.type = type;
aad.net.protocol = protocol;
aad.error = error;
if (likely(!aad.error)) {
u16 audit_mask = profile->net.audit[sa.u.net->family];
if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
!(1 << aad.net.type & audit_mask)))
return 0;
audit_type = AUDIT_APPARMOR_AUDIT;
} else {
u16 quiet_mask = profile->net.quiet[sa.u.net->family];
u16 kill_mask = 0;
u16 denied = (1 << aad.net.type);
if (denied & kill_mask)
audit_type = AUDIT_APPARMOR_KILL;
if ((denied & quiet_mask) &&
AUDIT_MODE(profile) != AUDIT_NOQUIET &&
AUDIT_MODE(profile) != AUDIT_ALL)
return COMPLAIN_MODE(profile) ? 0 : aad.error;
}
return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
}
/**
* aa_net_perm - very course network access check
* @op: operation being checked
* @label: label being enforced (NOT NULL)
* @family: network family
* @type: network type
* @protocol: network protocol
*
* Returns: %0 else error if permission denied
*/
int aa_net_perm(int op, struct aa_label *label, u16 family, int type,
int protocol, struct sock *sk)
{
struct aa_profile *profile;
u16 family_mask;
int i, error = 0;
if ((family < 0) || (family >= AF_MAX))
return -EINVAL;
if ((type < 0) || (type >= SOCK_MAX))
return -EINVAL;
/* unix domain and netlink sockets are handled by ipc */
if (family == AF_UNIX || family == AF_NETLINK)
return 0;
label_for_each_confined(i, label, profile) {
family_mask = profile->net.allow[family];
error = (family_mask & (1 << type)) ? 0 : -EACCES;
error = audit_net(profile, op, family, type, protocol, sk,
error);
if (error)
break;
}
return error;
}
/**
* aa_revalidate_sk - Revalidate access to a sock
* @op: operation being checked
* @sk: sock being revalidated (NOT NULL)
*
* Returns: %0 else error if permission denied
*/
int aa_revalidate_sk(int op, struct sock *sk)
{
struct aa_label *label;
int error = 0;
/* aa_revalidate_sk should not be called from interrupt context
* don't mediate these calls as they are not task related
*/
if (in_interrupt())
return 0;
label = __aa_current_label();
if (!unconfined(label))
error = aa_net_perm(op, label, sk->sk_family, sk->sk_type,
sk->sk_protocol, sk);
return error;
}