Skip to content

Commit

Permalink
apparmor: add base infastructure for socket mediation
Browse files Browse the repository at this point in the history
version 2 - Force an abi break. Network mediation will only be
            available in v8 abi complaint policy.

Provide a basic mediation of sockets. This is not a full net mediation
but just whether a spcific family of socket can be used by an
application, along with setting up some basic infrastructure for
network mediation to follow.

the user space rule hav the basic form of
  NETWORK RULE = [ QUALIFIERS ] 'network' [ DOMAIN ]
                 [ TYPE | PROTOCOL ]

  DOMAIN = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' |
             'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' |
	     'netbeui' | 'security' | 'key' | 'packet' | 'ash' |
	     'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' |
	     'wanpipe' | 'bluetooth' | 'netlink' | 'unix' | 'rds' |
	     'llc' | 'can' | 'tipc' | 'iucv' | 'rxrpc' | 'isdn' |
	     'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' |
	     'vsock' | 'mpls' | 'ib' | 'kcm' ) ','

  TYPE = ( 'stream' | 'dgram' | 'seqpacket' |  'rdm' | 'raw' |
           'packet' )

  PROTOCOL = ( 'tcp' | 'udp' | 'icmp' )

eg.
  network,
  network inet,

Signed-off-by: John Johansen <[email protected]>
Acked-by: Seth Arnold <[email protected]>
  • Loading branch information
John Johansen committed Mar 14, 2018
1 parent 21f6066 commit 56974a6
Show file tree
Hide file tree
Showing 13 changed files with 786 additions and 8 deletions.
1 change: 1 addition & 0 deletions security/apparmor/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#
# Generated include files
#
net_names.h
capability_names.h
rlim_names.h
43 changes: 41 additions & 2 deletions security/apparmor/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,44 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o

apparmor-y := apparmorfs.o audit.o capability.o task.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
resource.o secid.o file.o policy_ns.o label.o mount.o
resource.o secid.o file.o policy_ns.o label.o mount.o net.o
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o

clean-files := capability_names.h rlim_names.h
clean-files := capability_names.h rlim_names.h net_names.h

# Build a lower case string table of address family names
# Transform lines from
# #define AF_LOCAL 1 /* POSIX name for AF_UNIX */
# #define AF_INET 2 /* Internet IP Protocol */
# to
# [1] = "local",
# [2] = "inet",
#
# and build the securityfs entries for the mapping.
# Transforms lines from
# #define AF_INET 2 /* Internet IP Protocol */
# to
# #define AA_SFS_AF_MASK "local inet"
quiet_cmd_make-af = GEN $@
cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
echo "};" >> $@ ;\
printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\
sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
$< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@

# Build a lower case string table of sock type names
# Transform lines from
# SOCK_STREAM = 1,
# to
# [1] = "stream",
quiet_cmd_make-sock = GEN $@
cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
sed $^ >>$@ -r -n \
-e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
echo "};" >> $@

# Build a lower case string table of capability names
# Transforms lines from
Expand Down Expand Up @@ -62,10 +95,16 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@

$(obj)/capability.o : $(obj)/capability_names.h
$(obj)/net.o : $(obj)/net_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
$(src)/Makefile
$(call cmd,make-caps)
$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
$(src)/Makefile
$(call cmd,make-rlim)
$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
$(srctree)/include/linux/net.h \
$(src)/Makefile
$(call cmd,make-af)
$(call cmd,make-sock)
2 changes: 2 additions & 0 deletions security/apparmor/apparmorfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2169,6 +2169,7 @@ static struct aa_sfs_entry aa_sfs_entry_versions[] = {
AA_SFS_FILE_BOOLEAN("v5", 1),
AA_SFS_FILE_BOOLEAN("v6", 1),
AA_SFS_FILE_BOOLEAN("v7", 1),
AA_SFS_FILE_BOOLEAN("v8", 1),
{ }
};

Expand Down Expand Up @@ -2204,6 +2205,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
AA_SFS_DIR("policy", aa_sfs_entry_policy),
AA_SFS_DIR("domain", aa_sfs_entry_domain),
AA_SFS_DIR("file", aa_sfs_entry_file),
AA_SFS_DIR("network_v8", aa_sfs_entry_network),
AA_SFS_DIR("mount", aa_sfs_entry_mount),
AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
Expand Down
30 changes: 30 additions & 0 deletions security/apparmor/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "include/cred.h"
#include "include/file.h"
#include "include/match.h"
#include "include/net.h"
#include "include/path.h"
#include "include/policy.h"
#include "include/label.h"
Expand Down Expand Up @@ -560,6 +561,32 @@ static int __file_path_perm(const char *op, struct aa_label *label,
return error;
}

static int __file_sock_perm(const char *op, struct aa_label *label,
struct aa_label *flabel, struct file *file,
u32 request, u32 denied)
{
struct socket *sock = (struct socket *) file->private_data;
int error;

AA_BUG(!sock);

/* revalidation due to label out of date. No revocation at this time */
if (!denied && aa_label_is_subset(flabel, label))
return 0;

/* TODO: improve to skip profiles cached in flabel */
error = aa_sock_file_perm(label, op, request, sock);
if (denied) {
/* TODO: improve to skip profiles checked above */
/* check every profile in file label to is cached */
last_error(error, aa_sock_file_perm(flabel, op, request, sock));
}
if (!error)
update_file_ctx(file_ctx(file), label, request);

return error;
}

/**
* aa_file_perm - do permission revalidation check & audit for @file
* @op: operation being checked
Expand Down Expand Up @@ -604,6 +631,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
error = __file_path_perm(op, label, flabel, file, request,
denied);

else if (S_ISSOCK(file_inode(file)->i_mode))
error = __file_sock_perm(op, label, flabel, file, request,
denied);
done:
rcu_read_unlock();

Expand Down
3 changes: 2 additions & 1 deletion security/apparmor/include/apparmor.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
#define AA_CLASS_UNKNOWN 1
#define AA_CLASS_FILE 2
#define AA_CLASS_CAP 3
#define AA_CLASS_NET 4
#define AA_CLASS_DEPRECATED 4
#define AA_CLASS_RLIMITS 5
#define AA_CLASS_DOMAIN 6
#define AA_CLASS_MOUNT 7
#define AA_CLASS_PTRACE 9
#define AA_CLASS_SIGNAL 10
#define AA_CLASS_NET 14
#define AA_CLASS_LABEL 16

#define AA_CLASS_LAST AA_CLASS_LABEL
Expand Down
6 changes: 6 additions & 0 deletions security/apparmor/include/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ struct apparmor_audit_data {
int signal;
int unmappedsig;
};
struct {
int type, protocol;
struct sock *peer_sk;
void *addr;
int addrlen;
} net;
};
};
struct {
Expand Down
106 changes: 106 additions & 0 deletions security/apparmor/include/net.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* AppArmor security module
*
* This file contains AppArmor network mediation definitions.
*
* Copyright (C) 1998-2008 Novell/SUSE
* Copyright 2009-2017 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.
*/

#ifndef __AA_NET_H
#define __AA_NET_H

#include <net/sock.h>
#include <linux/path.h>

#include "apparmorfs.h"
#include "label.h"
#include "perms.h"
#include "policy.h"

#define AA_MAY_SEND AA_MAY_WRITE
#define AA_MAY_RECEIVE AA_MAY_READ

#define AA_MAY_SHUTDOWN AA_MAY_DELETE

#define AA_MAY_CONNECT AA_MAY_OPEN
#define AA_MAY_ACCEPT 0x00100000

#define AA_MAY_BIND 0x00200000
#define AA_MAY_LISTEN 0x00400000

#define AA_MAY_SETOPT 0x01000000
#define AA_MAY_GETOPT 0x02000000

#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN | \
AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)

#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD | \
AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK | \
AA_MAY_MPROT)

#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
AA_MAY_ACCEPT)
struct aa_sk_ctx {
struct aa_label *label;
struct aa_label *peer;
};

#define SK_CTX(X) ((X)->sk_security)
#define SOCK_ctx(X) SOCK_INODE(X)->i_security
#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \
struct lsm_network_audit NAME ## _net = { .sk = (SK), \
.family = (F)}; \
DEFINE_AUDIT_DATA(NAME, \
((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \
LSM_AUDIT_DATA_NONE, \
OP); \
NAME.u.net = &(NAME ## _net); \
aad(&NAME)->net.type = (T); \
aad(&NAME)->net.protocol = (P)

#define DEFINE_AUDIT_SK(NAME, OP, SK) \
DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \
(SK)->sk_protocol)


#define af_select(FAMILY, FN, DEF_FN) \
({ \
int __e; \
switch ((FAMILY)) { \
default: \
__e = DEF_FN; \
} \
__e; \
})

extern struct aa_sfs_entry aa_sfs_entry_network[];

void audit_net_cb(struct audit_buffer *ab, void *va);
int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
u32 request, u16 family, int type);
int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
int type, int protocol);
static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
struct common_audit_data *sa,
u32 request,
struct sock *sk)
{
return aa_profile_af_perm(profile, sa, request, sk->sk_family,
sk->sk_type);
}
int aa_sk_perm(const char *op, u32 request, struct sock *sk);

int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
struct socket *sock);

#endif /* __AA_NET_H */
5 changes: 3 additions & 2 deletions security/apparmor/include/perms.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,10 @@ extern struct aa_perms allperms;


void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
u32 mask);
void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
u32 chrsmask, const char **names, u32 namesmask);
u32 chrsmask, const char * const *names, u32 namesmask);
void aa_apply_modes_to_perms(struct aa_profile *profile,
struct aa_perms *perms);
void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
Expand Down
11 changes: 11 additions & 0 deletions security/apparmor/include/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "file.h"
#include "lib.h"
#include "label.h"
#include "net.h"
#include "perms.h"
#include "resource.h"

Expand Down Expand Up @@ -224,6 +225,16 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
return 0;
}

static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
u16 AF) {
unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
__be16 be_af = cpu_to_be16(AF);

if (!state)
return 0;
return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
}

/**
* aa_get_profile - increment refcount on profile @p
* @p: profile (MAYBE NULL)
Expand Down
5 changes: 3 additions & 2 deletions security/apparmor/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
*str = '\0';
}

void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
u32 mask)
{
const char *fmt = "%s";
unsigned int i, perm = 1;
Expand All @@ -229,7 +230,7 @@ void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
}

void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
u32 chrsmask, const char **names, u32 namesmask)
u32 chrsmask, const char * const *names, u32 namesmask)
{
char str[33];

Expand Down
Loading

0 comments on commit 56974a6

Please sign in to comment.