aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2017-07-19 02:18:33 -0400
committerJohn Johansen <john.johansen@canonical.com>2017-09-22 16:00:58 -0400
commit651e28c5537abb39076d3949fb7618536f1d242e (patch)
tree376539d1a5b97339f9123809707fe5c442afc193
parentcbf2d0e1a9e4876046a628e0e036a7545a3a4c40 (diff)
apparmor: add base infastructure for socket mediation
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 <john.johansen@canonical.com> Acked-by: Seth Arnold <seth.arnold@canonical.com>
-rw-r--r--security/apparmor/.gitignore1
-rw-r--r--security/apparmor/Makefile43
-rw-r--r--security/apparmor/apparmorfs.c1
-rw-r--r--security/apparmor/file.c30
-rw-r--r--security/apparmor/include/audit.h26
-rw-r--r--security/apparmor/include/net.h114
-rw-r--r--security/apparmor/include/perms.h5
-rw-r--r--security/apparmor/include/policy.h13
-rw-r--r--security/apparmor/lib.c5
-rw-r--r--security/apparmor/lsm.c387
-rw-r--r--security/apparmor/net.c184
-rw-r--r--security/apparmor/policy_unpack.c47
12 files changed, 840 insertions, 16 deletions
diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
index 9cdec70d72b8..d5b291e94264 100644
--- a/security/apparmor/.gitignore
+++ b/security/apparmor/.gitignore
@@ -1,5 +1,6 @@
1# 1#
2# Generated include files 2# Generated include files
3# 3#
4net_names.h
4capability_names.h 5capability_names.h
5rlim_names.h 6rlim_names.h
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 81a34426d024..dafdd387d42b 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,11 +4,44 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
4 4
5apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ 5apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
6 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ 6 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
7 resource.o secid.o file.o policy_ns.o label.o mount.o 7 resource.o secid.o file.o policy_ns.o label.o mount.o net.o
8apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o 8apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
9 9
10clean-files := capability_names.h rlim_names.h 10clean-files := capability_names.h rlim_names.h net_names.h
11 11
12# Build a lower case string table of address family names
13# Transform lines from
14# #define AF_LOCAL 1 /* POSIX name for AF_UNIX */
15# #define AF_INET 2 /* Internet IP Protocol */
16# to
17# [1] = "local",
18# [2] = "inet",
19#
20# and build the securityfs entries for the mapping.
21# Transforms lines from
22# #define AF_INET 2 /* Internet IP Protocol */
23# to
24# #define AA_SFS_AF_MASK "local inet"
25quiet_cmd_make-af = GEN $@
26cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
27 sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
28 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
29 echo "};" >> $@ ;\
30 printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\
31 sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
32 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
33 $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
34
35# Build a lower case string table of sock type names
36# Transform lines from
37# SOCK_STREAM = 1,
38# to
39# [1] = "stream",
40quiet_cmd_make-sock = GEN $@
41cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
42 sed $^ >>$@ -r -n \
43 -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
44 echo "};" >> $@
12 45
13# Build a lower case string table of capability names 46# Build a lower case string table of capability names
14# Transforms lines from 47# Transforms lines from
@@ -61,6 +94,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
61 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ 94 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
62 95
63$(obj)/capability.o : $(obj)/capability_names.h 96$(obj)/capability.o : $(obj)/capability_names.h
97$(obj)/net.o : $(obj)/net_names.h
64$(obj)/resource.o : $(obj)/rlim_names.h 98$(obj)/resource.o : $(obj)/rlim_names.h
65$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ 99$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
66 $(src)/Makefile 100 $(src)/Makefile
@@ -68,3 +102,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
68$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \ 102$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
69 $(src)/Makefile 103 $(src)/Makefile
70 $(call cmd,make-rlim) 104 $(call cmd,make-rlim)
105$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
106 $(srctree)/include/linux/net.h \
107 $(src)/Makefile
108 $(call cmd,make-af)
109 $(call cmd,make-sock)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 7acea14c850b..125dad5c3fde 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -2202,6 +2202,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
2202 AA_SFS_DIR("policy", aa_sfs_entry_policy), 2202 AA_SFS_DIR("policy", aa_sfs_entry_policy),
2203 AA_SFS_DIR("domain", aa_sfs_entry_domain), 2203 AA_SFS_DIR("domain", aa_sfs_entry_domain),
2204 AA_SFS_DIR("file", aa_sfs_entry_file), 2204 AA_SFS_DIR("file", aa_sfs_entry_file),
2205 AA_SFS_DIR("network", aa_sfs_entry_network),
2205 AA_SFS_DIR("mount", aa_sfs_entry_mount), 2206 AA_SFS_DIR("mount", aa_sfs_entry_mount),
2206 AA_SFS_DIR("namespaces", aa_sfs_entry_ns), 2207 AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
2207 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), 2208 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index 3382518b87fa..db80221891c6 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -21,6 +21,7 @@
21#include "include/context.h" 21#include "include/context.h"
22#include "include/file.h" 22#include "include/file.h"
23#include "include/match.h" 23#include "include/match.h"
24#include "include/net.h"
24#include "include/path.h" 25#include "include/path.h"
25#include "include/policy.h" 26#include "include/policy.h"
26#include "include/label.h" 27#include "include/label.h"
@@ -566,6 +567,32 @@ static int __file_path_perm(const char *op, struct aa_label *label,
566 return error; 567 return error;
567} 568}
568 569
570static int __file_sock_perm(const char *op, struct aa_label *label,
571 struct aa_label *flabel, struct file *file,
572 u32 request, u32 denied)
573{
574 struct socket *sock = (struct socket *) file->private_data;
575 int error;
576
577 AA_BUG(!sock);
578
579 /* revalidation due to label out of date. No revocation at this time */
580 if (!denied && aa_label_is_subset(flabel, label))
581 return 0;
582
583 /* TODO: improve to skip profiles cached in flabel */
584 error = aa_sock_file_perm(label, op, request, sock);
585 if (denied) {
586 /* TODO: improve to skip profiles checked above */
587 /* check every profile in file label to is cached */
588 last_error(error, aa_sock_file_perm(flabel, op, request, sock));
589 }
590 if (!error)
591 update_file_ctx(file_ctx(file), label, request);
592
593 return error;
594}
595
569/** 596/**
570 * aa_file_perm - do permission revalidation check & audit for @file 597 * aa_file_perm - do permission revalidation check & audit for @file
571 * @op: operation being checked 598 * @op: operation being checked
@@ -610,6 +637,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
610 error = __file_path_perm(op, label, flabel, file, request, 637 error = __file_path_perm(op, label, flabel, file, request,
611 denied); 638 denied);
612 639
640 else if (S_ISSOCK(file_inode(file)->i_mode))
641 error = __file_sock_perm(op, label, flabel, file, request,
642 denied);
613done: 643done:
614 rcu_read_unlock(); 644 rcu_read_unlock();
615 645
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 620e81169659..ff4316e1068d 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -121,21 +121,29 @@ struct apparmor_audit_data {
121 /* these entries require a custom callback fn */ 121 /* these entries require a custom callback fn */
122 struct { 122 struct {
123 struct aa_label *peer; 123 struct aa_label *peer;
124 struct { 124 union {
125 const char *target; 125 struct {
126 kuid_t ouid; 126 kuid_t ouid;
127 } fs; 127 const char *target;
128 } fs;
129 struct {
130 int type, protocol;
131 struct sock *peer_sk;
132 void *addr;
133 int addrlen;
134 } net;
135 int signal;
136 struct {
137 int rlim;
138 unsigned long max;
139 } rlim;
140 };
128 }; 141 };
129 struct { 142 struct {
130 struct aa_profile *profile; 143 struct aa_profile *profile;
131 const char *ns; 144 const char *ns;
132 long pos; 145 long pos;
133 } iface; 146 } iface;
134 int signal;
135 struct {
136 int rlim;
137 unsigned long max;
138 } rlim;
139 struct { 147 struct {
140 const char *src_name; 148 const char *src_name;
141 const char *type; 149 const char *type;
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644
index 000000000000..140c8efcf364
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,114 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor network mediation definitions.
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#ifndef __AA_NET_H
16#define __AA_NET_H
17
18#include <net/sock.h>
19#include <linux/path.h>
20
21#include "apparmorfs.h"
22#include "label.h"
23#include "perms.h"
24#include "policy.h"
25
26#define AA_MAY_SEND AA_MAY_WRITE
27#define AA_MAY_RECEIVE AA_MAY_READ
28
29#define AA_MAY_SHUTDOWN AA_MAY_DELETE
30
31#define AA_MAY_CONNECT AA_MAY_OPEN
32#define AA_MAY_ACCEPT 0x00100000
33
34#define AA_MAY_BIND 0x00200000
35#define AA_MAY_LISTEN 0x00400000
36
37#define AA_MAY_SETOPT 0x01000000
38#define AA_MAY_GETOPT 0x02000000
39
40#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
41 AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN | \
42 AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
43 AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)
44
45#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
46 AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
47 AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD | \
48 AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK | \
49 AA_MAY_MPROT)
50
51#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
52 AA_MAY_ACCEPT)
53struct aa_sk_ctx {
54 struct aa_label *label;
55 struct aa_label *peer;
56 struct path path;
57};
58
59#define SK_CTX(X) ((X)->sk_security)
60#define SOCK_ctx(X) SOCK_INODE(X)->i_security
61#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \
62 struct lsm_network_audit NAME ## _net = { .sk = (SK), \
63 .family = (F)}; \
64 DEFINE_AUDIT_DATA(NAME, \
65 ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \
66 LSM_AUDIT_DATA_NONE, \
67 OP); \
68 NAME.u.net = &(NAME ## _net); \
69 aad(&NAME)->net.type = (T); \
70 aad(&NAME)->net.protocol = (P)
71
72#define DEFINE_AUDIT_SK(NAME, OP, SK) \
73 DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \
74 (SK)->sk_protocol)
75
76/* struct aa_net - network confinement data
77 * @allow: basic network families permissions
78 * @audit: which network permissions to force audit
79 * @quiet: which network permissions to quiet rejects
80 */
81struct aa_net {
82 u16 allow[AF_MAX];
83 u16 audit[AF_MAX];
84 u16 quiet[AF_MAX];
85};
86
87
88extern struct aa_sfs_entry aa_sfs_entry_network[];
89
90void audit_net_cb(struct audit_buffer *ab, void *va);
91int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
92 u32 request, u16 family, int type);
93int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
94 int type, int protocol);
95static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
96 struct common_audit_data *sa,
97 u32 request,
98 struct sock *sk)
99{
100 return aa_profile_af_perm(profile, sa, request, sk->sk_family,
101 sk->sk_type);
102}
103int aa_sk_perm(const char *op, u32 request, struct sock *sk);
104
105int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
106 struct socket *sock);
107
108
109static inline void aa_free_net_rules(struct aa_net *new)
110{
111 /* NOP */
112}
113
114#endif /* __AA_NET_H */
diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h
index 2b27bb79aec4..af04d5a7d73d 100644
--- a/security/apparmor/include/perms.h
+++ b/security/apparmor/include/perms.h
@@ -135,9 +135,10 @@ extern struct aa_perms allperms;
135 135
136 136
137void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask); 137void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
138void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask); 138void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
139 u32 mask);
139void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 140void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
140 u32 chrsmask, const char **names, u32 namesmask); 141 u32 chrsmask, const char * const *names, u32 namesmask);
141void aa_apply_modes_to_perms(struct aa_profile *profile, 142void aa_apply_modes_to_perms(struct aa_profile *profile,
142 struct aa_perms *perms); 143 struct aa_perms *perms);
143void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, 144void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index 17fe41a9cac3..4364088a0b9e 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -30,6 +30,7 @@
30#include "file.h" 30#include "file.h"
31#include "lib.h" 31#include "lib.h"
32#include "label.h" 32#include "label.h"
33#include "net.h"
33#include "perms.h" 34#include "perms.h"
34#include "resource.h" 35#include "resource.h"
35 36
@@ -111,6 +112,7 @@ struct aa_data {
111 * @policy: general match rules governing policy 112 * @policy: general match rules governing policy
112 * @file: The set of rules governing basic file access and domain transitions 113 * @file: The set of rules governing basic file access and domain transitions
113 * @caps: capabilities for the profile 114 * @caps: capabilities for the profile
115 * @net: network controls for the profile
114 * @rlimits: rlimits for the profile 116 * @rlimits: rlimits for the profile
115 * 117 *
116 * @dents: dentries for the profiles file entries in apparmorfs 118 * @dents: dentries for the profiles file entries in apparmorfs
@@ -148,6 +150,7 @@ struct aa_profile {
148 struct aa_policydb policy; 150 struct aa_policydb policy;
149 struct aa_file_rules file; 151 struct aa_file_rules file;
150 struct aa_caps caps; 152 struct aa_caps caps;
153 struct aa_net net;
151 struct aa_rlimit rlimits; 154 struct aa_rlimit rlimits;
152 155
153 struct aa_loaddata *rawdata; 156 struct aa_loaddata *rawdata;
@@ -220,6 +223,16 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
220 return 0; 223 return 0;
221} 224}
222 225
226static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
227 u16 AF) {
228 unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
229 u16 be_af = cpu_to_be16(AF);
230
231 if (!state)
232 return 0;
233 return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
234}
235
223/** 236/**
224 * aa_get_profile - increment refcount on profile @p 237 * aa_get_profile - increment refcount on profile @p
225 * @p: profile (MAYBE NULL) 238 * @p: profile (MAYBE NULL)
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 08ca26bcca77..8818621b5d95 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -211,7 +211,8 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
211 *str = '\0'; 211 *str = '\0';
212} 212}
213 213
214void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask) 214void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
215 u32 mask)
215{ 216{
216 const char *fmt = "%s"; 217 const char *fmt = "%s";
217 unsigned int i, perm = 1; 218 unsigned int i, perm = 1;
@@ -229,7 +230,7 @@ void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
229} 230}
230 231
231void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 232void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
232 u32 chrsmask, const char **names, u32 namesmask) 233 u32 chrsmask, const char * const *names, u32 namesmask)
233{ 234{
234 char str[33]; 235 char str[33];
235 236
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 4ad0b3a45142..cc5ab23a2d84 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -33,6 +33,7 @@
33#include "include/context.h" 33#include "include/context.h"
34#include "include/file.h" 34#include "include/file.h"
35#include "include/ipc.h" 35#include "include/ipc.h"
36#include "include/net.h"
36#include "include/path.h" 37#include "include/path.h"
37#include "include/label.h" 38#include "include/label.h"
38#include "include/policy.h" 39#include "include/policy.h"
@@ -736,6 +737,368 @@ static int apparmor_task_kill(struct task_struct *target, struct siginfo *info,
736 return error; 737 return error;
737} 738}
738 739
740/**
741 * apparmor_sk_alloc_security - allocate and attach the sk_security field
742 */
743static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
744{
745 struct aa_sk_ctx *ctx;
746
747 ctx = kzalloc(sizeof(*ctx), flags);
748 if (!ctx)
749 return -ENOMEM;
750
751 SK_CTX(sk) = ctx;
752
753 return 0;
754}
755
756/**
757 * apparmor_sk_free_security - free the sk_security field
758 */
759static void apparmor_sk_free_security(struct sock *sk)
760{
761 struct aa_sk_ctx *ctx = SK_CTX(sk);
762
763 SK_CTX(sk) = NULL;
764 aa_put_label(ctx->label);
765 aa_put_label(ctx->peer);
766 path_put(&ctx->path);
767 kfree(ctx);
768}
769
770/**
771 * apparmor_clone_security - clone the sk_security field
772 */
773static void apparmor_sk_clone_security(const struct sock *sk,
774 struct sock *newsk)
775{
776 struct aa_sk_ctx *ctx = SK_CTX(sk);
777 struct aa_sk_ctx *new = SK_CTX(newsk);
778
779 new->label = aa_get_label(ctx->label);
780 new->peer = aa_get_label(ctx->peer);
781 new->path = ctx->path;
782 path_get(&new->path);
783}
784
785static int aa_sock_create_perm(struct aa_label *label, int family, int type,
786 int protocol)
787{
788 AA_BUG(!label);
789 AA_BUG(in_interrupt());
790
791 return aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, family, type,
792 protocol);
793}
794
795
796/**
797 * apparmor_socket_create - check perms before creating a new socket
798 */
799static int apparmor_socket_create(int family, int type, int protocol, int kern)
800{
801 struct aa_label *label;
802 int error = 0;
803
804 label = begin_current_label_crit_section();
805 if (!(kern || unconfined(label)))
806 error = aa_sock_create_perm(label, family, type, protocol);
807 end_current_label_crit_section(label);
808
809 return error;
810}
811
812/**
813 * apparmor_socket_post_create - setup the per-socket security struct
814 *
815 * Note:
816 * - kernel sockets currently labeled unconfined but we may want to
817 * move to a special kernel label
818 * - socket may not have sk here if created with sock_create_lite or
819 * sock_alloc. These should be accept cases which will be handled in
820 * sock_graft.
821 */
822static int apparmor_socket_post_create(struct socket *sock, int family,
823 int type, int protocol, int kern)
824{
825 struct aa_label *label;
826
827 if (kern) {
828 struct aa_ns *ns = aa_get_current_ns();
829
830 label = aa_get_label(ns_unconfined(ns));
831 aa_put_ns(ns);
832 } else
833 label = aa_get_current_label();
834
835 if (sock->sk) {
836 struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
837
838 aa_put_label(ctx->label);
839 ctx->label = aa_get_label(label);
840 }
841 aa_put_label(label);
842
843 return 0;
844}
845
846/**
847 * apparmor_socket_bind - check perms before bind addr to socket
848 */
849static int apparmor_socket_bind(struct socket *sock,
850 struct sockaddr *address, int addrlen)
851{
852 AA_BUG(!sock);
853 AA_BUG(!sock->sk);
854 AA_BUG(!address);
855 AA_BUG(in_interrupt());
856
857 return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk);
858}
859
860/**
861 * apparmor_socket_connect - check perms before connecting @sock to @address
862 */
863static int apparmor_socket_connect(struct socket *sock,
864 struct sockaddr *address, int addrlen)
865{
866 AA_BUG(!sock);
867 AA_BUG(!sock->sk);
868 AA_BUG(!address);
869 AA_BUG(in_interrupt());
870
871 return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk);
872}
873
874/**
875 * apparmor_socket_list - check perms before allowing listen
876 */
877static int apparmor_socket_listen(struct socket *sock, int backlog)
878{
879 AA_BUG(!sock);
880 AA_BUG(!sock->sk);
881 AA_BUG(in_interrupt());
882
883 return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk);
884}
885
886/**
887 * apparmor_socket_accept - check perms before accepting a new connection.
888 *
889 * Note: while @newsock is created and has some information, the accept
890 * has not been done.
891 */
892static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
893{
894 AA_BUG(!sock);
895 AA_BUG(!sock->sk);
896 AA_BUG(!newsock);
897 AA_BUG(in_interrupt());
898
899 return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk);
900}
901
902static int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock,
903 struct msghdr *msg, int size)
904{
905 AA_BUG(!sock);
906 AA_BUG(!sock->sk);
907 AA_BUG(!msg);
908 AA_BUG(in_interrupt());
909
910 return aa_sk_perm(op, request, sock->sk);
911}
912
913/**
914 * apparmor_socket_sendmsg - check perms before sending msg to another socket
915 */
916static int apparmor_socket_sendmsg(struct socket *sock,
917 struct msghdr *msg, int size)
918{
919 return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size);
920}
921
922/**
923 * apparmor_socket_recvmsg - check perms before receiving a message
924 */
925static int apparmor_socket_recvmsg(struct socket *sock,
926 struct msghdr *msg, int size, int flags)
927{
928 return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size);
929}
930
931/* revaliation, get/set attr, shutdown */
932static int aa_sock_perm(const char *op, u32 request, struct socket *sock)
933{
934 AA_BUG(!sock);
935 AA_BUG(!sock->sk);
936 AA_BUG(in_interrupt());
937
938 return aa_sk_perm(op, request, sock->sk);
939}
940
941/**
942 * apparmor_socket_getsockname - check perms before getting the local address
943 */
944static int apparmor_socket_getsockname(struct socket *sock)
945{
946 return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock);
947}
948
949/**
950 * apparmor_socket_getpeername - check perms before getting remote address
951 */
952static int apparmor_socket_getpeername(struct socket *sock)
953{
954 return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock);
955}
956
957/* revaliation, get/set attr, opt */
958static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock,
959 int level, int optname)
960{
961 AA_BUG(!sock);
962 AA_BUG(!sock->sk);
963 AA_BUG(in_interrupt());
964
965 return aa_sk_perm(op, request, sock->sk);
966}
967
968/**
969 * apparmor_getsockopt - check perms before getting socket options
970 */
971static int apparmor_socket_getsockopt(struct socket *sock, int level,
972 int optname)
973{
974 return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock,
975 level, optname);
976}
977
978/**
979 * apparmor_setsockopt - check perms before setting socket options
980 */
981static int apparmor_socket_setsockopt(struct socket *sock, int level,
982 int optname)
983{
984 return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock,
985 level, optname);
986}
987
988/**
989 * apparmor_socket_shutdown - check perms before shutting down @sock conn
990 */
991static int apparmor_socket_shutdown(struct socket *sock, int how)
992{
993 return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock);
994}
995
996/**
997 * apparmor_socket_sock_recv_skb - check perms before associating skb to sk
998 *
999 * Note: can not sleep may be called with locks held
1000 *
1001 * dont want protocol specific in __skb_recv_datagram()
1002 * to deny an incoming connection socket_sock_rcv_skb()
1003 */
1004static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
1005{
1006 return 0;
1007}
1008
1009
1010static struct aa_label *sk_peer_label(struct sock *sk)
1011{
1012 struct aa_sk_ctx *ctx = SK_CTX(sk);
1013
1014 if (ctx->peer)
1015 return ctx->peer;
1016
1017 return ERR_PTR(-ENOPROTOOPT);
1018}
1019
1020/**
1021 * apparmor_socket_getpeersec_stream - get security context of peer
1022 *
1023 * Note: for tcp only valid if using ipsec or cipso on lan
1024 */
1025static int apparmor_socket_getpeersec_stream(struct socket *sock,
1026 char __user *optval,
1027 int __user *optlen,
1028 unsigned int len)
1029{
1030 char *name;
1031 int slen, error = 0;
1032 struct aa_label *label;
1033 struct aa_label *peer;
1034
1035 label = begin_current_label_crit_section();
1036 peer = sk_peer_label(sock->sk);
1037 if (IS_ERR(peer)) {
1038 error = PTR_ERR(peer);
1039 goto done;
1040 }
1041 slen = aa_label_asxprint(&name, labels_ns(label), peer,
1042 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
1043 FLAG_HIDDEN_UNCONFINED, GFP_KERNEL);
1044 /* don't include terminating \0 in slen, it breaks some apps */
1045 if (slen < 0) {
1046 error = -ENOMEM;
1047 } else {
1048 if (slen > len) {
1049 error = -ERANGE;
1050 } else if (copy_to_user(optval, name, slen)) {
1051 error = -EFAULT;
1052 goto out;
1053 }
1054 if (put_user(slen, optlen))
1055 error = -EFAULT;
1056out:
1057 kfree(name);
1058
1059 }
1060
1061done:
1062 end_current_label_crit_section(label);
1063
1064 return error;
1065}
1066
1067/**
1068 * apparmor_socket_getpeersec_dgram - get security label of packet
1069 * @sock: the peer socket
1070 * @skb: packet data
1071 * @secid: pointer to where to put the secid of the packet
1072 *
1073 * Sets the netlabel socket state on sk from parent
1074 */
1075static int apparmor_socket_getpeersec_dgram(struct socket *sock,
1076 struct sk_buff *skb, u32 *secid)
1077
1078{
1079 /* TODO: requires secid support */
1080 return -ENOPROTOOPT;
1081}
1082
1083/**
1084 * apparmor_sock_graft - Initialize newly created socket
1085 * @sk: child sock
1086 * @parent: parent socket
1087 *
1088 * Note: could set off of SOCK_CTX(parent) but need to track inode and we can
1089 * just set sk security information off of current creating process label
1090 * Labeling of sk for accept case - probably should be sock based
1091 * instead of task, because of the case where an implicitly labeled
1092 * socket is shared by different tasks.
1093 */
1094static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
1095{
1096 struct aa_sk_ctx *ctx = SK_CTX(sk);
1097
1098 if (!ctx->label)
1099 ctx->label = aa_get_current_label();
1100}
1101
739static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { 1102static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
740 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), 1103 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
741 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), 1104 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
@@ -770,6 +1133,30 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
770 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), 1133 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
771 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), 1134 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
772 1135
1136 LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
1137 LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
1138 LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
1139
1140 LSM_HOOK_INIT(socket_create, apparmor_socket_create),
1141 LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create),
1142 LSM_HOOK_INIT(socket_bind, apparmor_socket_bind),
1143 LSM_HOOK_INIT(socket_connect, apparmor_socket_connect),
1144 LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
1145 LSM_HOOK_INIT(socket_accept, apparmor_socket_accept),
1146 LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg),
1147 LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg),
1148 LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname),
1149 LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername),
1150 LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt),
1151 LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt),
1152 LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown),
1153 LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb),
1154 LSM_HOOK_INIT(socket_getpeersec_stream,
1155 apparmor_socket_getpeersec_stream),
1156 LSM_HOOK_INIT(socket_getpeersec_dgram,
1157 apparmor_socket_getpeersec_dgram),
1158 LSM_HOOK_INIT(sock_graft, apparmor_sock_graft),
1159
773 LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), 1160 LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
774 LSM_HOOK_INIT(cred_free, apparmor_cred_free), 1161 LSM_HOOK_INIT(cred_free, apparmor_cred_free),
775 LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare), 1162 LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
new file mode 100644
index 000000000000..33d54435f8d6
--- /dev/null
+++ b/security/apparmor/net.c
@@ -0,0 +1,184 @@
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/context.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
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
115 AA_BUG(family >= AF_MAX);
116 AA_BUG(type < 0 || type >= SOCK_MAX);
117
118 if (profile_unconfined(profile))
119 return 0;
120
121 perms.allow = (profile->net.allow[family] & (1 << type)) ?
122 ALL_PERMS_MASK : 0;
123 perms.audit = (profile->net.audit[family] & (1 << type)) ?
124 ALL_PERMS_MASK : 0;
125 perms.quiet = (profile->net.quiet[family] & (1 << type)) ?
126 ALL_PERMS_MASK : 0;
127 aa_apply_modes_to_perms(profile, &perms);
128
129 return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
130}
131
132int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
133 int type, int protocol)
134{
135 struct aa_profile *profile;
136 DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
137
138 return fn_for_each_confined(label, profile,
139 aa_profile_af_perm(profile, &sa, request, family,
140 type));
141}
142
143static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
144 struct sock *sk)
145{
146 struct aa_profile *profile;
147 DEFINE_AUDIT_SK(sa, op, sk);
148
149 AA_BUG(!label);
150 AA_BUG(!sk);
151
152 if (unconfined(label))
153 return 0;
154
155 return fn_for_each_confined(label, profile,
156 aa_profile_af_sk_perm(profile, &sa, request, sk));
157}
158
159int aa_sk_perm(const char *op, u32 request, struct sock *sk)
160{
161 struct aa_label *label;
162 int error;
163
164 AA_BUG(!sk);
165 AA_BUG(in_interrupt());
166
167 /* TODO: switch to begin_current_label ???? */
168 label = begin_current_label_crit_section();
169 error = aa_label_sk_perm(label, op, request, sk);
170 end_current_label_crit_section(label);
171
172 return error;
173}
174
175
176int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
177 struct socket *sock)
178{
179 AA_BUG(!label);
180 AA_BUG(!sock);
181 AA_BUG(!sock->sk);
182
183 return aa_label_sk_perm(label, op, request, sock->sk);
184}
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 4ede87c30f8b..5a2aec358322 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -275,6 +275,19 @@ fail:
275 return 0; 275 return 0;
276} 276}
277 277
278static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
279{
280 if (unpack_nameX(e, AA_U16, name)) {
281 if (!inbounds(e, sizeof(u16)))
282 return 0;
283 if (data)
284 *data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
285 e->pos += sizeof(u16);
286 return 1;
287 }
288 return 0;
289}
290
278static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) 291static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
279{ 292{
280 if (unpack_nameX(e, AA_U32, name)) { 293 if (unpack_nameX(e, AA_U32, name)) {
@@ -584,7 +597,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
584 struct aa_profile *profile = NULL; 597 struct aa_profile *profile = NULL;
585 const char *tmpname, *tmpns = NULL, *name = NULL; 598 const char *tmpname, *tmpns = NULL, *name = NULL;
586 const char *info = "failed to unpack profile"; 599 const char *info = "failed to unpack profile";
587 size_t ns_len; 600 size_t size = 0, ns_len;
588 struct rhashtable_params params = { 0 }; 601 struct rhashtable_params params = { 0 };
589 char *key = NULL; 602 char *key = NULL;
590 struct aa_data *data; 603 struct aa_data *data;
@@ -717,6 +730,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
717 goto fail; 730 goto fail;
718 } 731 }
719 732
733 size = unpack_array(e, "net_allowed_af");
734 if (size) {
735
736 for (i = 0; i < size; i++) {
737 /* discard extraneous rules that this kernel will
738 * never request
739 */
740 if (i >= AF_MAX) {
741 u16 tmp;
742
743 if (!unpack_u16(e, &tmp, NULL) ||
744 !unpack_u16(e, &tmp, NULL) ||
745 !unpack_u16(e, &tmp, NULL))
746 goto fail;
747 continue;
748 }
749 if (!unpack_u16(e, &profile->net.allow[i], NULL))
750 goto fail;
751 if (!unpack_u16(e, &profile->net.audit[i], NULL))
752 goto fail;
753 if (!unpack_u16(e, &profile->net.quiet[i], NULL))
754 goto fail;
755 }
756 if (!unpack_nameX(e, AA_ARRAYEND, NULL))
757 goto fail;
758 }
759 if (VERSION_LT(e->version, v7)) {
760 /* pre v7 policy always allowed these */
761 profile->net.allow[AF_UNIX] = 0xffff;
762 profile->net.allow[AF_NETLINK] = 0xffff;
763 }
764
720 if (unpack_nameX(e, AA_STRUCT, "policydb")) { 765 if (unpack_nameX(e, AA_STRUCT, "policydb")) {
721 /* generic policy dfa - optional and may be NULL */ 766 /* generic policy dfa - optional and may be NULL */
722 info = "failed to unpack policydb"; 767 info = "failed to unpack policydb";