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