1 From 853cbdfb6924857a2ee2a1cd5b9fa494f8e7efa2 Mon Sep 17 00:00:00 2001
2 From: John Johansen <john.johansen@canonical.com>
3 Date: Tue, 18 Jul 2017 23:18:33 -0700
4 Subject: [PATCH 12/17] apparmor: add base infastructure for socket mediation
6 Provide a basic mediation of sockets. This is not a full net mediation
7 but just whether a spcific family of socket can be used by an
8 application, along with setting up some basic infrastructure for
9 network mediation to follow.
11 the user space rule hav the basic form of
12 NETWORK RULE = [ QUALIFIERS ] 'network' [ DOMAIN ]
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' ) ','
24 TYPE = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' |
27 PROTOCOL = ( 'tcp' | 'udp' | 'icmp' )
33 Signed-off-by: John Johansen <john.johansen@canonical.com>
34 Acked-by: Seth Arnold <seth.arnold@canonical.com>
35 (cherry picked from commit 56387cbe3f287034ee6959cb9e8f419889e38bd9)
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
53 diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
54 index 9cdec70d72b8..d5b291e94264 100644
55 --- a/security/apparmor/.gitignore
56 +++ b/security/apparmor/.gitignore
59 # Generated include files
64 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
65 index 81a34426d024..dafdd387d42b 100644
66 --- a/security/apparmor/Makefile
67 +++ b/security/apparmor/Makefile
68 @@ -4,11 +4,44 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
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
76 -clean-files := capability_names.h rlim_names.h
77 +clean-files := capability_names.h rlim_names.h net_names.h
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 */
87 +# and build the securityfs entries for the mapping.
88 +# Transforms lines from
89 +# #define AF_INET 2 /* Internet IP Protocol */
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';\
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/' >> $@
102 +# Build a lower case string table of sock type names
103 +# Transform lines from
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';\
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/' >> $@
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 \
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 \
126 $(call cmd,make-rlim)
127 +$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
128 + $(srctree)/include/linux/net.h \
130 + $(call cmd,make-af)
131 + $(call cmd,make-sock)
132 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
133 index 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),
144 diff --git a/security/apparmor/file.c b/security/apparmor/file.c
145 index 3382518b87fa..db80221891c6 100644
146 --- a/security/apparmor/file.c
147 +++ b/security/apparmor/file.c
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,
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)
164 + struct socket *sock = (struct socket *) file->private_data;
169 + /* revalidation due to label out of date. No revocation at this time */
170 + if (!denied && aa_label_is_subset(flabel, label))
173 + /* TODO: improve to skip profiles cached in flabel */
174 + error = aa_sock_file_perm(label, op, request, sock);
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));
181 + update_file_ctx(file_ctx(file), label, request);
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,
193 + else if (S_ISSOCK(file_inode(file)->i_mode))
194 + error = __file_sock_perm(op, label, flabel, file, request,
199 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
200 index 620e81169659..ff4316e1068d 100644
201 --- a/security/apparmor/include/audit.h
202 +++ b/security/apparmor/include/audit.h
203 @@ -121,23 +121,29 @@ struct apparmor_audit_data {
204 /* these entries require a custom callback fn */
206 struct aa_label *peer;
209 - const char *target;
217 + const char *target;
220 + int type, protocol;
221 + struct sock *peer_sk;
233 struct aa_profile *profile;
242 const char *src_name;
244 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
246 index 000000000000..140c8efcf364
248 +++ b/security/apparmor/include/net.h
251 + * AppArmor security module
253 + * This file contains AppArmor network mediation definitions.
255 + * Copyright (C) 1998-2008 Novell/SUSE
256 + * Copyright 2009-2017 Canonical Ltd.
258 + * This program is free software; you can redistribute it and/or
259 + * modify it under the terms of the GNU General Public License as
260 + * published by the Free Software Foundation, version 2 of the
267 +#include <net/sock.h>
268 +#include <linux/path.h>
270 +#include "apparmorfs.h"
275 +#define AA_MAY_SEND AA_MAY_WRITE
276 +#define AA_MAY_RECEIVE AA_MAY_READ
278 +#define AA_MAY_SHUTDOWN AA_MAY_DELETE
280 +#define AA_MAY_CONNECT AA_MAY_OPEN
281 +#define AA_MAY_ACCEPT 0x00100000
283 +#define AA_MAY_BIND 0x00200000
284 +#define AA_MAY_LISTEN 0x00400000
286 +#define AA_MAY_SETOPT 0x01000000
287 +#define AA_MAY_GETOPT 0x02000000
289 +#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
290 + AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN | \
291 + AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
292 + AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)
294 +#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
295 + AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
296 + AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD | \
297 + AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK | \
300 +#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
303 + struct aa_label *label;
304 + struct aa_label *peer;
308 +#define SK_CTX(X) ((X)->sk_security)
309 +#define SOCK_ctx(X) SOCK_INODE(X)->i_security
310 +#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \
311 + struct lsm_network_audit NAME ## _net = { .sk = (SK), \
313 + DEFINE_AUDIT_DATA(NAME, \
314 + ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \
315 + LSM_AUDIT_DATA_NONE, \
317 + NAME.u.net = &(NAME ## _net); \
318 + aad(&NAME)->net.type = (T); \
319 + aad(&NAME)->net.protocol = (P)
321 +#define DEFINE_AUDIT_SK(NAME, OP, SK) \
322 + DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \
325 +/* struct aa_net - network confinement data
326 + * @allow: basic network families permissions
327 + * @audit: which network permissions to force audit
328 + * @quiet: which network permissions to quiet rejects
337 +extern struct aa_sfs_entry aa_sfs_entry_network[];
339 +void audit_net_cb(struct audit_buffer *ab, void *va);
340 +int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
341 + u32 request, u16 family, int type);
342 +int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
343 + int type, int protocol);
344 +static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
345 + struct common_audit_data *sa,
349 + return aa_profile_af_perm(profile, sa, request, sk->sk_family,
352 +int aa_sk_perm(const char *op, u32 request, struct sock *sk);
354 +int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
355 + struct socket *sock);
358 +static inline void aa_free_net_rules(struct aa_net *new)
363 +#endif /* __AA_NET_H */
364 diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h
365 index 2b27bb79aec4..af04d5a7d73d 100644
366 --- a/security/apparmor/include/perms.h
367 +++ b/security/apparmor/include/perms.h
368 @@ -135,9 +135,10 @@ extern struct aa_perms allperms;
371 void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
372 -void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
373 +void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
375 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
376 - u32 chrsmask, const char **names, u32 namesmask);
377 + u32 chrsmask, const char * const *names, u32 namesmask);
378 void aa_apply_modes_to_perms(struct aa_profile *profile,
379 struct aa_perms *perms);
380 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
381 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
382 index 17fe41a9cac3..4364088a0b9e 100644
383 --- a/security/apparmor/include/policy.h
384 +++ b/security/apparmor/include/policy.h
391 #include "resource.h"
393 @@ -111,6 +112,7 @@ struct aa_data {
394 * @policy: general match rules governing policy
395 * @file: The set of rules governing basic file access and domain transitions
396 * @caps: capabilities for the profile
397 + * @net: network controls for the profile
398 * @rlimits: rlimits for the profile
400 * @dents: dentries for the profiles file entries in apparmorfs
401 @@ -148,6 +150,7 @@ struct aa_profile {
402 struct aa_policydb policy;
403 struct aa_file_rules file;
406 struct aa_rlimit rlimits;
408 struct aa_loaddata *rawdata;
409 @@ -220,6 +223,16 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
413 +static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
415 + unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
416 + u16 be_af = cpu_to_be16(AF);
420 + return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
424 * aa_get_profile - increment refcount on profile @p
425 * @p: profile (MAYBE NULL)
426 diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
427 index 08ca26bcca77..8818621b5d95 100644
428 --- a/security/apparmor/lib.c
429 +++ b/security/apparmor/lib.c
430 @@ -211,7 +211,8 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
434 -void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
435 +void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
438 const char *fmt = "%s";
439 unsigned int i, perm = 1;
440 @@ -229,7 +230,7 @@ void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
443 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
444 - u32 chrsmask, const char **names, u32 namesmask)
445 + u32 chrsmask, const char * const *names, u32 namesmask)
449 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
450 index 4ad0b3a45142..cc5ab23a2d84 100644
451 --- a/security/apparmor/lsm.c
452 +++ b/security/apparmor/lsm.c
454 #include "include/context.h"
455 #include "include/file.h"
456 #include "include/ipc.h"
457 +#include "include/net.h"
458 #include "include/path.h"
459 #include "include/label.h"
460 #include "include/policy.h"
461 @@ -736,6 +737,368 @@ static int apparmor_task_kill(struct task_struct *target, struct siginfo *info,
466 + * apparmor_sk_alloc_security - allocate and attach the sk_security field
468 +static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
470 + struct aa_sk_ctx *ctx;
472 + ctx = kzalloc(sizeof(*ctx), flags);
482 + * apparmor_sk_free_security - free the sk_security field
484 +static void apparmor_sk_free_security(struct sock *sk)
486 + struct aa_sk_ctx *ctx = SK_CTX(sk);
489 + aa_put_label(ctx->label);
490 + aa_put_label(ctx->peer);
491 + path_put(&ctx->path);
496 + * apparmor_clone_security - clone the sk_security field
498 +static void apparmor_sk_clone_security(const struct sock *sk,
499 + struct sock *newsk)
501 + struct aa_sk_ctx *ctx = SK_CTX(sk);
502 + struct aa_sk_ctx *new = SK_CTX(newsk);
504 + new->label = aa_get_label(ctx->label);
505 + new->peer = aa_get_label(ctx->peer);
506 + new->path = ctx->path;
507 + path_get(&new->path);
510 +static int aa_sock_create_perm(struct aa_label *label, int family, int type,
514 + AA_BUG(in_interrupt());
516 + return aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, family, type,
522 + * apparmor_socket_create - check perms before creating a new socket
524 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
526 + struct aa_label *label;
529 + label = begin_current_label_crit_section();
530 + if (!(kern || unconfined(label)))
531 + error = aa_sock_create_perm(label, family, type, protocol);
532 + end_current_label_crit_section(label);
538 + * apparmor_socket_post_create - setup the per-socket security struct
541 + * - kernel sockets currently labeled unconfined but we may want to
542 + * move to a special kernel label
543 + * - socket may not have sk here if created with sock_create_lite or
544 + * sock_alloc. These should be accept cases which will be handled in
547 +static int apparmor_socket_post_create(struct socket *sock, int family,
548 + int type, int protocol, int kern)
550 + struct aa_label *label;
553 + struct aa_ns *ns = aa_get_current_ns();
555 + label = aa_get_label(ns_unconfined(ns));
558 + label = aa_get_current_label();
561 + struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
563 + aa_put_label(ctx->label);
564 + ctx->label = aa_get_label(label);
566 + aa_put_label(label);
572 + * apparmor_socket_bind - check perms before bind addr to socket
574 +static int apparmor_socket_bind(struct socket *sock,
575 + struct sockaddr *address, int addrlen)
580 + AA_BUG(in_interrupt());
582 + return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk);
586 + * apparmor_socket_connect - check perms before connecting @sock to @address
588 +static int apparmor_socket_connect(struct socket *sock,
589 + struct sockaddr *address, int addrlen)
594 + AA_BUG(in_interrupt());
596 + return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk);
600 + * apparmor_socket_list - check perms before allowing listen
602 +static int apparmor_socket_listen(struct socket *sock, int backlog)
606 + AA_BUG(in_interrupt());
608 + return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk);
612 + * apparmor_socket_accept - check perms before accepting a new connection.
614 + * Note: while @newsock is created and has some information, the accept
615 + * has not been done.
617 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
622 + AA_BUG(in_interrupt());
624 + return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk);
627 +static int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock,
628 + struct msghdr *msg, int size)
633 + AA_BUG(in_interrupt());
635 + return aa_sk_perm(op, request, sock->sk);
639 + * apparmor_socket_sendmsg - check perms before sending msg to another socket
641 +static int apparmor_socket_sendmsg(struct socket *sock,
642 + struct msghdr *msg, int size)
644 + return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size);
648 + * apparmor_socket_recvmsg - check perms before receiving a message
650 +static int apparmor_socket_recvmsg(struct socket *sock,
651 + struct msghdr *msg, int size, int flags)
653 + return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size);
656 +/* revaliation, get/set attr, shutdown */
657 +static int aa_sock_perm(const char *op, u32 request, struct socket *sock)
661 + AA_BUG(in_interrupt());
663 + return aa_sk_perm(op, request, sock->sk);
667 + * apparmor_socket_getsockname - check perms before getting the local address
669 +static int apparmor_socket_getsockname(struct socket *sock)
671 + return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock);
675 + * apparmor_socket_getpeername - check perms before getting remote address
677 +static int apparmor_socket_getpeername(struct socket *sock)
679 + return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock);
682 +/* revaliation, get/set attr, opt */
683 +static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock,
684 + int level, int optname)
688 + AA_BUG(in_interrupt());
690 + return aa_sk_perm(op, request, sock->sk);
694 + * apparmor_getsockopt - check perms before getting socket options
696 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
699 + return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock,
704 + * apparmor_setsockopt - check perms before setting socket options
706 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
709 + return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock,
714 + * apparmor_socket_shutdown - check perms before shutting down @sock conn
716 +static int apparmor_socket_shutdown(struct socket *sock, int how)
718 + return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock);
722 + * apparmor_socket_sock_recv_skb - check perms before associating skb to sk
724 + * Note: can not sleep may be called with locks held
726 + * dont want protocol specific in __skb_recv_datagram()
727 + * to deny an incoming connection socket_sock_rcv_skb()
729 +static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
735 +static struct aa_label *sk_peer_label(struct sock *sk)
737 + struct aa_sk_ctx *ctx = SK_CTX(sk);
742 + return ERR_PTR(-ENOPROTOOPT);
746 + * apparmor_socket_getpeersec_stream - get security context of peer
748 + * Note: for tcp only valid if using ipsec or cipso on lan
750 +static int apparmor_socket_getpeersec_stream(struct socket *sock,
751 + char __user *optval,
752 + int __user *optlen,
756 + int slen, error = 0;
757 + struct aa_label *label;
758 + struct aa_label *peer;
760 + label = begin_current_label_crit_section();
761 + peer = sk_peer_label(sock->sk);
762 + if (IS_ERR(peer)) {
763 + error = PTR_ERR(peer);
766 + slen = aa_label_asxprint(&name, labels_ns(label), peer,
767 + FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
768 + FLAG_HIDDEN_UNCONFINED, GFP_KERNEL);
769 + /* don't include terminating \0 in slen, it breaks some apps */
775 + } else if (copy_to_user(optval, name, slen)) {
779 + if (put_user(slen, optlen))
787 + end_current_label_crit_section(label);
793 + * apparmor_socket_getpeersec_dgram - get security label of packet
794 + * @sock: the peer socket
795 + * @skb: packet data
796 + * @secid: pointer to where to put the secid of the packet
798 + * Sets the netlabel socket state on sk from parent
800 +static int apparmor_socket_getpeersec_dgram(struct socket *sock,
801 + struct sk_buff *skb, u32 *secid)
804 + /* TODO: requires secid support */
805 + return -ENOPROTOOPT;
809 + * apparmor_sock_graft - Initialize newly created socket
811 + * @parent: parent socket
813 + * Note: could set off of SOCK_CTX(parent) but need to track inode and we can
814 + * just set sk security information off of current creating process label
815 + * Labeling of sk for accept case - probably should be sock based
816 + * instead of task, because of the case where an implicitly labeled
817 + * socket is shared by different tasks.
819 +static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
821 + struct aa_sk_ctx *ctx = SK_CTX(sk);
824 + ctx->label = aa_get_current_label();
827 static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
828 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
829 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
830 @@ -770,6 +1133,30 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
831 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
832 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
834 + LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
835 + LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
836 + LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
838 + LSM_HOOK_INIT(socket_create, apparmor_socket_create),
839 + LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create),
840 + LSM_HOOK_INIT(socket_bind, apparmor_socket_bind),
841 + LSM_HOOK_INIT(socket_connect, apparmor_socket_connect),
842 + LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
843 + LSM_HOOK_INIT(socket_accept, apparmor_socket_accept),
844 + LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg),
845 + LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg),
846 + LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname),
847 + LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername),
848 + LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt),
849 + LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt),
850 + LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown),
851 + LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb),
852 + LSM_HOOK_INIT(socket_getpeersec_stream,
853 + apparmor_socket_getpeersec_stream),
854 + LSM_HOOK_INIT(socket_getpeersec_dgram,
855 + apparmor_socket_getpeersec_dgram),
856 + LSM_HOOK_INIT(sock_graft, apparmor_sock_graft),
858 LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
859 LSM_HOOK_INIT(cred_free, apparmor_cred_free),
860 LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
861 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
863 index 000000000000..33d54435f8d6
865 +++ b/security/apparmor/net.c
868 + * AppArmor security module
870 + * This file contains AppArmor network mediation
872 + * Copyright (C) 1998-2008 Novell/SUSE
873 + * Copyright 2009-2017 Canonical Ltd.
875 + * This program is free software; you can redistribute it and/or
876 + * modify it under the terms of the GNU General Public License as
877 + * published by the Free Software Foundation, version 2 of the
881 +#include "include/apparmor.h"
882 +#include "include/audit.h"
883 +#include "include/context.h"
884 +#include "include/label.h"
885 +#include "include/net.h"
886 +#include "include/policy.h"
888 +#include "net_names.h"
891 +struct aa_sfs_entry aa_sfs_entry_network[] = {
892 + AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),
896 +static const char * const net_mask_names[] = {
939 +/* audit callback for net specific fields */
940 +void audit_net_cb(struct audit_buffer *ab, void *va)
942 + struct common_audit_data *sa = va;
944 + audit_log_format(ab, " family=");
945 + if (address_family_names[sa->u.net->family])
946 + audit_log_string(ab, address_family_names[sa->u.net->family]);
948 + audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
949 + audit_log_format(ab, " sock_type=");
950 + if (sock_type_names[aad(sa)->net.type])
951 + audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
953 + audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
954 + audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
956 + if (aad(sa)->request & NET_PERMS_MASK) {
957 + audit_log_format(ab, " requested_mask=");
958 + aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
959 + net_mask_names, NET_PERMS_MASK);
961 + if (aad(sa)->denied & NET_PERMS_MASK) {
962 + audit_log_format(ab, " denied_mask=");
963 + aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
964 + net_mask_names, NET_PERMS_MASK);
967 + if (aad(sa)->peer) {
968 + audit_log_format(ab, " peer=");
969 + aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
970 + FLAGS_NONE, GFP_ATOMIC);
975 +/* Generic af perm */
976 +int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
977 + u32 request, u16 family, int type)
979 + struct aa_perms perms = { };
981 + AA_BUG(family >= AF_MAX);
982 + AA_BUG(type < 0 || type >= SOCK_MAX);
984 + if (profile_unconfined(profile))
987 + perms.allow = (profile->net.allow[family] & (1 << type)) ?
988 + ALL_PERMS_MASK : 0;
989 + perms.audit = (profile->net.audit[family] & (1 << type)) ?
990 + ALL_PERMS_MASK : 0;
991 + perms.quiet = (profile->net.quiet[family] & (1 << type)) ?
992 + ALL_PERMS_MASK : 0;
993 + aa_apply_modes_to_perms(profile, &perms);
995 + return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
998 +int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
999 + int type, int protocol)
1001 + struct aa_profile *profile;
1002 + DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
1004 + return fn_for_each_confined(label, profile,
1005 + aa_profile_af_perm(profile, &sa, request, family,
1009 +static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
1012 + struct aa_profile *profile;
1013 + DEFINE_AUDIT_SK(sa, op, sk);
1018 + if (unconfined(label))
1021 + return fn_for_each_confined(label, profile,
1022 + aa_profile_af_sk_perm(profile, &sa, request, sk));
1025 +int aa_sk_perm(const char *op, u32 request, struct sock *sk)
1027 + struct aa_label *label;
1031 + AA_BUG(in_interrupt());
1033 + /* TODO: switch to begin_current_label ???? */
1034 + label = begin_current_label_crit_section();
1035 + error = aa_label_sk_perm(label, op, request, sk);
1036 + end_current_label_crit_section(label);
1042 +int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
1043 + struct socket *sock)
1047 + AA_BUG(!sock->sk);
1049 + return aa_label_sk_perm(label, op, request, sock->sk);
1051 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
1052 index 4ede87c30f8b..5a2aec358322 100644
1053 --- a/security/apparmor/policy_unpack.c
1054 +++ b/security/apparmor/policy_unpack.c
1055 @@ -275,6 +275,19 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
1059 +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
1061 + if (unpack_nameX(e, AA_U16, name)) {
1062 + if (!inbounds(e, sizeof(u16)))
1065 + *data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
1066 + e->pos += sizeof(u16);
1072 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
1074 if (unpack_nameX(e, AA_U32, name)) {
1075 @@ -584,7 +597,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
1076 struct aa_profile *profile = NULL;
1077 const char *tmpname, *tmpns = NULL, *name = NULL;
1078 const char *info = "failed to unpack profile";
1080 + size_t size = 0, ns_len;
1081 struct rhashtable_params params = { 0 };
1083 struct aa_data *data;
1084 @@ -717,6 +730,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
1088 + size = unpack_array(e, "net_allowed_af");
1091 + for (i = 0; i < size; i++) {
1092 + /* discard extraneous rules that this kernel will
1095 + if (i >= AF_MAX) {
1098 + if (!unpack_u16(e, &tmp, NULL) ||
1099 + !unpack_u16(e, &tmp, NULL) ||
1100 + !unpack_u16(e, &tmp, NULL))
1104 + if (!unpack_u16(e, &profile->net.allow[i], NULL))
1106 + if (!unpack_u16(e, &profile->net.audit[i], NULL))
1108 + if (!unpack_u16(e, &profile->net.quiet[i], NULL))
1111 + if (!unpack_nameX(e, AA_ARRAYEND, NULL))
1114 + if (VERSION_LT(e->version, v7)) {
1115 + /* pre v7 policy always allowed these */
1116 + profile->net.allow[AF_UNIX] = 0xffff;
1117 + profile->net.allow[AF_NETLINK] = 0xffff;
1120 if (unpack_nameX(e, AA_STRUCT, "policydb")) {
1121 /* generic policy dfa - optional and may be NULL */
1122 info = "failed to unpack policydb";