]> git.pld-linux.org Git - packages/kernel.git/blame - 0001-apparmor-add-base-infastructure-for-socket-mediation.patch
- 4.15.11
[packages/kernel.git] / 0001-apparmor-add-base-infastructure-for-socket-mediation.patch
CommitLineData
d75b40d3 1From 27d9aac1346ff7feb6a49bfb33510c2d79a41da7 Mon Sep 17 00:00:00 2001
daaa955e
AM
2From: John Johansen <john.johansen@canonical.com>
3Date: Tue, 18 Jul 2017 23:18:33 -0700
d75b40d3 4Subject: [PATCH 1/2] apparmor: add base infastructure for socket mediation
daaa955e
AM
5
6Provide a basic mediation of sockets. This is not a full net mediation
7but just whether a spcific family of socket can be used by an
8application, along with setting up some basic infrastructure for
9network mediation to follow.
10
11the user space rule hav the basic form of
12 NETWORK RULE = [ QUALIFIERS ] 'network' [ DOMAIN ]
13 [ TYPE | PROTOCOL ]
14
15 DOMAIN = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' |
16 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' |
17 'netbeui' | 'security' | 'key' | 'packet' | 'ash' |
18 'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' |
19 'wanpipe' | 'bluetooth' | 'netlink' | 'unix' | 'rds' |
20 'llc' | 'can' | 'tipc' | 'iucv' | 'rxrpc' | 'isdn' |
21 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' |
22 'vsock' | 'mpls' | 'ib' | 'kcm' ) ','
23
24 TYPE = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' |
25 'packet' )
26
27 PROTOCOL = ( 'tcp' | 'udp' | 'icmp' )
28
29eg.
30 network,
31 network inet,
32
33Signed-off-by: John Johansen <john.johansen@canonical.com>
34Acked-by: Seth Arnold <seth.arnold@canonical.com>
daaa955e
AM
35---
36 security/apparmor/.gitignore | 1 +
37 security/apparmor/Makefile | 43 ++++-
38 security/apparmor/apparmorfs.c | 1 +
39 security/apparmor/file.c | 30 +++
d75b40d3 40 security/apparmor/include/audit.h | 16 +-
daaa955e
AM
41 security/apparmor/include/net.h | 114 +++++++++++
42 security/apparmor/include/perms.h | 5 +-
43 security/apparmor/include/policy.h | 13 ++
44 security/apparmor/lib.c | 5 +-
45 security/apparmor/lsm.c | 387 +++++++++++++++++++++++++++++++++++++
46 security/apparmor/net.c | 184 ++++++++++++++++++
47 security/apparmor/policy_unpack.c | 47 ++++-
d75b40d3 48 12 files changed, 834 insertions(+), 12 deletions(-)
daaa955e
AM
49 create mode 100644 security/apparmor/include/net.h
50 create mode 100644 security/apparmor/net.c
51
52diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
53index 9cdec70d72b8..d5b291e94264 100644
54--- a/security/apparmor/.gitignore
55+++ b/security/apparmor/.gitignore
56@@ -1,5 +1,6 @@
57 #
58 # Generated include files
59 #
60+net_names.h
61 capability_names.h
62 rlim_names.h
63diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
d75b40d3 64index 9a6b4033d52b..e7ff2183532a 100644
daaa955e
AM
65--- a/security/apparmor/Makefile
66+++ b/security/apparmor/Makefile
d75b40d3 67@@ -5,11 +5,44 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
daaa955e
AM
68
69 apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
70 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
71- resource.o secid.o file.o policy_ns.o label.o mount.o
72+ resource.o secid.o file.o policy_ns.o label.o mount.o net.o
73 apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
74
75-clean-files := capability_names.h rlim_names.h
76+clean-files := capability_names.h rlim_names.h net_names.h
77
78+# Build a lower case string table of address family names
79+# Transform lines from
80+# #define AF_LOCAL 1 /* POSIX name for AF_UNIX */
81+# #define AF_INET 2 /* Internet IP Protocol */
82+# to
83+# [1] = "local",
84+# [2] = "inet",
85+#
86+# and build the securityfs entries for the mapping.
87+# Transforms lines from
88+# #define AF_INET 2 /* Internet IP Protocol */
89+# to
90+# #define AA_SFS_AF_MASK "local inet"
91+quiet_cmd_make-af = GEN $@
92+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
93+ sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
94+ 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
95+ echo "};" >> $@ ;\
96+ printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\
97+ sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
98+ 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
99+ $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
100+
101+# Build a lower case string table of sock type names
102+# Transform lines from
103+# SOCK_STREAM = 1,
104+# to
105+# [1] = "stream",
106+quiet_cmd_make-sock = GEN $@
107+cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
108+ sed $^ >>$@ -r -n \
109+ -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
110+ echo "};" >> $@
111
112 # Build a lower case string table of capability names
113 # Transforms lines from
d75b40d3 114@@ -62,6 +95,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
daaa955e
AM
115 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
116
117 $(obj)/capability.o : $(obj)/capability_names.h
118+$(obj)/net.o : $(obj)/net_names.h
119 $(obj)/resource.o : $(obj)/rlim_names.h
120 $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
121 $(src)/Makefile
d75b40d3 122@@ -69,3 +103,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
daaa955e
AM
123 $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
124 $(src)/Makefile
125 $(call cmd,make-rlim)
126+$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
127+ $(srctree)/include/linux/net.h \
128+ $(src)/Makefile
129+ $(call cmd,make-af)
130+ $(call cmd,make-sock)
131diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
d75b40d3 132index d4fa04d91439..694c4f48a975 100644
daaa955e
AM
133--- a/security/apparmor/apparmorfs.c
134+++ b/security/apparmor/apparmorfs.c
135@@ -2202,6 +2202,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
136 AA_SFS_DIR("policy", aa_sfs_entry_policy),
137 AA_SFS_DIR("domain", aa_sfs_entry_domain),
138 AA_SFS_DIR("file", aa_sfs_entry_file),
139+ AA_SFS_DIR("network", aa_sfs_entry_network),
140 AA_SFS_DIR("mount", aa_sfs_entry_mount),
141 AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
142 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
143diff --git a/security/apparmor/file.c b/security/apparmor/file.c
d75b40d3 144index e79bf44396a3..86d57e56fabe 100644
daaa955e
AM
145--- a/security/apparmor/file.c
146+++ b/security/apparmor/file.c
147@@ -21,6 +21,7 @@
148 #include "include/context.h"
149 #include "include/file.h"
150 #include "include/match.h"
151+#include "include/net.h"
152 #include "include/path.h"
153 #include "include/policy.h"
154 #include "include/label.h"
d75b40d3 155@@ -560,6 +561,32 @@ static int __file_path_perm(const char *op, struct aa_label *label,
daaa955e
AM
156 return error;
157 }
158
159+static int __file_sock_perm(const char *op, struct aa_label *label,
160+ struct aa_label *flabel, struct file *file,
161+ u32 request, u32 denied)
162+{
163+ struct socket *sock = (struct socket *) file->private_data;
164+ int error;
165+
166+ AA_BUG(!sock);
167+
168+ /* revalidation due to label out of date. No revocation at this time */
169+ if (!denied && aa_label_is_subset(flabel, label))
170+ return 0;
171+
172+ /* TODO: improve to skip profiles cached in flabel */
173+ error = aa_sock_file_perm(label, op, request, sock);
174+ if (denied) {
175+ /* TODO: improve to skip profiles checked above */
176+ /* check every profile in file label to is cached */
177+ last_error(error, aa_sock_file_perm(flabel, op, request, sock));
178+ }
179+ if (!error)
180+ update_file_ctx(file_ctx(file), label, request);
181+
182+ return error;
183+}
184+
185 /**
186 * aa_file_perm - do permission revalidation check & audit for @file
187 * @op: operation being checked
d75b40d3 188@@ -604,6 +631,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
daaa955e
AM
189 error = __file_path_perm(op, label, flabel, file, request,
190 denied);
191
192+ else if (S_ISSOCK(file_inode(file)->i_mode))
193+ error = __file_sock_perm(op, label, flabel, file, request,
194+ denied);
195 done:
196 rcu_read_unlock();
197
198diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
d75b40d3 199index 4ac095118717..ff4316e1068d 100644
daaa955e
AM
200--- a/security/apparmor/include/audit.h
201+++ b/security/apparmor/include/audit.h
d75b40d3 202@@ -123,10 +123,20 @@ struct apparmor_audit_data {
daaa955e 203 struct aa_label *peer;
d75b40d3
AM
204 union {
205 struct {
29e30844 206- const char *target;
d75b40d3 207 kuid_t ouid;
daaa955e 208+ const char *target;
d75b40d3 209 } fs;
daaa955e
AM
210+ struct {
211+ int type, protocol;
212+ struct sock *peer_sk;
213+ void *addr;
214+ int addrlen;
215+ } net;
d75b40d3 216 int signal;
daaa955e
AM
217+ struct {
218+ int rlim;
219+ unsigned long max;
220+ } rlim;
d75b40d3 221 };
daaa955e
AM
222 };
223 struct {
d75b40d3 224@@ -134,10 +144,6 @@ struct apparmor_audit_data {
daaa955e
AM
225 const char *ns;
226 long pos;
227 } iface;
daaa955e
AM
228- struct {
229- int rlim;
230- unsigned long max;
231- } rlim;
232 struct {
233 const char *src_name;
234 const char *type;
235diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
236new file mode 100644
237index 000000000000..140c8efcf364
238--- /dev/null
239+++ b/security/apparmor/include/net.h
240@@ -0,0 +1,114 @@
241+/*
242+ * AppArmor security module
243+ *
244+ * This file contains AppArmor network mediation definitions.
245+ *
246+ * Copyright (C) 1998-2008 Novell/SUSE
247+ * Copyright 2009-2017 Canonical Ltd.
248+ *
249+ * This program is free software; you can redistribute it and/or
250+ * modify it under the terms of the GNU General Public License as
251+ * published by the Free Software Foundation, version 2 of the
252+ * License.
253+ */
254+
255+#ifndef __AA_NET_H
256+#define __AA_NET_H
257+
258+#include <net/sock.h>
259+#include <linux/path.h>
260+
261+#include "apparmorfs.h"
262+#include "label.h"
263+#include "perms.h"
264+#include "policy.h"
265+
266+#define AA_MAY_SEND AA_MAY_WRITE
267+#define AA_MAY_RECEIVE AA_MAY_READ
268+
269+#define AA_MAY_SHUTDOWN AA_MAY_DELETE
270+
271+#define AA_MAY_CONNECT AA_MAY_OPEN
272+#define AA_MAY_ACCEPT 0x00100000
273+
274+#define AA_MAY_BIND 0x00200000
275+#define AA_MAY_LISTEN 0x00400000
276+
277+#define AA_MAY_SETOPT 0x01000000
278+#define AA_MAY_GETOPT 0x02000000
279+
280+#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
281+ AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN | \
282+ AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
283+ AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)
284+
285+#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
286+ AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
287+ AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD | \
288+ AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK | \
289+ AA_MAY_MPROT)
290+
291+#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
292+ AA_MAY_ACCEPT)
293+struct aa_sk_ctx {
294+ struct aa_label *label;
295+ struct aa_label *peer;
296+ struct path path;
297+};
298+
299+#define SK_CTX(X) ((X)->sk_security)
300+#define SOCK_ctx(X) SOCK_INODE(X)->i_security
301+#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \
302+ struct lsm_network_audit NAME ## _net = { .sk = (SK), \
303+ .family = (F)}; \
304+ DEFINE_AUDIT_DATA(NAME, \
305+ ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \
306+ LSM_AUDIT_DATA_NONE, \
307+ OP); \
308+ NAME.u.net = &(NAME ## _net); \
309+ aad(&NAME)->net.type = (T); \
310+ aad(&NAME)->net.protocol = (P)
311+
312+#define DEFINE_AUDIT_SK(NAME, OP, SK) \
313+ DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \
314+ (SK)->sk_protocol)
315+
316+/* struct aa_net - network confinement data
317+ * @allow: basic network families permissions
318+ * @audit: which network permissions to force audit
319+ * @quiet: which network permissions to quiet rejects
320+ */
321+struct aa_net {
322+ u16 allow[AF_MAX];
323+ u16 audit[AF_MAX];
324+ u16 quiet[AF_MAX];
325+};
326+
327+
328+extern struct aa_sfs_entry aa_sfs_entry_network[];
329+
330+void audit_net_cb(struct audit_buffer *ab, void *va);
331+int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
332+ u32 request, u16 family, int type);
333+int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
334+ int type, int protocol);
335+static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
336+ struct common_audit_data *sa,
337+ u32 request,
338+ struct sock *sk)
339+{
340+ return aa_profile_af_perm(profile, sa, request, sk->sk_family,
341+ sk->sk_type);
342+}
343+int aa_sk_perm(const char *op, u32 request, struct sock *sk);
344+
345+int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
346+ struct socket *sock);
347+
348+
349+static inline void aa_free_net_rules(struct aa_net *new)
350+{
351+ /* NOP */
352+}
353+
354+#endif /* __AA_NET_H */
355diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h
d75b40d3 356index d7b7e7115160..38aa6247d00f 100644
daaa955e
AM
357--- a/security/apparmor/include/perms.h
358+++ b/security/apparmor/include/perms.h
d75b40d3 359@@ -138,9 +138,10 @@ extern struct aa_perms allperms;
daaa955e
AM
360
361
362 void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
363-void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
364+void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
365+ u32 mask);
366 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
367- u32 chrsmask, const char **names, u32 namesmask);
368+ u32 chrsmask, const char * const *names, u32 namesmask);
369 void aa_apply_modes_to_perms(struct aa_profile *profile,
370 struct aa_perms *perms);
371 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
372diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
373index 17fe41a9cac3..4364088a0b9e 100644
374--- a/security/apparmor/include/policy.h
375+++ b/security/apparmor/include/policy.h
376@@ -30,6 +30,7 @@
377 #include "file.h"
378 #include "lib.h"
379 #include "label.h"
380+#include "net.h"
381 #include "perms.h"
382 #include "resource.h"
383
384@@ -111,6 +112,7 @@ struct aa_data {
385 * @policy: general match rules governing policy
386 * @file: The set of rules governing basic file access and domain transitions
387 * @caps: capabilities for the profile
388+ * @net: network controls for the profile
389 * @rlimits: rlimits for the profile
390 *
391 * @dents: dentries for the profiles file entries in apparmorfs
392@@ -148,6 +150,7 @@ struct aa_profile {
393 struct aa_policydb policy;
394 struct aa_file_rules file;
395 struct aa_caps caps;
396+ struct aa_net net;
397 struct aa_rlimit rlimits;
398
399 struct aa_loaddata *rawdata;
400@@ -220,6 +223,16 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
401 return 0;
402 }
403
404+static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
405+ u16 AF) {
406+ unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
407+ u16 be_af = cpu_to_be16(AF);
408+
409+ if (!state)
410+ return 0;
411+ return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
412+}
413+
414 /**
415 * aa_get_profile - increment refcount on profile @p
416 * @p: profile (MAYBE NULL)
417diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
d75b40d3 418index 4d5e98e49d5e..068a9f471f77 100644
daaa955e
AM
419--- a/security/apparmor/lib.c
420+++ b/security/apparmor/lib.c
421@@ -211,7 +211,8 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
422 *str = '\0';
423 }
424
425-void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
426+void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
427+ u32 mask)
428 {
429 const char *fmt = "%s";
430 unsigned int i, perm = 1;
431@@ -229,7 +230,7 @@ void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
432 }
433
434 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
435- u32 chrsmask, const char **names, u32 namesmask)
436+ u32 chrsmask, const char * const *names, u32 namesmask)
437 {
438 char str[33];
439
440diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
d75b40d3 441index 9a65eeaf7dfa..0cd717614fd0 100644
daaa955e
AM
442--- a/security/apparmor/lsm.c
443+++ b/security/apparmor/lsm.c
444@@ -33,6 +33,7 @@
445 #include "include/context.h"
446 #include "include/file.h"
447 #include "include/ipc.h"
448+#include "include/net.h"
449 #include "include/path.h"
450 #include "include/label.h"
451 #include "include/policy.h"
452@@ -736,6 +737,368 @@ static int apparmor_task_kill(struct task_struct *target, struct siginfo *info,
453 return error;
454 }
455
456+/**
457+ * apparmor_sk_alloc_security - allocate and attach the sk_security field
458+ */
459+static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
460+{
461+ struct aa_sk_ctx *ctx;
462+
463+ ctx = kzalloc(sizeof(*ctx), flags);
464+ if (!ctx)
465+ return -ENOMEM;
466+
467+ SK_CTX(sk) = ctx;
468+
469+ return 0;
470+}
471+
472+/**
473+ * apparmor_sk_free_security - free the sk_security field
474+ */
475+static void apparmor_sk_free_security(struct sock *sk)
476+{
477+ struct aa_sk_ctx *ctx = SK_CTX(sk);
478+
479+ SK_CTX(sk) = NULL;
480+ aa_put_label(ctx->label);
481+ aa_put_label(ctx->peer);
482+ path_put(&ctx->path);
483+ kfree(ctx);
484+}
485+
486+/**
487+ * apparmor_clone_security - clone the sk_security field
488+ */
489+static void apparmor_sk_clone_security(const struct sock *sk,
490+ struct sock *newsk)
491+{
492+ struct aa_sk_ctx *ctx = SK_CTX(sk);
493+ struct aa_sk_ctx *new = SK_CTX(newsk);
494+
495+ new->label = aa_get_label(ctx->label);
496+ new->peer = aa_get_label(ctx->peer);
497+ new->path = ctx->path;
498+ path_get(&new->path);
499+}
500+
501+static int aa_sock_create_perm(struct aa_label *label, int family, int type,
502+ int protocol)
503+{
504+ AA_BUG(!label);
505+ AA_BUG(in_interrupt());
506+
507+ return aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, family, type,
508+ protocol);
509+}
510+
511+
512+/**
513+ * apparmor_socket_create - check perms before creating a new socket
514+ */
515+static int apparmor_socket_create(int family, int type, int protocol, int kern)
516+{
517+ struct aa_label *label;
518+ int error = 0;
519+
520+ label = begin_current_label_crit_section();
521+ if (!(kern || unconfined(label)))
522+ error = aa_sock_create_perm(label, family, type, protocol);
523+ end_current_label_crit_section(label);
524+
525+ return error;
526+}
527+
528+/**
529+ * apparmor_socket_post_create - setup the per-socket security struct
530+ *
531+ * Note:
532+ * - kernel sockets currently labeled unconfined but we may want to
533+ * move to a special kernel label
534+ * - socket may not have sk here if created with sock_create_lite or
535+ * sock_alloc. These should be accept cases which will be handled in
536+ * sock_graft.
537+ */
538+static int apparmor_socket_post_create(struct socket *sock, int family,
539+ int type, int protocol, int kern)
540+{
541+ struct aa_label *label;
542+
543+ if (kern) {
544+ struct aa_ns *ns = aa_get_current_ns();
545+
546+ label = aa_get_label(ns_unconfined(ns));
547+ aa_put_ns(ns);
548+ } else
549+ label = aa_get_current_label();
550+
551+ if (sock->sk) {
552+ struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
553+
554+ aa_put_label(ctx->label);
555+ ctx->label = aa_get_label(label);
556+ }
557+ aa_put_label(label);
558+
559+ return 0;
560+}
561+
562+/**
563+ * apparmor_socket_bind - check perms before bind addr to socket
564+ */
565+static int apparmor_socket_bind(struct socket *sock,
566+ struct sockaddr *address, int addrlen)
567+{
568+ AA_BUG(!sock);
569+ AA_BUG(!sock->sk);
570+ AA_BUG(!address);
571+ AA_BUG(in_interrupt());
572+
573+ return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk);
574+}
575+
576+/**
577+ * apparmor_socket_connect - check perms before connecting @sock to @address
578+ */
579+static int apparmor_socket_connect(struct socket *sock,
580+ struct sockaddr *address, int addrlen)
581+{
582+ AA_BUG(!sock);
583+ AA_BUG(!sock->sk);
584+ AA_BUG(!address);
585+ AA_BUG(in_interrupt());
586+
587+ return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk);
588+}
589+
590+/**
591+ * apparmor_socket_list - check perms before allowing listen
592+ */
593+static int apparmor_socket_listen(struct socket *sock, int backlog)
594+{
595+ AA_BUG(!sock);
596+ AA_BUG(!sock->sk);
597+ AA_BUG(in_interrupt());
598+
599+ return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk);
600+}
601+
602+/**
603+ * apparmor_socket_accept - check perms before accepting a new connection.
604+ *
605+ * Note: while @newsock is created and has some information, the accept
606+ * has not been done.
607+ */
608+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
609+{
610+ AA_BUG(!sock);
611+ AA_BUG(!sock->sk);
612+ AA_BUG(!newsock);
613+ AA_BUG(in_interrupt());
614+
615+ return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk);
616+}
617+
618+static int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock,
619+ struct msghdr *msg, int size)
620+{
621+ AA_BUG(!sock);
622+ AA_BUG(!sock->sk);
623+ AA_BUG(!msg);
624+ AA_BUG(in_interrupt());
625+
626+ return aa_sk_perm(op, request, sock->sk);
627+}
628+
629+/**
630+ * apparmor_socket_sendmsg - check perms before sending msg to another socket
631+ */
632+static int apparmor_socket_sendmsg(struct socket *sock,
633+ struct msghdr *msg, int size)
634+{
635+ return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size);
636+}
637+
638+/**
639+ * apparmor_socket_recvmsg - check perms before receiving a message
640+ */
641+static int apparmor_socket_recvmsg(struct socket *sock,
642+ struct msghdr *msg, int size, int flags)
643+{
644+ return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size);
645+}
646+
647+/* revaliation, get/set attr, shutdown */
648+static int aa_sock_perm(const char *op, u32 request, struct socket *sock)
649+{
650+ AA_BUG(!sock);
651+ AA_BUG(!sock->sk);
652+ AA_BUG(in_interrupt());
653+
654+ return aa_sk_perm(op, request, sock->sk);
655+}
656+
657+/**
658+ * apparmor_socket_getsockname - check perms before getting the local address
659+ */
660+static int apparmor_socket_getsockname(struct socket *sock)
661+{
662+ return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock);
663+}
664+
665+/**
666+ * apparmor_socket_getpeername - check perms before getting remote address
667+ */
668+static int apparmor_socket_getpeername(struct socket *sock)
669+{
670+ return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock);
671+}
672+
673+/* revaliation, get/set attr, opt */
674+static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock,
675+ int level, int optname)
676+{
677+ AA_BUG(!sock);
678+ AA_BUG(!sock->sk);
679+ AA_BUG(in_interrupt());
680+
681+ return aa_sk_perm(op, request, sock->sk);
682+}
683+
684+/**
685+ * apparmor_getsockopt - check perms before getting socket options
686+ */
687+static int apparmor_socket_getsockopt(struct socket *sock, int level,
688+ int optname)
689+{
690+ return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock,
691+ level, optname);
692+}
693+
694+/**
695+ * apparmor_setsockopt - check perms before setting socket options
696+ */
697+static int apparmor_socket_setsockopt(struct socket *sock, int level,
698+ int optname)
699+{
700+ return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock,
701+ level, optname);
702+}
703+
704+/**
705+ * apparmor_socket_shutdown - check perms before shutting down @sock conn
706+ */
707+static int apparmor_socket_shutdown(struct socket *sock, int how)
708+{
709+ return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock);
710+}
711+
712+/**
713+ * apparmor_socket_sock_recv_skb - check perms before associating skb to sk
714+ *
715+ * Note: can not sleep may be called with locks held
716+ *
717+ * dont want protocol specific in __skb_recv_datagram()
718+ * to deny an incoming connection socket_sock_rcv_skb()
719+ */
720+static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
721+{
722+ return 0;
723+}
724+
725+
726+static struct aa_label *sk_peer_label(struct sock *sk)
727+{
728+ struct aa_sk_ctx *ctx = SK_CTX(sk);
729+
730+ if (ctx->peer)
731+ return ctx->peer;
732+
733+ return ERR_PTR(-ENOPROTOOPT);
734+}
735+
736+/**
737+ * apparmor_socket_getpeersec_stream - get security context of peer
738+ *
739+ * Note: for tcp only valid if using ipsec or cipso on lan
740+ */
741+static int apparmor_socket_getpeersec_stream(struct socket *sock,
742+ char __user *optval,
743+ int __user *optlen,
744+ unsigned int len)
745+{
746+ char *name;
747+ int slen, error = 0;
748+ struct aa_label *label;
749+ struct aa_label *peer;
750+
751+ label = begin_current_label_crit_section();
752+ peer = sk_peer_label(sock->sk);
753+ if (IS_ERR(peer)) {
754+ error = PTR_ERR(peer);
755+ goto done;
756+ }
757+ slen = aa_label_asxprint(&name, labels_ns(label), peer,
758+ FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
759+ FLAG_HIDDEN_UNCONFINED, GFP_KERNEL);
760+ /* don't include terminating \0 in slen, it breaks some apps */
761+ if (slen < 0) {
762+ error = -ENOMEM;
763+ } else {
764+ if (slen > len) {
765+ error = -ERANGE;
766+ } else if (copy_to_user(optval, name, slen)) {
767+ error = -EFAULT;
768+ goto out;
769+ }
770+ if (put_user(slen, optlen))
771+ error = -EFAULT;
772+out:
773+ kfree(name);
774+
775+ }
776+
777+done:
778+ end_current_label_crit_section(label);
779+
780+ return error;
781+}
782+
783+/**
784+ * apparmor_socket_getpeersec_dgram - get security label of packet
785+ * @sock: the peer socket
786+ * @skb: packet data
787+ * @secid: pointer to where to put the secid of the packet
788+ *
789+ * Sets the netlabel socket state on sk from parent
790+ */
791+static int apparmor_socket_getpeersec_dgram(struct socket *sock,
792+ struct sk_buff *skb, u32 *secid)
793+
794+{
795+ /* TODO: requires secid support */
796+ return -ENOPROTOOPT;
797+}
798+
799+/**
800+ * apparmor_sock_graft - Initialize newly created socket
801+ * @sk: child sock
802+ * @parent: parent socket
803+ *
804+ * Note: could set off of SOCK_CTX(parent) but need to track inode and we can
805+ * just set sk security information off of current creating process label
806+ * Labeling of sk for accept case - probably should be sock based
807+ * instead of task, because of the case where an implicitly labeled
808+ * socket is shared by different tasks.
809+ */
810+static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
811+{
812+ struct aa_sk_ctx *ctx = SK_CTX(sk);
813+
814+ if (!ctx->label)
815+ ctx->label = aa_get_current_label();
816+}
817+
818 static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
819 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
820 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
821@@ -770,6 +1133,30 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
822 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
823 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
824
825+ LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
826+ LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
827+ LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
828+
829+ LSM_HOOK_INIT(socket_create, apparmor_socket_create),
830+ LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create),
831+ LSM_HOOK_INIT(socket_bind, apparmor_socket_bind),
832+ LSM_HOOK_INIT(socket_connect, apparmor_socket_connect),
833+ LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
834+ LSM_HOOK_INIT(socket_accept, apparmor_socket_accept),
835+ LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg),
836+ LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg),
837+ LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname),
838+ LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername),
839+ LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt),
840+ LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt),
841+ LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown),
842+ LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb),
843+ LSM_HOOK_INIT(socket_getpeersec_stream,
844+ apparmor_socket_getpeersec_stream),
845+ LSM_HOOK_INIT(socket_getpeersec_dgram,
846+ apparmor_socket_getpeersec_dgram),
847+ LSM_HOOK_INIT(sock_graft, apparmor_sock_graft),
848+
849 LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
850 LSM_HOOK_INIT(cred_free, apparmor_cred_free),
851 LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
852diff --git a/security/apparmor/net.c b/security/apparmor/net.c
853new file mode 100644
854index 000000000000..33d54435f8d6
855--- /dev/null
856+++ b/security/apparmor/net.c
857@@ -0,0 +1,184 @@
858+/*
859+ * AppArmor security module
860+ *
861+ * This file contains AppArmor network mediation
862+ *
863+ * Copyright (C) 1998-2008 Novell/SUSE
864+ * Copyright 2009-2017 Canonical Ltd.
865+ *
866+ * This program is free software; you can redistribute it and/or
867+ * modify it under the terms of the GNU General Public License as
868+ * published by the Free Software Foundation, version 2 of the
869+ * License.
870+ */
871+
872+#include "include/apparmor.h"
873+#include "include/audit.h"
874+#include "include/context.h"
875+#include "include/label.h"
876+#include "include/net.h"
877+#include "include/policy.h"
878+
879+#include "net_names.h"
880+
881+
882+struct aa_sfs_entry aa_sfs_entry_network[] = {
883+ AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),
884+ { }
885+};
886+
887+static const char * const net_mask_names[] = {
888+ "unknown",
889+ "send",
890+ "receive",
891+ "unknown",
892+
893+ "create",
894+ "shutdown",
895+ "connect",
896+ "unknown",
897+
898+ "setattr",
899+ "getattr",
900+ "setcred",
901+ "getcred",
902+
903+ "chmod",
904+ "chown",
905+ "chgrp",
906+ "lock",
907+
908+ "mmap",
909+ "mprot",
910+ "unknown",
911+ "unknown",
912+
913+ "accept",
914+ "bind",
915+ "listen",
916+ "unknown",
917+
918+ "setopt",
919+ "getopt",
920+ "unknown",
921+ "unknown",
922+
923+ "unknown",
924+ "unknown",
925+ "unknown",
926+ "unknown",
927+};
928+
929+
930+/* audit callback for net specific fields */
931+void audit_net_cb(struct audit_buffer *ab, void *va)
932+{
933+ struct common_audit_data *sa = va;
934+
935+ audit_log_format(ab, " family=");
936+ if (address_family_names[sa->u.net->family])
937+ audit_log_string(ab, address_family_names[sa->u.net->family]);
938+ else
939+ audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
940+ audit_log_format(ab, " sock_type=");
941+ if (sock_type_names[aad(sa)->net.type])
942+ audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
943+ else
944+ audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
945+ audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
946+
947+ if (aad(sa)->request & NET_PERMS_MASK) {
948+ audit_log_format(ab, " requested_mask=");
949+ aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
950+ net_mask_names, NET_PERMS_MASK);
951+
952+ if (aad(sa)->denied & NET_PERMS_MASK) {
953+ audit_log_format(ab, " denied_mask=");
954+ aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
955+ net_mask_names, NET_PERMS_MASK);
956+ }
957+ }
958+ if (aad(sa)->peer) {
959+ audit_log_format(ab, " peer=");
960+ aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
961+ FLAGS_NONE, GFP_ATOMIC);
962+ }
963+}
964+
965+
966+/* Generic af perm */
967+int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
968+ u32 request, u16 family, int type)
969+{
970+ struct aa_perms perms = { };
971+
972+ AA_BUG(family >= AF_MAX);
973+ AA_BUG(type < 0 || type >= SOCK_MAX);
974+
975+ if (profile_unconfined(profile))
976+ return 0;
977+
978+ perms.allow = (profile->net.allow[family] & (1 << type)) ?
979+ ALL_PERMS_MASK : 0;
980+ perms.audit = (profile->net.audit[family] & (1 << type)) ?
981+ ALL_PERMS_MASK : 0;
982+ perms.quiet = (profile->net.quiet[family] & (1 << type)) ?
983+ ALL_PERMS_MASK : 0;
984+ aa_apply_modes_to_perms(profile, &perms);
985+
986+ return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
987+}
988+
989+int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
990+ int type, int protocol)
991+{
992+ struct aa_profile *profile;
993+ DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
994+
995+ return fn_for_each_confined(label, profile,
996+ aa_profile_af_perm(profile, &sa, request, family,
997+ type));
998+}
999+
1000+static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
1001+ struct sock *sk)
1002+{
1003+ struct aa_profile *profile;
1004+ DEFINE_AUDIT_SK(sa, op, sk);
1005+
1006+ AA_BUG(!label);
1007+ AA_BUG(!sk);
1008+
1009+ if (unconfined(label))
1010+ return 0;
1011+
1012+ return fn_for_each_confined(label, profile,
1013+ aa_profile_af_sk_perm(profile, &sa, request, sk));
1014+}
1015+
1016+int aa_sk_perm(const char *op, u32 request, struct sock *sk)
1017+{
1018+ struct aa_label *label;
1019+ int error;
1020+
1021+ AA_BUG(!sk);
1022+ AA_BUG(in_interrupt());
1023+
1024+ /* TODO: switch to begin_current_label ???? */
1025+ label = begin_current_label_crit_section();
1026+ error = aa_label_sk_perm(label, op, request, sk);
1027+ end_current_label_crit_section(label);
1028+
1029+ return error;
1030+}
1031+
1032+
1033+int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
1034+ struct socket *sock)
1035+{
1036+ AA_BUG(!label);
1037+ AA_BUG(!sock);
1038+ AA_BUG(!sock->sk);
1039+
1040+ return aa_label_sk_perm(label, op, request, sock->sk);
1041+}
1042diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
d75b40d3 1043index 59a1a25b7d43..68b168e8f499 100644
daaa955e
AM
1044--- a/security/apparmor/policy_unpack.c
1045+++ b/security/apparmor/policy_unpack.c
1046@@ -275,6 +275,19 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
1047 return 0;
1048 }
1049
1050+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
1051+{
1052+ if (unpack_nameX(e, AA_U16, name)) {
1053+ if (!inbounds(e, sizeof(u16)))
1054+ return 0;
1055+ if (data)
1056+ *data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
1057+ e->pos += sizeof(u16);
1058+ return 1;
1059+ }
1060+ return 0;
1061+}
1062+
1063 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
1064 {
1065 if (unpack_nameX(e, AA_U32, name)) {
1066@@ -584,7 +597,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
1067 struct aa_profile *profile = NULL;
1068 const char *tmpname, *tmpns = NULL, *name = NULL;
1069 const char *info = "failed to unpack profile";
1070- size_t ns_len;
1071+ size_t size = 0, ns_len;
1072 struct rhashtable_params params = { 0 };
1073 char *key = NULL;
1074 struct aa_data *data;
1075@@ -717,6 +730,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
1076 goto fail;
1077 }
1078
1079+ size = unpack_array(e, "net_allowed_af");
1080+ if (size) {
1081+
1082+ for (i = 0; i < size; i++) {
1083+ /* discard extraneous rules that this kernel will
1084+ * never request
1085+ */
1086+ if (i >= AF_MAX) {
1087+ u16 tmp;
1088+
1089+ if (!unpack_u16(e, &tmp, NULL) ||
1090+ !unpack_u16(e, &tmp, NULL) ||
1091+ !unpack_u16(e, &tmp, NULL))
1092+ goto fail;
1093+ continue;
1094+ }
1095+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
1096+ goto fail;
1097+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
1098+ goto fail;
1099+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
1100+ goto fail;
1101+ }
1102+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
1103+ goto fail;
1104+ }
1105+ if (VERSION_LT(e->version, v7)) {
1106+ /* pre v7 policy always allowed these */
1107+ profile->net.allow[AF_UNIX] = 0xffff;
1108+ profile->net.allow[AF_NETLINK] = 0xffff;
1109+ }
1110+
1111 if (unpack_nameX(e, AA_STRUCT, "policydb")) {
1112 /* generic policy dfa - optional and may be NULL */
1113 info = "failed to unpack policydb";
1114--
d75b40d3 11152.14.1
daaa955e 1116
This page took 0.151628 seconds and 4 git commands to generate.