The AppArmor source code distributes out-of-tree kernel patches that
are needed in order to support the full functionality of AppArmor.
So, import those kernel patches from the latest available version of
AppArmor, i.e., v2.13.
Change-Id: I7bee0aece63b980a2cb36b053a9d8f28d934a993
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/5378
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Sharath George
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,607 @@ |
| 0 |
+From 20f953a08580786932c6b2c214c7dc2e2f99cf75 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: John Johansen <john.johansen@canonical.com> |
|
| 2 |
+Date: Mon, 4 Oct 2010 15:03:36 -0700 |
|
| 3 |
+Subject: [PATCH 1/3] UBUNTU: SAUCE: AppArmor: basic networking rules |
|
| 4 |
+ |
|
| 5 |
+[ This is an out-of-tree patch distributed with the AppArmor source |
|
| 6 |
+ code (v2.13) ] |
|
| 7 |
+ |
|
| 8 |
+Base support for network mediation. |
|
| 9 |
+ |
|
| 10 |
+Signed-off-by: John Johansen <john.johansen@canonical.com> |
|
| 11 |
+Signed-off-by: Srivatsa S. Bhat <srivatsa@csail.mit.edu> |
|
| 12 |
+--- |
|
| 13 |
+ security/apparmor/.gitignore | 1 + |
|
| 14 |
+ security/apparmor/Makefile | 42 +++++++++- |
|
| 15 |
+ security/apparmor/apparmorfs.c | 1 + |
|
| 16 |
+ security/apparmor/include/audit.h | 4 + |
|
| 17 |
+ security/apparmor/include/net.h | 44 ++++++++++ |
|
| 18 |
+ security/apparmor/include/policy.h | 3 + |
|
| 19 |
+ security/apparmor/lsm.c | 112 +++++++++++++++++++++++++ |
|
| 20 |
+ security/apparmor/net.c | 162 +++++++++++++++++++++++++++++++++++++ |
|
| 21 |
+ security/apparmor/policy.c | 1 + |
|
| 22 |
+ security/apparmor/policy_unpack.c | 46 +++++++++++ |
|
| 23 |
+ 10 files changed, 414 insertions(+), 2 deletions(-) |
|
| 24 |
+ create mode 100644 security/apparmor/include/net.h |
|
| 25 |
+ create mode 100644 security/apparmor/net.c |
|
| 26 |
+ |
|
| 27 |
+diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore |
|
| 28 |
+index 9cdec70..d5b291e 100644 |
|
| 29 |
+--- a/security/apparmor/.gitignore |
|
| 30 |
+@@ -1,5 +1,6 @@ |
|
| 31 |
+ # |
|
| 32 |
+ # Generated include files |
|
| 33 |
+ # |
|
| 34 |
++net_names.h |
|
| 35 |
+ capability_names.h |
|
| 36 |
+ rlim_names.h |
|
| 37 |
+diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile |
|
| 38 |
+index d693df8..5dbb72f 100644 |
|
| 39 |
+--- a/security/apparmor/Makefile |
|
| 40 |
+@@ -4,10 +4,10 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o |
|
| 41 |
+ |
|
| 42 |
+ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ |
|
| 43 |
+ path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ |
|
| 44 |
+- resource.o sid.o file.o |
|
| 45 |
++ resource.o sid.o file.o net.o |
|
| 46 |
+ apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o |
|
| 47 |
+ |
|
| 48 |
+-clean-files := capability_names.h rlim_names.h |
|
| 49 |
++clean-files := capability_names.h rlim_names.h net_names.h |
|
| 50 |
+ |
|
| 51 |
+ |
|
| 52 |
+ # Build a lower case string table of capability names |
|
| 53 |
+@@ -25,6 +25,38 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
|
|
| 54 |
+ -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \ |
|
| 55 |
+ tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ |
|
| 56 |
+ |
|
| 57 |
++# Build a lower case string table of address family names |
|
| 58 |
++# Transform lines from |
|
| 59 |
++# define AF_LOCAL 1 /* POSIX name for AF_UNIX */ |
|
| 60 |
++# #define AF_INET 2 /* Internet IP Protocol */ |
|
| 61 |
++# to |
|
| 62 |
++# [1] = "local", |
|
| 63 |
++# [2] = "inet", |
|
| 64 |
++# |
|
| 65 |
++# and build the securityfs entries for the mapping. |
|
| 66 |
++# Transforms lines from |
|
| 67 |
++# #define AF_INET 2 /* Internet IP Protocol */ |
|
| 68 |
++# to |
|
| 69 |
++# #define AA_FS_AF_MASK "local inet" |
|
| 70 |
++quiet_cmd_make-af = GEN $@ |
|
| 71 |
++cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
|
|
| 72 |
++ sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \ |
|
| 73 |
++ 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\ |
|
| 74 |
++ echo "};" >> $@ ;\ |
|
| 75 |
++ echo -n '\#define AA_FS_AF_MASK "' >> $@ ;\ |
|
| 76 |
++ sed -r -n 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\ |
|
| 77 |
++ $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ |
|
| 78 |
++ |
|
| 79 |
++# Build a lower case string table of sock type names |
|
| 80 |
++# Transform lines from |
|
| 81 |
++# SOCK_STREAM = 1, |
|
| 82 |
++# to |
|
| 83 |
++# [1] = "stream", |
|
| 84 |
++quiet_cmd_make-sock = GEN $@ |
|
| 85 |
++cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
|
|
| 86 |
++ sed $^ >>$@ -r -n \ |
|
| 87 |
++ -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\ |
|
| 88 |
++ echo "};" >> $@ |
|
| 89 |
+ |
|
| 90 |
+ # Build a lower case string table of rlimit names. |
|
| 91 |
+ # Transforms lines from |
|
| 92 |
+@@ -61,6 +93,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
|
|
| 93 |
+ tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ |
|
| 94 |
+ |
|
| 95 |
+ $(obj)/capability.o : $(obj)/capability_names.h |
|
| 96 |
++$(obj)/net.o : $(obj)/net_names.h |
|
| 97 |
+ $(obj)/resource.o : $(obj)/rlim_names.h |
|
| 98 |
+ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ |
|
| 99 |
+ $(src)/Makefile |
|
| 100 |
+@@ -68,3 +101,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ |
|
| 101 |
+ $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \ |
|
| 102 |
+ $(src)/Makefile |
|
| 103 |
+ $(call cmd,make-rlim) |
|
| 104 |
++$(obj)/net_names.h : $(srctree)/include/linux/socket.h \ |
|
| 105 |
++ $(srctree)/include/linux/net.h \ |
|
| 106 |
++ $(src)/Makefile |
|
| 107 |
++ $(call cmd,make-af) |
|
| 108 |
++ $(call cmd,make-sock) |
|
| 109 |
+diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c |
|
| 110 |
+index 5923d56..bd558db 100644 |
|
| 111 |
+--- a/security/apparmor/apparmorfs.c |
|
| 112 |
+@@ -807,6 +807,7 @@ static struct aa_fs_entry aa_fs_entry_features[] = {
|
|
| 113 |
+ AA_FS_DIR("policy", aa_fs_entry_policy),
|
|
| 114 |
+ AA_FS_DIR("domain", aa_fs_entry_domain),
|
|
| 115 |
+ AA_FS_DIR("file", aa_fs_entry_file),
|
|
| 116 |
++ AA_FS_DIR("network", aa_fs_entry_network),
|
|
| 117 |
+ AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
|
|
| 118 |
+ AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
|
|
| 119 |
+ AA_FS_DIR("caps", aa_fs_entry_caps),
|
|
| 120 |
+diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h |
|
| 121 |
+index ba3dfd1..5d3c419 100644 |
|
| 122 |
+--- a/security/apparmor/include/audit.h |
|
| 123 |
+@@ -125,6 +125,10 @@ struct apparmor_audit_data {
|
|
| 124 |
+ u32 denied; |
|
| 125 |
+ kuid_t ouid; |
|
| 126 |
+ } fs; |
|
| 127 |
++ struct {
|
|
| 128 |
++ int type, protocol; |
|
| 129 |
++ struct sock *sk; |
|
| 130 |
++ } net; |
|
| 131 |
+ }; |
|
| 132 |
+ }; |
|
| 133 |
+ |
|
| 134 |
+diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h |
|
| 135 |
+new file mode 100644 |
|
| 136 |
+index 0000000..cb8a121 |
|
| 137 |
+--- /dev/null |
|
| 138 |
+@@ -0,0 +1,44 @@ |
|
| 139 |
++/* |
|
| 140 |
++ * AppArmor security module |
|
| 141 |
++ * |
|
| 142 |
++ * This file contains AppArmor network mediation definitions. |
|
| 143 |
++ * |
|
| 144 |
++ * Copyright (C) 1998-2008 Novell/SUSE |
|
| 145 |
++ * Copyright 2009-2012 Canonical Ltd. |
|
| 146 |
++ * |
|
| 147 |
++ * This program is free software; you can redistribute it and/or |
|
| 148 |
++ * modify it under the terms of the GNU General Public License as |
|
| 149 |
++ * published by the Free Software Foundation, version 2 of the |
|
| 150 |
++ * License. |
|
| 151 |
++ */ |
|
| 152 |
++ |
|
| 153 |
++#ifndef __AA_NET_H |
|
| 154 |
++#define __AA_NET_H |
|
| 155 |
++ |
|
| 156 |
++#include <net/sock.h> |
|
| 157 |
++ |
|
| 158 |
++#include "apparmorfs.h" |
|
| 159 |
++ |
|
| 160 |
++/* struct aa_net - network confinement data |
|
| 161 |
++ * @allowed: basic network families permissions |
|
| 162 |
++ * @audit_network: which network permissions to force audit |
|
| 163 |
++ * @quiet_network: which network permissions to quiet rejects |
|
| 164 |
++ */ |
|
| 165 |
++struct aa_net {
|
|
| 166 |
++ u16 allow[AF_MAX]; |
|
| 167 |
++ u16 audit[AF_MAX]; |
|
| 168 |
++ u16 quiet[AF_MAX]; |
|
| 169 |
++}; |
|
| 170 |
++ |
|
| 171 |
++extern struct aa_fs_entry aa_fs_entry_network[]; |
|
| 172 |
++ |
|
| 173 |
++extern int aa_net_perm(int op, struct aa_profile *profile, u16 family, |
|
| 174 |
++ int type, int protocol, struct sock *sk); |
|
| 175 |
++extern int aa_revalidate_sk(int op, struct sock *sk); |
|
| 176 |
++ |
|
| 177 |
++static inline void aa_free_net_rules(struct aa_net *new) |
|
| 178 |
++{
|
|
| 179 |
++ /* NOP */ |
|
| 180 |
++} |
|
| 181 |
++ |
|
| 182 |
++#endif /* __AA_NET_H */ |
|
| 183 |
+diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h |
|
| 184 |
+index 52275f0..4fc4dac 100644 |
|
| 185 |
+--- a/security/apparmor/include/policy.h |
|
| 186 |
+@@ -27,6 +27,7 @@ |
|
| 187 |
+ #include "capability.h" |
|
| 188 |
+ #include "domain.h" |
|
| 189 |
+ #include "file.h" |
|
| 190 |
++#include "net.h" |
|
| 191 |
+ #include "resource.h" |
|
| 192 |
+ |
|
| 193 |
+ extern const char *const aa_profile_mode_names[]; |
|
| 194 |
+@@ -176,6 +177,7 @@ struct aa_replacedby {
|
|
| 195 |
+ * @policy: general match rules governing policy |
|
| 196 |
+ * @file: The set of rules governing basic file access and domain transitions |
|
| 197 |
+ * @caps: capabilities for the profile |
|
| 198 |
++ * @net: network controls for the profile |
|
| 199 |
+ * @rlimits: rlimits for the profile |
|
| 200 |
+ * |
|
| 201 |
+ * @dents: dentries for the profiles file entries in apparmorfs |
|
| 202 |
+@@ -217,6 +219,7 @@ struct aa_profile {
|
|
| 203 |
+ struct aa_policydb policy; |
|
| 204 |
+ struct aa_file_rules file; |
|
| 205 |
+ struct aa_caps caps; |
|
| 206 |
++ struct aa_net net; |
|
| 207 |
+ struct aa_rlimit rlimits; |
|
| 208 |
+ |
|
| 209 |
+ unsigned char *hash; |
|
| 210 |
+diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c |
|
| 211 |
+index 02cc952..de3b68a 100644 |
|
| 212 |
+--- a/security/apparmor/lsm.c |
|
| 213 |
+@@ -32,6 +32,7 @@ |
|
| 214 |
+ #include "include/context.h" |
|
| 215 |
+ #include "include/file.h" |
|
| 216 |
+ #include "include/ipc.h" |
|
| 217 |
++#include "include/net.h" |
|
| 218 |
+ #include "include/path.h" |
|
| 219 |
+ #include "include/policy.h" |
|
| 220 |
+ #include "include/procattr.h" |
|
| 221 |
+@@ -584,6 +585,104 @@ static int apparmor_task_setrlimit(struct task_struct *task, |
|
| 222 |
+ return error; |
|
| 223 |
+ } |
|
| 224 |
+ |
|
| 225 |
++static int apparmor_socket_create(int family, int type, int protocol, int kern) |
|
| 226 |
++{
|
|
| 227 |
++ struct aa_profile *profile; |
|
| 228 |
++ int error = 0; |
|
| 229 |
++ |
|
| 230 |
++ if (kern) |
|
| 231 |
++ return 0; |
|
| 232 |
++ |
|
| 233 |
++ profile = __aa_current_profile(); |
|
| 234 |
++ if (!unconfined(profile)) |
|
| 235 |
++ error = aa_net_perm(OP_CREATE, profile, family, type, protocol, |
|
| 236 |
++ NULL); |
|
| 237 |
++ return error; |
|
| 238 |
++} |
|
| 239 |
++ |
|
| 240 |
++static int apparmor_socket_bind(struct socket *sock, |
|
| 241 |
++ struct sockaddr *address, int addrlen) |
|
| 242 |
++{
|
|
| 243 |
++ struct sock *sk = sock->sk; |
|
| 244 |
++ |
|
| 245 |
++ return aa_revalidate_sk(OP_BIND, sk); |
|
| 246 |
++} |
|
| 247 |
++ |
|
| 248 |
++static int apparmor_socket_connect(struct socket *sock, |
|
| 249 |
++ struct sockaddr *address, int addrlen) |
|
| 250 |
++{
|
|
| 251 |
++ struct sock *sk = sock->sk; |
|
| 252 |
++ |
|
| 253 |
++ return aa_revalidate_sk(OP_CONNECT, sk); |
|
| 254 |
++} |
|
| 255 |
++ |
|
| 256 |
++static int apparmor_socket_listen(struct socket *sock, int backlog) |
|
| 257 |
++{
|
|
| 258 |
++ struct sock *sk = sock->sk; |
|
| 259 |
++ |
|
| 260 |
++ return aa_revalidate_sk(OP_LISTEN, sk); |
|
| 261 |
++} |
|
| 262 |
++ |
|
| 263 |
++static int apparmor_socket_accept(struct socket *sock, struct socket *newsock) |
|
| 264 |
++{
|
|
| 265 |
++ struct sock *sk = sock->sk; |
|
| 266 |
++ |
|
| 267 |
++ return aa_revalidate_sk(OP_ACCEPT, sk); |
|
| 268 |
++} |
|
| 269 |
++ |
|
| 270 |
++static int apparmor_socket_sendmsg(struct socket *sock, |
|
| 271 |
++ struct msghdr *msg, int size) |
|
| 272 |
++{
|
|
| 273 |
++ struct sock *sk = sock->sk; |
|
| 274 |
++ |
|
| 275 |
++ return aa_revalidate_sk(OP_SENDMSG, sk); |
|
| 276 |
++} |
|
| 277 |
++ |
|
| 278 |
++static int apparmor_socket_recvmsg(struct socket *sock, |
|
| 279 |
++ struct msghdr *msg, int size, int flags) |
|
| 280 |
++{
|
|
| 281 |
++ struct sock *sk = sock->sk; |
|
| 282 |
++ |
|
| 283 |
++ return aa_revalidate_sk(OP_RECVMSG, sk); |
|
| 284 |
++} |
|
| 285 |
++ |
|
| 286 |
++static int apparmor_socket_getsockname(struct socket *sock) |
|
| 287 |
++{
|
|
| 288 |
++ struct sock *sk = sock->sk; |
|
| 289 |
++ |
|
| 290 |
++ return aa_revalidate_sk(OP_GETSOCKNAME, sk); |
|
| 291 |
++} |
|
| 292 |
++ |
|
| 293 |
++static int apparmor_socket_getpeername(struct socket *sock) |
|
| 294 |
++{
|
|
| 295 |
++ struct sock *sk = sock->sk; |
|
| 296 |
++ |
|
| 297 |
++ return aa_revalidate_sk(OP_GETPEERNAME, sk); |
|
| 298 |
++} |
|
| 299 |
++ |
|
| 300 |
++static int apparmor_socket_getsockopt(struct socket *sock, int level, |
|
| 301 |
++ int optname) |
|
| 302 |
++{
|
|
| 303 |
++ struct sock *sk = sock->sk; |
|
| 304 |
++ |
|
| 305 |
++ return aa_revalidate_sk(OP_GETSOCKOPT, sk); |
|
| 306 |
++} |
|
| 307 |
++ |
|
| 308 |
++static int apparmor_socket_setsockopt(struct socket *sock, int level, |
|
| 309 |
++ int optname) |
|
| 310 |
++{
|
|
| 311 |
++ struct sock *sk = sock->sk; |
|
| 312 |
++ |
|
| 313 |
++ return aa_revalidate_sk(OP_SETSOCKOPT, sk); |
|
| 314 |
++} |
|
| 315 |
++ |
|
| 316 |
++static int apparmor_socket_shutdown(struct socket *sock, int how) |
|
| 317 |
++{
|
|
| 318 |
++ struct sock *sk = sock->sk; |
|
| 319 |
++ |
|
| 320 |
++ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk); |
|
| 321 |
++} |
|
| 322 |
++ |
|
| 323 |
+ static struct security_hook_list apparmor_hooks[] = {
|
|
| 324 |
+ LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), |
|
| 325 |
+ LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), |
|
| 326 |
+@@ -613,6 +712,19 @@ static struct security_hook_list apparmor_hooks[] = {
|
|
| 327 |
+ LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), |
|
| 328 |
+ LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), |
|
| 329 |
+ |
|
| 330 |
++ LSM_HOOK_INIT(socket_create, apparmor_socket_create), |
|
| 331 |
++ LSM_HOOK_INIT(socket_bind, apparmor_socket_bind), |
|
| 332 |
++ LSM_HOOK_INIT(socket_connect, apparmor_socket_connect), |
|
| 333 |
++ LSM_HOOK_INIT(socket_listen, apparmor_socket_listen), |
|
| 334 |
++ LSM_HOOK_INIT(socket_accept, apparmor_socket_accept), |
|
| 335 |
++ LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg), |
|
| 336 |
++ LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg), |
|
| 337 |
++ LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname), |
|
| 338 |
++ LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername), |
|
| 339 |
++ LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt), |
|
| 340 |
++ LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt), |
|
| 341 |
++ LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown), |
|
| 342 |
++ |
|
| 343 |
+ LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), |
|
| 344 |
+ LSM_HOOK_INIT(cred_free, apparmor_cred_free), |
|
| 345 |
+ LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare), |
|
| 346 |
+diff --git a/security/apparmor/net.c b/security/apparmor/net.c |
|
| 347 |
+new file mode 100644 |
|
| 348 |
+index 0000000..003dd18 |
|
| 349 |
+--- /dev/null |
|
| 350 |
+@@ -0,0 +1,162 @@ |
|
| 351 |
++/* |
|
| 352 |
++ * AppArmor security module |
|
| 353 |
++ * |
|
| 354 |
++ * This file contains AppArmor network mediation |
|
| 355 |
++ * |
|
| 356 |
++ * Copyright (C) 1998-2008 Novell/SUSE |
|
| 357 |
++ * Copyright 2009-2012 Canonical Ltd. |
|
| 358 |
++ * |
|
| 359 |
++ * This program is free software; you can redistribute it and/or |
|
| 360 |
++ * modify it under the terms of the GNU General Public License as |
|
| 361 |
++ * published by the Free Software Foundation, version 2 of the |
|
| 362 |
++ * License. |
|
| 363 |
++ */ |
|
| 364 |
++ |
|
| 365 |
++#include "include/apparmor.h" |
|
| 366 |
++#include "include/audit.h" |
|
| 367 |
++#include "include/context.h" |
|
| 368 |
++#include "include/net.h" |
|
| 369 |
++#include "include/policy.h" |
|
| 370 |
++ |
|
| 371 |
++#include "net_names.h" |
|
| 372 |
++ |
|
| 373 |
++struct aa_fs_entry aa_fs_entry_network[] = {
|
|
| 374 |
++ AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
|
|
| 375 |
++ { }
|
|
| 376 |
++}; |
|
| 377 |
++ |
|
| 378 |
++/* audit callback for net specific fields */ |
|
| 379 |
++static void audit_cb(struct audit_buffer *ab, void *va) |
|
| 380 |
++{
|
|
| 381 |
++ struct common_audit_data *sa = va; |
|
| 382 |
++ |
|
| 383 |
++ audit_log_format(ab, " family="); |
|
| 384 |
++ if (address_family_names[sa->u.net->family]) {
|
|
| 385 |
++ audit_log_string(ab, address_family_names[sa->u.net->family]); |
|
| 386 |
++ } else {
|
|
| 387 |
++ audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family); |
|
| 388 |
++ } |
|
| 389 |
++ audit_log_format(ab, " sock_type="); |
|
| 390 |
++ if (sock_type_names[sa->aad->net.type]) {
|
|
| 391 |
++ audit_log_string(ab, sock_type_names[sa->aad->net.type]); |
|
| 392 |
++ } else {
|
|
| 393 |
++ audit_log_format(ab, "\"unknown(%d)\"", sa->aad->net.type); |
|
| 394 |
++ } |
|
| 395 |
++ audit_log_format(ab, " protocol=%d", sa->aad->net.protocol); |
|
| 396 |
++} |
|
| 397 |
++ |
|
| 398 |
++/** |
|
| 399 |
++ * audit_net - audit network access |
|
| 400 |
++ * @profile: profile being enforced (NOT NULL) |
|
| 401 |
++ * @op: operation being checked |
|
| 402 |
++ * @family: network family |
|
| 403 |
++ * @type: network type |
|
| 404 |
++ * @protocol: network protocol |
|
| 405 |
++ * @sk: socket auditing is being applied to |
|
| 406 |
++ * @error: error code for failure else 0 |
|
| 407 |
++ * |
|
| 408 |
++ * Returns: %0 or sa->error else other errorcode on failure |
|
| 409 |
++ */ |
|
| 410 |
++static int audit_net(struct aa_profile *profile, int op, u16 family, int type, |
|
| 411 |
++ int protocol, struct sock *sk, int error) |
|
| 412 |
++{
|
|
| 413 |
++ int audit_type = AUDIT_APPARMOR_AUTO; |
|
| 414 |
++ struct common_audit_data sa; |
|
| 415 |
++ struct apparmor_audit_data aad = { };
|
|
| 416 |
++ struct lsm_network_audit net = { };
|
|
| 417 |
++ if (sk) {
|
|
| 418 |
++ sa.type = LSM_AUDIT_DATA_NET; |
|
| 419 |
++ } else {
|
|
| 420 |
++ sa.type = LSM_AUDIT_DATA_NONE; |
|
| 421 |
++ } |
|
| 422 |
++ /* todo fill in socket addr info */ |
|
| 423 |
++ sa.aad = &aad; |
|
| 424 |
++ sa.u.net = &net; |
|
| 425 |
++ sa.aad->op = op, |
|
| 426 |
++ sa.u.net->family = family; |
|
| 427 |
++ sa.u.net->sk = sk; |
|
| 428 |
++ sa.aad->net.type = type; |
|
| 429 |
++ sa.aad->net.protocol = protocol; |
|
| 430 |
++ sa.aad->error = error; |
|
| 431 |
++ |
|
| 432 |
++ if (likely(!sa.aad->error)) {
|
|
| 433 |
++ u16 audit_mask = profile->net.audit[sa.u.net->family]; |
|
| 434 |
++ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) && |
|
| 435 |
++ !(1 << sa.aad->net.type & audit_mask))) |
|
| 436 |
++ return 0; |
|
| 437 |
++ audit_type = AUDIT_APPARMOR_AUDIT; |
|
| 438 |
++ } else {
|
|
| 439 |
++ u16 quiet_mask = profile->net.quiet[sa.u.net->family]; |
|
| 440 |
++ u16 kill_mask = 0; |
|
| 441 |
++ u16 denied = (1 << sa.aad->net.type) & ~quiet_mask; |
|
| 442 |
++ |
|
| 443 |
++ if (denied & kill_mask) |
|
| 444 |
++ audit_type = AUDIT_APPARMOR_KILL; |
|
| 445 |
++ |
|
| 446 |
++ if ((denied & quiet_mask) && |
|
| 447 |
++ AUDIT_MODE(profile) != AUDIT_NOQUIET && |
|
| 448 |
++ AUDIT_MODE(profile) != AUDIT_ALL) |
|
| 449 |
++ return COMPLAIN_MODE(profile) ? 0 : sa.aad->error; |
|
| 450 |
++ } |
|
| 451 |
++ |
|
| 452 |
++ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb); |
|
| 453 |
++} |
|
| 454 |
++ |
|
| 455 |
++/** |
|
| 456 |
++ * aa_net_perm - very course network access check |
|
| 457 |
++ * @op: operation being checked |
|
| 458 |
++ * @profile: profile being enforced (NOT NULL) |
|
| 459 |
++ * @family: network family |
|
| 460 |
++ * @type: network type |
|
| 461 |
++ * @protocol: network protocol |
|
| 462 |
++ * |
|
| 463 |
++ * Returns: %0 else error if permission denied |
|
| 464 |
++ */ |
|
| 465 |
++int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type, |
|
| 466 |
++ int protocol, struct sock *sk) |
|
| 467 |
++{
|
|
| 468 |
++ u16 family_mask; |
|
| 469 |
++ int error; |
|
| 470 |
++ |
|
| 471 |
++ if ((family < 0) || (family >= AF_MAX)) |
|
| 472 |
++ return -EINVAL; |
|
| 473 |
++ |
|
| 474 |
++ if ((type < 0) || (type >= SOCK_MAX)) |
|
| 475 |
++ return -EINVAL; |
|
| 476 |
++ |
|
| 477 |
++ /* unix domain and netlink sockets are handled by ipc */ |
|
| 478 |
++ if (family == AF_UNIX || family == AF_NETLINK) |
|
| 479 |
++ return 0; |
|
| 480 |
++ |
|
| 481 |
++ family_mask = profile->net.allow[family]; |
|
| 482 |
++ |
|
| 483 |
++ error = (family_mask & (1 << type)) ? 0 : -EACCES; |
|
| 484 |
++ |
|
| 485 |
++ return audit_net(profile, op, family, type, protocol, sk, error); |
|
| 486 |
++} |
|
| 487 |
++ |
|
| 488 |
++/** |
|
| 489 |
++ * aa_revalidate_sk - Revalidate access to a sock |
|
| 490 |
++ * @op: operation being checked |
|
| 491 |
++ * @sk: sock being revalidated (NOT NULL) |
|
| 492 |
++ * |
|
| 493 |
++ * Returns: %0 else error if permission denied |
|
| 494 |
++ */ |
|
| 495 |
++int aa_revalidate_sk(int op, struct sock *sk) |
|
| 496 |
++{
|
|
| 497 |
++ struct aa_profile *profile; |
|
| 498 |
++ int error = 0; |
|
| 499 |
++ |
|
| 500 |
++ /* aa_revalidate_sk should not be called from interrupt context |
|
| 501 |
++ * don't mediate these calls as they are not task related |
|
| 502 |
++ */ |
|
| 503 |
++ if (in_interrupt()) |
|
| 504 |
++ return 0; |
|
| 505 |
++ |
|
| 506 |
++ profile = __aa_current_profile(); |
|
| 507 |
++ if (!unconfined(profile)) |
|
| 508 |
++ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type, |
|
| 509 |
++ sk->sk_protocol, sk); |
|
| 510 |
++ |
|
| 511 |
++ return error; |
|
| 512 |
++} |
|
| 513 |
+diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c |
|
| 514 |
+index 179e68d..f1a8541 100644 |
|
| 515 |
+--- a/security/apparmor/policy.c |
|
| 516 |
+@@ -603,6 +603,7 @@ void aa_free_profile(struct aa_profile *profile) |
|
| 517 |
+ |
|
| 518 |
+ aa_free_file_rules(&profile->file); |
|
| 519 |
+ aa_free_cap_rules(&profile->caps); |
|
| 520 |
++ aa_free_net_rules(&profile->net); |
|
| 521 |
+ aa_free_rlimit_rules(&profile->rlimits); |
|
| 522 |
+ |
|
| 523 |
+ kzfree(profile->dirname); |
|
| 524 |
+diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c |
|
| 525 |
+index 1381206..7dc15ff 100644 |
|
| 526 |
+--- a/security/apparmor/policy_unpack.c |
|
| 527 |
+@@ -193,6 +193,19 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) |
|
| 528 |
+ return 0; |
|
| 529 |
+ } |
|
| 530 |
+ |
|
| 531 |
++static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name) |
|
| 532 |
++{
|
|
| 533 |
++ if (unpack_nameX(e, AA_U16, name)) {
|
|
| 534 |
++ if (!inbounds(e, sizeof(u16))) |
|
| 535 |
++ return 0; |
|
| 536 |
++ if (data) |
|
| 537 |
++ *data = le16_to_cpu(get_unaligned((u16 *) e->pos)); |
|
| 538 |
++ e->pos += sizeof(u16); |
|
| 539 |
++ return 1; |
|
| 540 |
++ } |
|
| 541 |
++ return 0; |
|
| 542 |
++} |
|
| 543 |
++ |
|
| 544 |
+ static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) |
|
| 545 |
+ {
|
|
| 546 |
+ if (unpack_nameX(e, AA_U32, name)) {
|
|
| 547 |
+@@ -476,6 +489,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e) |
|
| 548 |
+ {
|
|
| 549 |
+ struct aa_profile *profile = NULL; |
|
| 550 |
+ const char *name = NULL; |
|
| 551 |
++ size_t size = 0; |
|
| 552 |
+ int i, error = -EPROTO; |
|
| 553 |
+ kernel_cap_t tmpcap; |
|
| 554 |
+ u32 tmp; |
|
| 555 |
+@@ -576,6 +590,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e) |
|
| 556 |
+ if (!unpack_rlimits(e, profile)) |
|
| 557 |
+ goto fail; |
|
| 558 |
+ |
|
| 559 |
++ size = unpack_array(e, "net_allowed_af"); |
|
| 560 |
++ if (size) {
|
|
| 561 |
++ |
|
| 562 |
++ for (i = 0; i < size; i++) {
|
|
| 563 |
++ /* discard extraneous rules that this kernel will |
|
| 564 |
++ * never request |
|
| 565 |
++ */ |
|
| 566 |
++ if (i >= AF_MAX) {
|
|
| 567 |
++ u16 tmp; |
|
| 568 |
++ if (!unpack_u16(e, &tmp, NULL) || |
|
| 569 |
++ !unpack_u16(e, &tmp, NULL) || |
|
| 570 |
++ !unpack_u16(e, &tmp, NULL)) |
|
| 571 |
++ goto fail; |
|
| 572 |
++ continue; |
|
| 573 |
++ } |
|
| 574 |
++ if (!unpack_u16(e, &profile->net.allow[i], NULL)) |
|
| 575 |
++ goto fail; |
|
| 576 |
++ if (!unpack_u16(e, &profile->net.audit[i], NULL)) |
|
| 577 |
++ goto fail; |
|
| 578 |
++ if (!unpack_u16(e, &profile->net.quiet[i], NULL)) |
|
| 579 |
++ goto fail; |
|
| 580 |
++ } |
|
| 581 |
++ if (!unpack_nameX(e, AA_ARRAYEND, NULL)) |
|
| 582 |
++ goto fail; |
|
| 583 |
++ } |
|
| 584 |
++ /* |
|
| 585 |
++ * allow unix domain and netlink sockets they are handled |
|
| 586 |
++ * by IPC |
|
| 587 |
++ */ |
|
| 588 |
++ profile->net.allow[AF_UNIX] = 0xffff; |
|
| 589 |
++ profile->net.allow[AF_NETLINK] = 0xffff; |
|
| 590 |
++ |
|
| 591 |
+ if (unpack_nameX(e, AA_STRUCT, "policydb")) {
|
|
| 592 |
+ /* generic policy dfa - optional and may be NULL */ |
|
| 593 |
+ profile->policy.dfa = unpack_dfa(e); |
|
| 594 |
+-- |
|
| 595 |
+2.7.4 |
|
| 596 |
+ |
| 0 | 597 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,42 @@ |
| 0 |
+From 43d2482f8472a21571feadade4d945d3048aec00 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: John Johansen <john.johansen@canonical.com> |
|
| 2 |
+Date: Fri, 29 Jun 2012 17:34:00 -0700 |
|
| 3 |
+Subject: [PATCH 2/3] apparmor: Fix quieting of audit messages for network |
|
| 4 |
+ mediation |
|
| 5 |
+ |
|
| 6 |
+[ This is an out-of-tree patch distributed with the AppArmor source |
|
| 7 |
+ code (v2.13) ] |
|
| 8 |
+ |
|
| 9 |
+If a profile specified a quieting of network denials for a given rule by |
|
| 10 |
+either the quiet or deny rule qualifiers, the resultant quiet mask for |
|
| 11 |
+denied requests was applied incorrectly, resulting in two potential bugs. |
|
| 12 |
+1. The misapplied quiet mask would prevent denials from being correctly |
|
| 13 |
+ tested against the kill mask/mode. Thus network access requests that |
|
| 14 |
+ should have resulted in the application being killed did not. |
|
| 15 |
+ |
|
| 16 |
+2. The actual quieting of the denied network request was not being applied. |
|
| 17 |
+ This would result in network rejections always being logged even when |
|
| 18 |
+ they had been specifically marked as quieted. |
|
| 19 |
+ |
|
| 20 |
+Signed-off-by: John Johansen <john.johansen@canonical.com> |
|
| 21 |
+Signed-off-by: Srivatsa S. Bhat <srivatsa@csail.mit.edu> |
|
| 22 |
+--- |
|
| 23 |
+ security/apparmor/net.c | 2 +- |
|
| 24 |
+ 1 file changed, 1 insertion(+), 1 deletion(-) |
|
| 25 |
+ |
|
| 26 |
+diff --git a/security/apparmor/net.c b/security/apparmor/net.c |
|
| 27 |
+index 003dd18..6e6e5c9 100644 |
|
| 28 |
+--- a/security/apparmor/net.c |
|
| 29 |
+@@ -88,7 +88,7 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type, |
|
| 30 |
+ } else {
|
|
| 31 |
+ u16 quiet_mask = profile->net.quiet[sa.u.net->family]; |
|
| 32 |
+ u16 kill_mask = 0; |
|
| 33 |
+- u16 denied = (1 << sa.aad->net.type) & ~quiet_mask; |
|
| 34 |
++ u16 denied = (1 << sa.aad->net.type); |
|
| 35 |
+ |
|
| 36 |
+ if (denied & kill_mask) |
|
| 37 |
+ audit_type = AUDIT_APPARMOR_KILL; |
|
| 38 |
+-- |
|
| 39 |
+2.7.4 |
|
| 40 |
+ |
| 0 | 41 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,966 @@ |
| 0 |
+From 4d628e0f2b5d6346131f117b7e61ca873b6ad99b Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: John Johansen <john.johansen@canonical.com> |
|
| 2 |
+Date: Wed, 16 May 2012 10:58:05 -0700 |
|
| 3 |
+Subject: [PATCH 3/3] UBUNTU: SAUCE: apparmor: Add the ability to mediate mount |
|
| 4 |
+ |
|
| 5 |
+[ This is an out-of-tree patch distributed with the AppArmor source |
|
| 6 |
+ code (v2.13) ] |
|
| 7 |
+ |
|
| 8 |
+Add the ability for apparmor to do mediation of mount operations. Mount |
|
| 9 |
+rules require an updated apparmor_parser (2.8 series) for policy compilation. |
|
| 10 |
+ |
|
| 11 |
+The basic form of the rules are. |
|
| 12 |
+ |
|
| 13 |
+ [audit] [deny] mount [conds]* [device] [ -> [conds] path], |
|
| 14 |
+ [audit] [deny] remount [conds]* [path], |
|
| 15 |
+ [audit] [deny] umount [conds]* [path], |
|
| 16 |
+ [audit] [deny] pivotroot [oldroot=<value>] <path> |
|
| 17 |
+ |
|
| 18 |
+ remount is just a short cut for mount options=remount |
|
| 19 |
+ |
|
| 20 |
+ where [conds] can be |
|
| 21 |
+ fstype=<expr> |
|
| 22 |
+ options=<expr> |
|
| 23 |
+ |
|
| 24 |
+Example mount commands |
|
| 25 |
+ mount, # allow all mounts, but not umount or pivotroot |
|
| 26 |
+ |
|
| 27 |
+ mount fstype=procfs, # allow mounting procfs anywhere |
|
| 28 |
+ |
|
| 29 |
+ mount options=(bind, ro) /foo -> /bar, # readonly bind mount |
|
| 30 |
+ |
|
| 31 |
+ mount /dev/sda -> /mnt, |
|
| 32 |
+ |
|
| 33 |
+ mount /dev/sd** -> /mnt/**, |
|
| 34 |
+ |
|
| 35 |
+ mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) -> /mnt/ |
|
| 36 |
+ |
|
| 37 |
+ umount, |
|
| 38 |
+ |
|
| 39 |
+ umount /m*, |
|
| 40 |
+ |
|
| 41 |
+See the apparmor userspace for full documentation |
|
| 42 |
+ |
|
| 43 |
+Signed-off-by: John Johansen <john.johansen@canonical.com> |
|
| 44 |
+Acked-by: Kees Cook <kees@ubuntu.com> |
|
| 45 |
+Signed-off-by: Srivatsa S. Bhat <srivatsa@csail.mit.edu> |
|
| 46 |
+--- |
|
| 47 |
+ security/apparmor/Makefile | 2 +- |
|
| 48 |
+ security/apparmor/apparmorfs.c | 15 +- |
|
| 49 |
+ security/apparmor/audit.c | 4 + |
|
| 50 |
+ security/apparmor/domain.c | 2 +- |
|
| 51 |
+ security/apparmor/include/apparmor.h | 3 +- |
|
| 52 |
+ security/apparmor/include/audit.h | 11 + |
|
| 53 |
+ security/apparmor/include/domain.h | 2 + |
|
| 54 |
+ security/apparmor/include/mount.h | 54 +++ |
|
| 55 |
+ security/apparmor/lsm.c | 60 ++++ |
|
| 56 |
+ security/apparmor/mount.c | 620 +++++++++++++++++++++++++++++++++++ |
|
| 57 |
+ 10 files changed, 769 insertions(+), 4 deletions(-) |
|
| 58 |
+ create mode 100644 security/apparmor/include/mount.h |
|
| 59 |
+ create mode 100644 security/apparmor/mount.c |
|
| 60 |
+ |
|
| 61 |
+diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile |
|
| 62 |
+index 5dbb72f..89b3445 100644 |
|
| 63 |
+--- a/security/apparmor/Makefile |
|
| 64 |
+@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o |
|
| 65 |
+ |
|
| 66 |
+ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ |
|
| 67 |
+ path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ |
|
| 68 |
+- resource.o sid.o file.o net.o |
|
| 69 |
++ resource.o sid.o file.o net.o mount.o |
|
| 70 |
+ apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o |
|
| 71 |
+ |
|
| 72 |
+ clean-files := capability_names.h rlim_names.h net_names.h |
|
| 73 |
+diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c |
|
| 74 |
+index bd558db..fa61086 100644 |
|
| 75 |
+--- a/security/apparmor/apparmorfs.c |
|
| 76 |
+@@ -800,7 +800,18 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
|
|
| 77 |
+ |
|
| 78 |
+ static struct aa_fs_entry aa_fs_entry_policy[] = {
|
|
| 79 |
+ AA_FS_FILE_BOOLEAN("set_load", 1),
|
|
| 80 |
+- {}
|
|
| 81 |
++ { }
|
|
| 82 |
++}; |
|
| 83 |
++ |
|
| 84 |
++static struct aa_fs_entry aa_fs_entry_mount[] = {
|
|
| 85 |
++ AA_FS_FILE_STRING("mask", "mount umount"),
|
|
| 86 |
++ { }
|
|
| 87 |
++}; |
|
| 88 |
++ |
|
| 89 |
++static struct aa_fs_entry aa_fs_entry_namespaces[] = {
|
|
| 90 |
++ AA_FS_FILE_BOOLEAN("profile", 1),
|
|
| 91 |
++ AA_FS_FILE_BOOLEAN("pivot_root", 1),
|
|
| 92 |
++ { }
|
|
| 93 |
+ }; |
|
| 94 |
+ |
|
| 95 |
+ static struct aa_fs_entry aa_fs_entry_features[] = {
|
|
| 96 |
+@@ -808,6 +819,8 @@ static struct aa_fs_entry aa_fs_entry_features[] = {
|
|
| 97 |
+ AA_FS_DIR("domain", aa_fs_entry_domain),
|
|
| 98 |
+ AA_FS_DIR("file", aa_fs_entry_file),
|
|
| 99 |
+ AA_FS_DIR("network", aa_fs_entry_network),
|
|
| 100 |
++ AA_FS_DIR("mount", aa_fs_entry_mount),
|
|
| 101 |
++ AA_FS_DIR("namespaces", aa_fs_entry_namespaces),
|
|
| 102 |
+ AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
|
|
| 103 |
+ AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
|
|
| 104 |
+ AA_FS_DIR("caps", aa_fs_entry_caps),
|
|
| 105 |
+diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c |
|
| 106 |
+index 3a7f1da..c2a8b8a 100644 |
|
| 107 |
+--- a/security/apparmor/audit.c |
|
| 108 |
+@@ -44,6 +44,10 @@ const char *const op_table[] = {
|
|
| 109 |
+ "file_mmap", |
|
| 110 |
+ "file_mprotect", |
|
| 111 |
+ |
|
| 112 |
++ "pivotroot", |
|
| 113 |
++ "mount", |
|
| 114 |
++ "umount", |
|
| 115 |
++ |
|
| 116 |
+ "create", |
|
| 117 |
+ "post_create", |
|
| 118 |
+ "bind", |
|
| 119 |
+diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c |
|
| 120 |
+index a4d90aa..dbd68f2 100644 |
|
| 121 |
+--- a/security/apparmor/domain.c |
|
| 122 |
+@@ -236,7 +236,7 @@ static const char *next_name(int xtype, const char *name) |
|
| 123 |
+ * |
|
| 124 |
+ * Returns: refcounted profile, or NULL on failure (MAYBE NULL) |
|
| 125 |
+ */ |
|
| 126 |
+-static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex) |
|
| 127 |
++struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex) |
|
| 128 |
+ {
|
|
| 129 |
+ struct aa_profile *new_profile = NULL; |
|
| 130 |
+ struct aa_namespace *ns = profile->ns; |
|
| 131 |
+diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h |
|
| 132 |
+index 5d721e9..b57da7b 100644 |
|
| 133 |
+--- a/security/apparmor/include/apparmor.h |
|
| 134 |
+@@ -30,8 +30,9 @@ |
|
| 135 |
+ #define AA_CLASS_NET 4 |
|
| 136 |
+ #define AA_CLASS_RLIMITS 5 |
|
| 137 |
+ #define AA_CLASS_DOMAIN 6 |
|
| 138 |
++#define AA_CLASS_MOUNT 7 |
|
| 139 |
+ |
|
| 140 |
+-#define AA_CLASS_LAST AA_CLASS_DOMAIN |
|
| 141 |
++#define AA_CLASS_LAST AA_CLASS_MOUNT |
|
| 142 |
+ |
|
| 143 |
+ /* Control parameters settable through module/boot flags */ |
|
| 144 |
+ extern enum audit_mode aa_g_audit; |
|
| 145 |
+diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h |
|
| 146 |
+index 5d3c419..b9f1d57 100644 |
|
| 147 |
+--- a/security/apparmor/include/audit.h |
|
| 148 |
+@@ -72,6 +72,10 @@ enum aa_ops {
|
|
| 149 |
+ OP_FMMAP, |
|
| 150 |
+ OP_FMPROT, |
|
| 151 |
+ |
|
| 152 |
++ OP_PIVOTROOT, |
|
| 153 |
++ OP_MOUNT, |
|
| 154 |
++ OP_UMOUNT, |
|
| 155 |
++ |
|
| 156 |
+ OP_CREATE, |
|
| 157 |
+ OP_POST_CREATE, |
|
| 158 |
+ OP_BIND, |
|
| 159 |
+@@ -120,6 +124,13 @@ struct apparmor_audit_data {
|
|
| 160 |
+ unsigned long max; |
|
| 161 |
+ } rlim; |
|
| 162 |
+ struct {
|
|
| 163 |
++ const char *src_name; |
|
| 164 |
++ const char *type; |
|
| 165 |
++ const char *trans; |
|
| 166 |
++ const char *data; |
|
| 167 |
++ unsigned long flags; |
|
| 168 |
++ } mnt; |
|
| 169 |
++ struct {
|
|
| 170 |
+ const char *target; |
|
| 171 |
+ u32 request; |
|
| 172 |
+ u32 denied; |
|
| 173 |
+diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h |
|
| 174 |
+index de04464..a3f70c5 100644 |
|
| 175 |
+--- a/security/apparmor/include/domain.h |
|
| 176 |
+@@ -23,6 +23,8 @@ struct aa_domain {
|
|
| 177 |
+ char **table; |
|
| 178 |
+ }; |
|
| 179 |
+ |
|
| 180 |
++struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex); |
|
| 181 |
++ |
|
| 182 |
+ int apparmor_bprm_set_creds(struct linux_binprm *bprm); |
|
| 183 |
+ int apparmor_bprm_secureexec(struct linux_binprm *bprm); |
|
| 184 |
+ void apparmor_bprm_committing_creds(struct linux_binprm *bprm); |
|
| 185 |
+diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h |
|
| 186 |
+new file mode 100644 |
|
| 187 |
+index 0000000..a43b1d6 |
|
| 188 |
+--- /dev/null |
|
| 189 |
+@@ -0,0 +1,54 @@ |
|
| 190 |
++/* |
|
| 191 |
++ * AppArmor security module |
|
| 192 |
++ * |
|
| 193 |
++ * This file contains AppArmor file mediation function definitions. |
|
| 194 |
++ * |
|
| 195 |
++ * Copyright 2012 Canonical Ltd. |
|
| 196 |
++ * |
|
| 197 |
++ * This program is free software; you can redistribute it and/or |
|
| 198 |
++ * modify it under the terms of the GNU General Public License as |
|
| 199 |
++ * published by the Free Software Foundation, version 2 of the |
|
| 200 |
++ * License. |
|
| 201 |
++ */ |
|
| 202 |
++ |
|
| 203 |
++#ifndef __AA_MOUNT_H |
|
| 204 |
++#define __AA_MOUNT_H |
|
| 205 |
++ |
|
| 206 |
++#include <linux/fs.h> |
|
| 207 |
++#include <linux/path.h> |
|
| 208 |
++ |
|
| 209 |
++#include "domain.h" |
|
| 210 |
++#include "policy.h" |
|
| 211 |
++ |
|
| 212 |
++/* mount perms */ |
|
| 213 |
++#define AA_MAY_PIVOTROOT 0x01 |
|
| 214 |
++#define AA_MAY_MOUNT 0x02 |
|
| 215 |
++#define AA_MAY_UMOUNT 0x04 |
|
| 216 |
++#define AA_AUDIT_DATA 0x40 |
|
| 217 |
++#define AA_CONT_MATCH 0x40 |
|
| 218 |
++ |
|
| 219 |
++#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN) |
|
| 220 |
++ |
|
| 221 |
++int aa_remount(struct aa_profile *profile, const struct path *path, |
|
| 222 |
++ unsigned long flags, void *data); |
|
| 223 |
++ |
|
| 224 |
++int aa_bind_mount(struct aa_profile *profile, const struct path *path, |
|
| 225 |
++ const char *old_name, unsigned long flags); |
|
| 226 |
++ |
|
| 227 |
++ |
|
| 228 |
++int aa_mount_change_type(struct aa_profile *profile, const struct path *path, |
|
| 229 |
++ unsigned long flags); |
|
| 230 |
++ |
|
| 231 |
++int aa_move_mount(struct aa_profile *profile, const struct path *path, |
|
| 232 |
++ const char *old_name); |
|
| 233 |
++ |
|
| 234 |
++int aa_new_mount(struct aa_profile *profile, const char *dev_name, |
|
| 235 |
++ const struct path *path, const char *type, unsigned long flags, |
|
| 236 |
++ void *data); |
|
| 237 |
++ |
|
| 238 |
++int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags); |
|
| 239 |
++ |
|
| 240 |
++int aa_pivotroot(struct aa_profile *profile, const struct path *old_path, |
|
| 241 |
++ const struct path *new_path); |
|
| 242 |
++ |
|
| 243 |
++#endif /* __AA_MOUNT_H */ |
|
| 244 |
+diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c |
|
| 245 |
+index de3b68a..40c9fda 100644 |
|
| 246 |
+--- a/security/apparmor/lsm.c |
|
| 247 |
+@@ -36,6 +36,7 @@ |
|
| 248 |
+ #include "include/path.h" |
|
| 249 |
+ #include "include/policy.h" |
|
| 250 |
+ #include "include/procattr.h" |
|
| 251 |
++#include "include/mount.h" |
|
| 252 |
+ |
|
| 253 |
+ /* Flag indicating whether initialization completed */ |
|
| 254 |
+ int apparmor_initialized __initdata; |
|
| 255 |
+@@ -469,6 +470,61 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma, |
|
| 256 |
+ !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0); |
|
| 257 |
+ } |
|
| 258 |
+ |
|
| 259 |
++static int apparmor_sb_mount(const char *dev_name, const struct path *path, |
|
| 260 |
++ const char *type, unsigned long flags, void *data) |
|
| 261 |
++{
|
|
| 262 |
++ struct aa_profile *profile; |
|
| 263 |
++ int error = 0; |
|
| 264 |
++ |
|
| 265 |
++ /* Discard magic */ |
|
| 266 |
++ if ((flags & MS_MGC_MSK) == MS_MGC_VAL) |
|
| 267 |
++ flags &= ~MS_MGC_MSK; |
|
| 268 |
++ |
|
| 269 |
++ flags &= ~AA_MS_IGNORE_MASK; |
|
| 270 |
++ |
|
| 271 |
++ profile = __aa_current_profile(); |
|
| 272 |
++ if (!unconfined(profile)) {
|
|
| 273 |
++ if (flags & MS_REMOUNT) |
|
| 274 |
++ error = aa_remount(profile, path, flags, data); |
|
| 275 |
++ else if (flags & MS_BIND) |
|
| 276 |
++ error = aa_bind_mount(profile, path, dev_name, flags); |
|
| 277 |
++ else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | |
|
| 278 |
++ MS_UNBINDABLE)) |
|
| 279 |
++ error = aa_mount_change_type(profile, path, flags); |
|
| 280 |
++ else if (flags & MS_MOVE) |
|
| 281 |
++ error = aa_move_mount(profile, path, dev_name); |
|
| 282 |
++ else |
|
| 283 |
++ error = aa_new_mount(profile, dev_name, path, type, |
|
| 284 |
++ flags, data); |
|
| 285 |
++ } |
|
| 286 |
++ return error; |
|
| 287 |
++} |
|
| 288 |
++ |
|
| 289 |
++static int apparmor_sb_umount(struct vfsmount *mnt, int flags) |
|
| 290 |
++{
|
|
| 291 |
++ struct aa_profile *profile; |
|
| 292 |
++ int error = 0; |
|
| 293 |
++ |
|
| 294 |
++ profile = __aa_current_profile(); |
|
| 295 |
++ if (!unconfined(profile)) |
|
| 296 |
++ error = aa_umount(profile, mnt, flags); |
|
| 297 |
++ |
|
| 298 |
++ return error; |
|
| 299 |
++} |
|
| 300 |
++ |
|
| 301 |
++static int apparmor_sb_pivotroot(const struct path *old_path, |
|
| 302 |
++ const struct path *new_path) |
|
| 303 |
++{
|
|
| 304 |
++ struct aa_profile *profile; |
|
| 305 |
++ int error = 0; |
|
| 306 |
++ |
|
| 307 |
++ profile = __aa_current_profile(); |
|
| 308 |
++ if (!unconfined(profile)) |
|
| 309 |
++ error = aa_pivotroot(profile, old_path, new_path); |
|
| 310 |
++ |
|
| 311 |
++ return error; |
|
| 312 |
++} |
|
| 313 |
++ |
|
| 314 |
+ static int apparmor_getprocattr(struct task_struct *task, char *name, |
|
| 315 |
+ char **value) |
|
| 316 |
+ {
|
|
| 317 |
+@@ -689,6 +745,10 @@ static struct security_hook_list apparmor_hooks[] = {
|
|
| 318 |
+ LSM_HOOK_INIT(capget, apparmor_capget), |
|
| 319 |
+ LSM_HOOK_INIT(capable, apparmor_capable), |
|
| 320 |
+ |
|
| 321 |
++ LSM_HOOK_INIT(sb_mount, apparmor_sb_mount), |
|
| 322 |
++ LSM_HOOK_INIT(sb_umount, apparmor_sb_umount), |
|
| 323 |
++ LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot), |
|
| 324 |
++ |
|
| 325 |
+ LSM_HOOK_INIT(path_link, apparmor_path_link), |
|
| 326 |
+ LSM_HOOK_INIT(path_unlink, apparmor_path_unlink), |
|
| 327 |
+ LSM_HOOK_INIT(path_symlink, apparmor_path_symlink), |
|
| 328 |
+diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c |
|
| 329 |
+new file mode 100644 |
|
| 330 |
+index 0000000..9cf9170 |
|
| 331 |
+--- /dev/null |
|
| 332 |
+@@ -0,0 +1,620 @@ |
|
| 333 |
++/* |
|
| 334 |
++ * AppArmor security module |
|
| 335 |
++ * |
|
| 336 |
++ * This file contains AppArmor mediation of files |
|
| 337 |
++ * |
|
| 338 |
++ * Copyright (C) 1998-2008 Novell/SUSE |
|
| 339 |
++ * Copyright 2009-2012 Canonical Ltd. |
|
| 340 |
++ * |
|
| 341 |
++ * This program is free software; you can redistribute it and/or |
|
| 342 |
++ * modify it under the terms of the GNU General Public License as |
|
| 343 |
++ * published by the Free Software Foundation, version 2 of the |
|
| 344 |
++ * License. |
|
| 345 |
++ */ |
|
| 346 |
++ |
|
| 347 |
++#include <linux/fs.h> |
|
| 348 |
++#include <linux/mount.h> |
|
| 349 |
++#include <linux/namei.h> |
|
| 350 |
++ |
|
| 351 |
++#include "include/apparmor.h" |
|
| 352 |
++#include "include/audit.h" |
|
| 353 |
++#include "include/context.h" |
|
| 354 |
++#include "include/domain.h" |
|
| 355 |
++#include "include/file.h" |
|
| 356 |
++#include "include/match.h" |
|
| 357 |
++#include "include/mount.h" |
|
| 358 |
++#include "include/path.h" |
|
| 359 |
++#include "include/policy.h" |
|
| 360 |
++ |
|
| 361 |
++ |
|
| 362 |
++static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags) |
|
| 363 |
++{
|
|
| 364 |
++ if (flags & MS_RDONLY) |
|
| 365 |
++ audit_log_format(ab, "ro"); |
|
| 366 |
++ else |
|
| 367 |
++ audit_log_format(ab, "rw"); |
|
| 368 |
++ if (flags & MS_NOSUID) |
|
| 369 |
++ audit_log_format(ab, ", nosuid"); |
|
| 370 |
++ if (flags & MS_NODEV) |
|
| 371 |
++ audit_log_format(ab, ", nodev"); |
|
| 372 |
++ if (flags & MS_NOEXEC) |
|
| 373 |
++ audit_log_format(ab, ", noexec"); |
|
| 374 |
++ if (flags & MS_SYNCHRONOUS) |
|
| 375 |
++ audit_log_format(ab, ", sync"); |
|
| 376 |
++ if (flags & MS_REMOUNT) |
|
| 377 |
++ audit_log_format(ab, ", remount"); |
|
| 378 |
++ if (flags & MS_MANDLOCK) |
|
| 379 |
++ audit_log_format(ab, ", mand"); |
|
| 380 |
++ if (flags & MS_DIRSYNC) |
|
| 381 |
++ audit_log_format(ab, ", dirsync"); |
|
| 382 |
++ if (flags & MS_NOATIME) |
|
| 383 |
++ audit_log_format(ab, ", noatime"); |
|
| 384 |
++ if (flags & MS_NODIRATIME) |
|
| 385 |
++ audit_log_format(ab, ", nodiratime"); |
|
| 386 |
++ if (flags & MS_BIND) |
|
| 387 |
++ audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind"); |
|
| 388 |
++ if (flags & MS_MOVE) |
|
| 389 |
++ audit_log_format(ab, ", move"); |
|
| 390 |
++ if (flags & MS_SILENT) |
|
| 391 |
++ audit_log_format(ab, ", silent"); |
|
| 392 |
++ if (flags & MS_POSIXACL) |
|
| 393 |
++ audit_log_format(ab, ", acl"); |
|
| 394 |
++ if (flags & MS_UNBINDABLE) |
|
| 395 |
++ audit_log_format(ab, flags & MS_REC ? ", runbindable" : |
|
| 396 |
++ ", unbindable"); |
|
| 397 |
++ if (flags & MS_PRIVATE) |
|
| 398 |
++ audit_log_format(ab, flags & MS_REC ? ", rprivate" : |
|
| 399 |
++ ", private"); |
|
| 400 |
++ if (flags & MS_SLAVE) |
|
| 401 |
++ audit_log_format(ab, flags & MS_REC ? ", rslave" : |
|
| 402 |
++ ", slave"); |
|
| 403 |
++ if (flags & MS_SHARED) |
|
| 404 |
++ audit_log_format(ab, flags & MS_REC ? ", rshared" : |
|
| 405 |
++ ", shared"); |
|
| 406 |
++ if (flags & MS_RELATIME) |
|
| 407 |
++ audit_log_format(ab, ", relatime"); |
|
| 408 |
++ if (flags & MS_I_VERSION) |
|
| 409 |
++ audit_log_format(ab, ", iversion"); |
|
| 410 |
++ if (flags & MS_STRICTATIME) |
|
| 411 |
++ audit_log_format(ab, ", strictatime"); |
|
| 412 |
++ if (flags & MS_NOUSER) |
|
| 413 |
++ audit_log_format(ab, ", nouser"); |
|
| 414 |
++} |
|
| 415 |
++ |
|
| 416 |
++/** |
|
| 417 |
++ * audit_cb - call back for mount specific audit fields |
|
| 418 |
++ * @ab: audit_buffer (NOT NULL) |
|
| 419 |
++ * @va: audit struct to audit values of (NOT NULL) |
|
| 420 |
++ */ |
|
| 421 |
++static void audit_cb(struct audit_buffer *ab, void *va) |
|
| 422 |
++{
|
|
| 423 |
++ struct common_audit_data *sa = va; |
|
| 424 |
++ |
|
| 425 |
++ if (sa->aad->mnt.type) {
|
|
| 426 |
++ audit_log_format(ab, " fstype="); |
|
| 427 |
++ audit_log_untrustedstring(ab, sa->aad->mnt.type); |
|
| 428 |
++ } |
|
| 429 |
++ if (sa->aad->mnt.src_name) {
|
|
| 430 |
++ audit_log_format(ab, " srcname="); |
|
| 431 |
++ audit_log_untrustedstring(ab, sa->aad->mnt.src_name); |
|
| 432 |
++ } |
|
| 433 |
++ if (sa->aad->mnt.trans) {
|
|
| 434 |
++ audit_log_format(ab, " trans="); |
|
| 435 |
++ audit_log_untrustedstring(ab, sa->aad->mnt.trans); |
|
| 436 |
++ } |
|
| 437 |
++ if (sa->aad->mnt.flags || sa->aad->op == OP_MOUNT) {
|
|
| 438 |
++ audit_log_format(ab, " flags=\""); |
|
| 439 |
++ audit_mnt_flags(ab, sa->aad->mnt.flags); |
|
| 440 |
++ audit_log_format(ab, "\""); |
|
| 441 |
++ } |
|
| 442 |
++ if (sa->aad->mnt.data) {
|
|
| 443 |
++ audit_log_format(ab, " options="); |
|
| 444 |
++ audit_log_untrustedstring(ab, sa->aad->mnt.data); |
|
| 445 |
++ } |
|
| 446 |
++} |
|
| 447 |
++ |
|
| 448 |
++/** |
|
| 449 |
++ * audit_mount - handle the auditing of mount operations |
|
| 450 |
++ * @profile: the profile being enforced (NOT NULL) |
|
| 451 |
++ * @gfp: allocation flags |
|
| 452 |
++ * @op: operation being mediated (NOT NULL) |
|
| 453 |
++ * @name: name of object being mediated (MAYBE NULL) |
|
| 454 |
++ * @src_name: src_name of object being mediated (MAYBE_NULL) |
|
| 455 |
++ * @type: type of filesystem (MAYBE_NULL) |
|
| 456 |
++ * @trans: name of trans (MAYBE NULL) |
|
| 457 |
++ * @flags: filesystem idependent mount flags |
|
| 458 |
++ * @data: filesystem mount flags |
|
| 459 |
++ * @request: permissions requested |
|
| 460 |
++ * @perms: the permissions computed for the request (NOT NULL) |
|
| 461 |
++ * @info: extra information message (MAYBE NULL) |
|
| 462 |
++ * @error: 0 if operation allowed else failure error code |
|
| 463 |
++ * |
|
| 464 |
++ * Returns: %0 or error on failure |
|
| 465 |
++ */ |
|
| 466 |
++static int audit_mount(struct aa_profile *profile, gfp_t gfp, int op, |
|
| 467 |
++ const char *name, const char *src_name, |
|
| 468 |
++ const char *type, const char *trans, |
|
| 469 |
++ unsigned long flags, const void *data, u32 request, |
|
| 470 |
++ struct file_perms *perms, const char *info, int error) |
|
| 471 |
++{
|
|
| 472 |
++ int audit_type = AUDIT_APPARMOR_AUTO; |
|
| 473 |
++ struct common_audit_data sa = { };
|
|
| 474 |
++ struct apparmor_audit_data aad = { };
|
|
| 475 |
++ |
|
| 476 |
++ if (likely(!error)) {
|
|
| 477 |
++ u32 mask = perms->audit; |
|
| 478 |
++ |
|
| 479 |
++ if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) |
|
| 480 |
++ mask = 0xffff; |
|
| 481 |
++ |
|
| 482 |
++ /* mask off perms that are not being force audited */ |
|
| 483 |
++ request &= mask; |
|
| 484 |
++ |
|
| 485 |
++ if (likely(!request)) |
|
| 486 |
++ return 0; |
|
| 487 |
++ audit_type = AUDIT_APPARMOR_AUDIT; |
|
| 488 |
++ } else {
|
|
| 489 |
++ /* only report permissions that were denied */ |
|
| 490 |
++ request = request & ~perms->allow; |
|
| 491 |
++ |
|
| 492 |
++ if (request & perms->kill) |
|
| 493 |
++ audit_type = AUDIT_APPARMOR_KILL; |
|
| 494 |
++ |
|
| 495 |
++ /* quiet known rejects, assumes quiet and kill do not overlap */ |
|
| 496 |
++ if ((request & perms->quiet) && |
|
| 497 |
++ AUDIT_MODE(profile) != AUDIT_NOQUIET && |
|
| 498 |
++ AUDIT_MODE(profile) != AUDIT_ALL) |
|
| 499 |
++ request &= ~perms->quiet; |
|
| 500 |
++ |
|
| 501 |
++ if (!request) |
|
| 502 |
++ return COMPLAIN_MODE(profile) ? |
|
| 503 |
++ complain_error(error) : error; |
|
| 504 |
++ } |
|
| 505 |
++ |
|
| 506 |
++ sa.type = LSM_AUDIT_DATA_NONE; |
|
| 507 |
++ sa.aad = &aad; |
|
| 508 |
++ sa.aad->op = op; |
|
| 509 |
++ sa.aad->name = name; |
|
| 510 |
++ sa.aad->mnt.src_name = src_name; |
|
| 511 |
++ sa.aad->mnt.type = type; |
|
| 512 |
++ sa.aad->mnt.trans = trans; |
|
| 513 |
++ sa.aad->mnt.flags = flags; |
|
| 514 |
++ if (data && (perms->audit & AA_AUDIT_DATA)) |
|
| 515 |
++ sa.aad->mnt.data = data; |
|
| 516 |
++ sa.aad->info = info; |
|
| 517 |
++ sa.aad->error = error; |
|
| 518 |
++ |
|
| 519 |
++ return aa_audit(audit_type, profile, gfp, &sa, audit_cb); |
|
| 520 |
++} |
|
| 521 |
++ |
|
| 522 |
++/** |
|
| 523 |
++ * match_mnt_flags - Do an ordered match on mount flags |
|
| 524 |
++ * @dfa: dfa to match against |
|
| 525 |
++ * @state: state to start in |
|
| 526 |
++ * @flags: mount flags to match against |
|
| 527 |
++ * |
|
| 528 |
++ * Mount flags are encoded as an ordered match. This is done instead of |
|
| 529 |
++ * checking against a simple bitmask, to allow for logical operations |
|
| 530 |
++ * on the flags. |
|
| 531 |
++ * |
|
| 532 |
++ * Returns: next state after flags match |
|
| 533 |
++ */ |
|
| 534 |
++static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state, |
|
| 535 |
++ unsigned long flags) |
|
| 536 |
++{
|
|
| 537 |
++ unsigned int i; |
|
| 538 |
++ |
|
| 539 |
++ for (i = 0; i <= 31 ; ++i) {
|
|
| 540 |
++ if ((1 << i) & flags) |
|
| 541 |
++ state = aa_dfa_next(dfa, state, i + 1); |
|
| 542 |
++ } |
|
| 543 |
++ |
|
| 544 |
++ return state; |
|
| 545 |
++} |
|
| 546 |
++ |
|
| 547 |
++/** |
|
| 548 |
++ * compute_mnt_perms - compute mount permission associated with @state |
|
| 549 |
++ * @dfa: dfa to match against (NOT NULL) |
|
| 550 |
++ * @state: state match finished in |
|
| 551 |
++ * |
|
| 552 |
++ * Returns: mount permissions |
|
| 553 |
++ */ |
|
| 554 |
++static struct file_perms compute_mnt_perms(struct aa_dfa *dfa, |
|
| 555 |
++ unsigned int state) |
|
| 556 |
++{
|
|
| 557 |
++ struct file_perms perms; |
|
| 558 |
++ |
|
| 559 |
++ perms.kill = 0; |
|
| 560 |
++ perms.allow = dfa_user_allow(dfa, state); |
|
| 561 |
++ perms.audit = dfa_user_audit(dfa, state); |
|
| 562 |
++ perms.quiet = dfa_user_quiet(dfa, state); |
|
| 563 |
++ perms.xindex = dfa_user_xindex(dfa, state); |
|
| 564 |
++ |
|
| 565 |
++ return perms; |
|
| 566 |
++} |
|
| 567 |
++ |
|
| 568 |
++static const char const *mnt_info_table[] = {
|
|
| 569 |
++ "match succeeded", |
|
| 570 |
++ "failed mntpnt match", |
|
| 571 |
++ "failed srcname match", |
|
| 572 |
++ "failed type match", |
|
| 573 |
++ "failed flags match", |
|
| 574 |
++ "failed data match" |
|
| 575 |
++}; |
|
| 576 |
++ |
|
| 577 |
++/* |
|
| 578 |
++ * Returns 0 on success else element that match failed in, this is the |
|
| 579 |
++ * index into the mnt_info_table above |
|
| 580 |
++ */ |
|
| 581 |
++static int do_match_mnt(struct aa_dfa *dfa, unsigned int start, |
|
| 582 |
++ const char *mntpnt, const char *devname, |
|
| 583 |
++ const char *type, unsigned long flags, |
|
| 584 |
++ void *data, bool binary, struct file_perms *perms) |
|
| 585 |
++{
|
|
| 586 |
++ unsigned int state; |
|
| 587 |
++ |
|
| 588 |
++ state = aa_dfa_match(dfa, start, mntpnt); |
|
| 589 |
++ state = aa_dfa_null_transition(dfa, state); |
|
| 590 |
++ if (!state) |
|
| 591 |
++ return 1; |
|
| 592 |
++ |
|
| 593 |
++ if (devname) |
|
| 594 |
++ state = aa_dfa_match(dfa, state, devname); |
|
| 595 |
++ state = aa_dfa_null_transition(dfa, state); |
|
| 596 |
++ if (!state) |
|
| 597 |
++ return 2; |
|
| 598 |
++ |
|
| 599 |
++ if (type) |
|
| 600 |
++ state = aa_dfa_match(dfa, state, type); |
|
| 601 |
++ state = aa_dfa_null_transition(dfa, state); |
|
| 602 |
++ if (!state) |
|
| 603 |
++ return 3; |
|
| 604 |
++ |
|
| 605 |
++ state = match_mnt_flags(dfa, state, flags); |
|
| 606 |
++ if (!state) |
|
| 607 |
++ return 4; |
|
| 608 |
++ *perms = compute_mnt_perms(dfa, state); |
|
| 609 |
++ if (perms->allow & AA_MAY_MOUNT) |
|
| 610 |
++ return 0; |
|
| 611 |
++ |
|
| 612 |
++ /* only match data if not binary and the DFA flags data is expected */ |
|
| 613 |
++ if (data && !binary && (perms->allow & AA_CONT_MATCH)) {
|
|
| 614 |
++ state = aa_dfa_null_transition(dfa, state); |
|
| 615 |
++ if (!state) |
|
| 616 |
++ return 4; |
|
| 617 |
++ |
|
| 618 |
++ state = aa_dfa_match(dfa, state, data); |
|
| 619 |
++ if (!state) |
|
| 620 |
++ return 5; |
|
| 621 |
++ *perms = compute_mnt_perms(dfa, state); |
|
| 622 |
++ if (perms->allow & AA_MAY_MOUNT) |
|
| 623 |
++ return 0; |
|
| 624 |
++ } |
|
| 625 |
++ |
|
| 626 |
++ /* failed at end of flags match */ |
|
| 627 |
++ return 4; |
|
| 628 |
++} |
|
| 629 |
++ |
|
| 630 |
++/** |
|
| 631 |
++ * match_mnt - handle path matching for mount |
|
| 632 |
++ * @profile: the confining profile |
|
| 633 |
++ * @mntpnt: string for the mntpnt (NOT NULL) |
|
| 634 |
++ * @devname: string for the devname/src_name (MAYBE NULL) |
|
| 635 |
++ * @type: string for the dev type (MAYBE NULL) |
|
| 636 |
++ * @flags: mount flags to match |
|
| 637 |
++ * @data: fs mount data (MAYBE NULL) |
|
| 638 |
++ * @binary: whether @data is binary |
|
| 639 |
++ * @perms: Returns: permission found by the match |
|
| 640 |
++ * @info: Returns: infomation string about the match for logging |
|
| 641 |
++ * |
|
| 642 |
++ * Returns: 0 on success else error |
|
| 643 |
++ */ |
|
| 644 |
++static int match_mnt(struct aa_profile *profile, const char *mntpnt, |
|
| 645 |
++ const char *devname, const char *type, |
|
| 646 |
++ unsigned long flags, void *data, bool binary, |
|
| 647 |
++ struct file_perms *perms, const char **info) |
|
| 648 |
++{
|
|
| 649 |
++ int pos; |
|
| 650 |
++ |
|
| 651 |
++ if (!profile->policy.dfa) |
|
| 652 |
++ return -EACCES; |
|
| 653 |
++ |
|
| 654 |
++ pos = do_match_mnt(profile->policy.dfa, |
|
| 655 |
++ profile->policy.start[AA_CLASS_MOUNT], |
|
| 656 |
++ mntpnt, devname, type, flags, data, binary, perms); |
|
| 657 |
++ if (pos) {
|
|
| 658 |
++ *info = mnt_info_table[pos]; |
|
| 659 |
++ return -EACCES; |
|
| 660 |
++ } |
|
| 661 |
++ |
|
| 662 |
++ return 0; |
|
| 663 |
++} |
|
| 664 |
++ |
|
| 665 |
++static int path_flags(struct aa_profile *profile, const struct path *path) |
|
| 666 |
++{
|
|
| 667 |
++ return profile->path_flags | |
|
| 668 |
++ S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0; |
|
| 669 |
++} |
|
| 670 |
++ |
|
| 671 |
++int aa_remount(struct aa_profile *profile, const struct path *path, |
|
| 672 |
++ unsigned long flags, void *data) |
|
| 673 |
++{
|
|
| 674 |
++ struct file_perms perms = { };
|
|
| 675 |
++ const char *name, *info = NULL; |
|
| 676 |
++ char *buffer = NULL; |
|
| 677 |
++ int binary, error; |
|
| 678 |
++ |
|
| 679 |
++ binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA; |
|
| 680 |
++ |
|
| 681 |
++ error = aa_path_name(path, path_flags(profile, path), &buffer, &name, |
|
| 682 |
++ &info); |
|
| 683 |
++ if (error) |
|
| 684 |
++ goto audit; |
|
| 685 |
++ |
|
| 686 |
++ error = match_mnt(profile, name, NULL, NULL, flags, data, binary, |
|
| 687 |
++ &perms, &info); |
|
| 688 |
++ |
|
| 689 |
++audit: |
|
| 690 |
++ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL, |
|
| 691 |
++ NULL, flags, data, AA_MAY_MOUNT, &perms, info, |
|
| 692 |
++ error); |
|
| 693 |
++ kfree(buffer); |
|
| 694 |
++ |
|
| 695 |
++ return error; |
|
| 696 |
++} |
|
| 697 |
++ |
|
| 698 |
++int aa_bind_mount(struct aa_profile *profile, const struct path *path, |
|
| 699 |
++ const char *dev_name, unsigned long flags) |
|
| 700 |
++{
|
|
| 701 |
++ struct file_perms perms = { };
|
|
| 702 |
++ char *buffer = NULL, *old_buffer = NULL; |
|
| 703 |
++ const char *name, *old_name = NULL, *info = NULL; |
|
| 704 |
++ struct path old_path; |
|
| 705 |
++ int error; |
|
| 706 |
++ |
|
| 707 |
++ if (!dev_name || !*dev_name) |
|
| 708 |
++ return -EINVAL; |
|
| 709 |
++ |
|
| 710 |
++ flags &= MS_REC | MS_BIND; |
|
| 711 |
++ |
|
| 712 |
++ error = aa_path_name(path, path_flags(profile, path), &buffer, &name, |
|
| 713 |
++ &info); |
|
| 714 |
++ if (error) |
|
| 715 |
++ goto audit; |
|
| 716 |
++ |
|
| 717 |
++ error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path); |
|
| 718 |
++ if (error) |
|
| 719 |
++ goto audit; |
|
| 720 |
++ |
|
| 721 |
++ error = aa_path_name(&old_path, path_flags(profile, &old_path), |
|
| 722 |
++ &old_buffer, &old_name, &info); |
|
| 723 |
++ path_put(&old_path); |
|
| 724 |
++ if (error) |
|
| 725 |
++ goto audit; |
|
| 726 |
++ |
|
| 727 |
++ error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0, |
|
| 728 |
++ &perms, &info); |
|
| 729 |
++ |
|
| 730 |
++audit: |
|
| 731 |
++ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name, |
|
| 732 |
++ NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms, |
|
| 733 |
++ info, error); |
|
| 734 |
++ kfree(buffer); |
|
| 735 |
++ kfree(old_buffer); |
|
| 736 |
++ |
|
| 737 |
++ return error; |
|
| 738 |
++} |
|
| 739 |
++ |
|
| 740 |
++int aa_mount_change_type(struct aa_profile *profile, const struct path *path, |
|
| 741 |
++ unsigned long flags) |
|
| 742 |
++{
|
|
| 743 |
++ struct file_perms perms = { };
|
|
| 744 |
++ char *buffer = NULL; |
|
| 745 |
++ const char *name, *info = NULL; |
|
| 746 |
++ int error; |
|
| 747 |
++ |
|
| 748 |
++ /* These are the flags allowed by do_change_type() */ |
|
| 749 |
++ flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE | |
|
| 750 |
++ MS_UNBINDABLE); |
|
| 751 |
++ |
|
| 752 |
++ error = aa_path_name(path, path_flags(profile, path), &buffer, &name, |
|
| 753 |
++ &info); |
|
| 754 |
++ if (error) |
|
| 755 |
++ goto audit; |
|
| 756 |
++ |
|
| 757 |
++ error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms, |
|
| 758 |
++ &info); |
|
| 759 |
++ |
|
| 760 |
++audit: |
|
| 761 |
++ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL, |
|
| 762 |
++ NULL, flags, NULL, AA_MAY_MOUNT, &perms, info, |
|
| 763 |
++ error); |
|
| 764 |
++ kfree(buffer); |
|
| 765 |
++ |
|
| 766 |
++ return error; |
|
| 767 |
++} |
|
| 768 |
++ |
|
| 769 |
++int aa_move_mount(struct aa_profile *profile, const struct path *path, |
|
| 770 |
++ const char *orig_name) |
|
| 771 |
++{
|
|
| 772 |
++ struct file_perms perms = { };
|
|
| 773 |
++ char *buffer = NULL, *old_buffer = NULL; |
|
| 774 |
++ const char *name, *old_name = NULL, *info = NULL; |
|
| 775 |
++ struct path old_path; |
|
| 776 |
++ int error; |
|
| 777 |
++ |
|
| 778 |
++ if (!orig_name || !*orig_name) |
|
| 779 |
++ return -EINVAL; |
|
| 780 |
++ |
|
| 781 |
++ error = aa_path_name(path, path_flags(profile, path), &buffer, &name, |
|
| 782 |
++ &info); |
|
| 783 |
++ if (error) |
|
| 784 |
++ goto audit; |
|
| 785 |
++ |
|
| 786 |
++ error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path); |
|
| 787 |
++ if (error) |
|
| 788 |
++ goto audit; |
|
| 789 |
++ |
|
| 790 |
++ error = aa_path_name(&old_path, path_flags(profile, &old_path), |
|
| 791 |
++ &old_buffer, &old_name, &info); |
|
| 792 |
++ path_put(&old_path); |
|
| 793 |
++ if (error) |
|
| 794 |
++ goto audit; |
|
| 795 |
++ |
|
| 796 |
++ error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0, |
|
| 797 |
++ &perms, &info); |
|
| 798 |
++ |
|
| 799 |
++audit: |
|
| 800 |
++ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name, |
|
| 801 |
++ NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms, |
|
| 802 |
++ info, error); |
|
| 803 |
++ kfree(buffer); |
|
| 804 |
++ kfree(old_buffer); |
|
| 805 |
++ |
|
| 806 |
++ return error; |
|
| 807 |
++} |
|
| 808 |
++ |
|
| 809 |
++int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name, |
|
| 810 |
++ const struct path *path, const char *type, unsigned long flags, |
|
| 811 |
++ void *data) |
|
| 812 |
++{
|
|
| 813 |
++ struct file_perms perms = { };
|
|
| 814 |
++ char *buffer = NULL, *dev_buffer = NULL; |
|
| 815 |
++ const char *name = NULL, *dev_name = NULL, *info = NULL; |
|
| 816 |
++ int binary = 1; |
|
| 817 |
++ int error; |
|
| 818 |
++ |
|
| 819 |
++ dev_name = orig_dev_name; |
|
| 820 |
++ if (type) {
|
|
| 821 |
++ int requires_dev; |
|
| 822 |
++ struct file_system_type *fstype = get_fs_type(type); |
|
| 823 |
++ if (!fstype) |
|
| 824 |
++ return -ENODEV; |
|
| 825 |
++ |
|
| 826 |
++ binary = fstype->fs_flags & FS_BINARY_MOUNTDATA; |
|
| 827 |
++ requires_dev = fstype->fs_flags & FS_REQUIRES_DEV; |
|
| 828 |
++ put_filesystem(fstype); |
|
| 829 |
++ |
|
| 830 |
++ if (requires_dev) {
|
|
| 831 |
++ struct path dev_path; |
|
| 832 |
++ |
|
| 833 |
++ if (!dev_name || !*dev_name) {
|
|
| 834 |
++ error = -ENOENT; |
|
| 835 |
++ goto out; |
|
| 836 |
++ } |
|
| 837 |
++ |
|
| 838 |
++ error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path); |
|
| 839 |
++ if (error) |
|
| 840 |
++ goto audit; |
|
| 841 |
++ |
|
| 842 |
++ error = aa_path_name(&dev_path, |
|
| 843 |
++ path_flags(profile, &dev_path), |
|
| 844 |
++ &dev_buffer, &dev_name, &info); |
|
| 845 |
++ path_put(&dev_path); |
|
| 846 |
++ if (error) |
|
| 847 |
++ goto audit; |
|
| 848 |
++ } |
|
| 849 |
++ } |
|
| 850 |
++ |
|
| 851 |
++ error = aa_path_name(path, path_flags(profile, path), &buffer, &name, |
|
| 852 |
++ &info); |
|
| 853 |
++ if (error) |
|
| 854 |
++ goto audit; |
|
| 855 |
++ |
|
| 856 |
++ error = match_mnt(profile, name, dev_name, type, flags, data, binary, |
|
| 857 |
++ &perms, &info); |
|
| 858 |
++ |
|
| 859 |
++audit: |
|
| 860 |
++ error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, dev_name, |
|
| 861 |
++ type, NULL, flags, data, AA_MAY_MOUNT, &perms, info, |
|
| 862 |
++ error); |
|
| 863 |
++ kfree(buffer); |
|
| 864 |
++ kfree(dev_buffer); |
|
| 865 |
++ |
|
| 866 |
++out: |
|
| 867 |
++ return error; |
|
| 868 |
++ |
|
| 869 |
++} |
|
| 870 |
++ |
|
| 871 |
++int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags) |
|
| 872 |
++{
|
|
| 873 |
++ struct file_perms perms = { };
|
|
| 874 |
++ char *buffer = NULL; |
|
| 875 |
++ const char *name, *info = NULL; |
|
| 876 |
++ int error; |
|
| 877 |
++ |
|
| 878 |
++ struct path path = { mnt, mnt->mnt_root };
|
|
| 879 |
++ error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name, |
|
| 880 |
++ &info); |
|
| 881 |
++ if (error) |
|
| 882 |
++ goto audit; |
|
| 883 |
++ |
|
| 884 |
++ if (!error && profile->policy.dfa) {
|
|
| 885 |
++ unsigned int state; |
|
| 886 |
++ state = aa_dfa_match(profile->policy.dfa, |
|
| 887 |
++ profile->policy.start[AA_CLASS_MOUNT], |
|
| 888 |
++ name); |
|
| 889 |
++ perms = compute_mnt_perms(profile->policy.dfa, state); |
|
| 890 |
++ } |
|
| 891 |
++ |
|
| 892 |
++ if (AA_MAY_UMOUNT & ~perms.allow) |
|
| 893 |
++ error = -EACCES; |
|
| 894 |
++ |
|
| 895 |
++audit: |
|
| 896 |
++ error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL, |
|
| 897 |
++ NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error); |
|
| 898 |
++ kfree(buffer); |
|
| 899 |
++ |
|
| 900 |
++ return error; |
|
| 901 |
++} |
|
| 902 |
++ |
|
| 903 |
++int aa_pivotroot(struct aa_profile *profile, const struct path *old_path, |
|
| 904 |
++ const struct path *new_path) |
|
| 905 |
++{
|
|
| 906 |
++ struct file_perms perms = { };
|
|
| 907 |
++ struct aa_profile *target = NULL; |
|
| 908 |
++ char *old_buffer = NULL, *new_buffer = NULL; |
|
| 909 |
++ const char *old_name, *new_name = NULL, *info = NULL; |
|
| 910 |
++ int error; |
|
| 911 |
++ |
|
| 912 |
++ error = aa_path_name(old_path, path_flags(profile, old_path), |
|
| 913 |
++ &old_buffer, &old_name, &info); |
|
| 914 |
++ if (error) |
|
| 915 |
++ goto audit; |
|
| 916 |
++ |
|
| 917 |
++ error = aa_path_name(new_path, path_flags(profile, new_path), |
|
| 918 |
++ &new_buffer, &new_name, &info); |
|
| 919 |
++ if (error) |
|
| 920 |
++ goto audit; |
|
| 921 |
++ |
|
| 922 |
++ if (profile->policy.dfa) {
|
|
| 923 |
++ unsigned int state; |
|
| 924 |
++ state = aa_dfa_match(profile->policy.dfa, |
|
| 925 |
++ profile->policy.start[AA_CLASS_MOUNT], |
|
| 926 |
++ new_name); |
|
| 927 |
++ state = aa_dfa_null_transition(profile->policy.dfa, state); |
|
| 928 |
++ state = aa_dfa_match(profile->policy.dfa, state, old_name); |
|
| 929 |
++ perms = compute_mnt_perms(profile->policy.dfa, state); |
|
| 930 |
++ } |
|
| 931 |
++ |
|
| 932 |
++ if (AA_MAY_PIVOTROOT & perms.allow) {
|
|
| 933 |
++ if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
|
|
| 934 |
++ target = x_table_lookup(profile, perms.xindex); |
|
| 935 |
++ if (!target) |
|
| 936 |
++ error = -ENOENT; |
|
| 937 |
++ else |
|
| 938 |
++ error = aa_replace_current_profile(target); |
|
| 939 |
++ } |
|
| 940 |
++ } else |
|
| 941 |
++ error = -EACCES; |
|
| 942 |
++ |
|
| 943 |
++audit: |
|
| 944 |
++ error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name, |
|
| 945 |
++ old_name, NULL, target ? target->base.name : NULL, |
|
| 946 |
++ 0, NULL, AA_MAY_PIVOTROOT, &perms, info, error); |
|
| 947 |
++ aa_put_profile(target); |
|
| 948 |
++ kfree(old_buffer); |
|
| 949 |
++ kfree(new_buffer); |
|
| 950 |
++ |
|
| 951 |
++ return error; |
|
| 952 |
++} |
|
| 953 |
+-- |
|
| 954 |
+2.7.4 |
|
| 955 |
+ |
| ... | ... |
@@ -2,7 +2,7 @@ |
| 2 | 2 |
Summary: Kernel |
| 3 | 3 |
Name: linux-aws |
| 4 | 4 |
Version: 4.9.111 |
| 5 |
-Release: 4%{?kat_build:.%kat_build}%{?dist}
|
|
| 5 |
+Release: 5%{?kat_build:.%kat_build}%{?dist}
|
|
| 6 | 6 |
License: GPLv2 |
| 7 | 7 |
URL: http://www.kernel.org/ |
| 8 | 8 |
Group: System Environment/Kernel |
| ... | ... |
@@ -85,6 +85,12 @@ Patch62: 0151-ipv6-prevent-speculative-execution.patch |
| 85 | 85 |
Patch64: 0153-net-mpls-prevent-speculative-execution.patch |
| 86 | 86 |
Patch65: 0154-udf-prevent-speculative-execution.patch |
| 87 | 87 |
Patch66: 0155-userns-prevent-speculative-execution.patch |
| 88 |
+ |
|
| 89 |
+# Out-of-tree patches from AppArmor: |
|
| 90 |
+Patch71: 0001-UBUNTU-SAUCE-AppArmor-basic-networking-rules.patch |
|
| 91 |
+Patch72: 0002-apparmor-Fix-quieting-of-audit-messages-for-network-.patch |
|
| 92 |
+Patch73: 0003-UBUNTU-SAUCE-apparmor-Add-the-ability-to-mediate-mou.patch |
|
| 93 |
+ |
|
| 88 | 94 |
# Amazon AWS |
| 89 | 95 |
Patch101: 0002-lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch |
| 90 | 96 |
Patch102: 0009-bump-the-default-TTL-to-255.patch |
| ... | ... |
@@ -263,6 +269,10 @@ This package contains the 'perf' performance analysis tools for Linux kernel. |
| 263 | 263 |
%patch65 -p1 |
| 264 | 264 |
%patch66 -p1 |
| 265 | 265 |
|
| 266 |
+%patch71 -p1 |
|
| 267 |
+%patch72 -p1 |
|
| 268 |
+%patch73 -p1 |
|
| 269 |
+ |
|
| 266 | 270 |
%patch101 -p1 |
| 267 | 271 |
%patch102 -p1 |
| 268 | 272 |
%patch103 -p1 |
| ... | ... |
@@ -467,6 +477,8 @@ ln -sf %{name}-%{uname_r}.cfg /boot/photon.cfg
|
| 467 | 467 |
/usr/share/doc/* |
| 468 | 468 |
|
| 469 | 469 |
%changelog |
| 470 |
+* Thu Jul 19 2018 Srivatsa S. Bhat <srivatsa@csail.mit.edu> 4.9.111-5 |
|
| 471 |
+- Apply out-of-tree patches needed for AppArmor. |
|
| 470 | 472 |
* Thu Jul 17 2018 Srinidhi Rao <srinidhir@vmware.com> 4.9.111-4 |
| 471 | 473 |
- Fix CVE-2018-10322 |
| 472 | 474 |
* Thu Jul 12 2018 Srinidhi Rao <srinidhir@vmware.com> 4.9.111-3 |
| ... | ... |
@@ -2,7 +2,7 @@ |
| 2 | 2 |
Summary: Kernel |
| 3 | 3 |
Name: linux-secure |
| 4 | 4 |
Version: 4.9.111 |
| 5 |
-Release: 3%{?kat_build:.%kat_build}%{?dist}
|
|
| 5 |
+Release: 4%{?kat_build:.%kat_build}%{?dist}
|
|
| 6 | 6 |
License: GPLv2 |
| 7 | 7 |
URL: http://www.kernel.org/ |
| 8 | 8 |
Group: System Environment/Kernel |
| ... | ... |
@@ -92,6 +92,10 @@ Patch64: 0153-net-mpls-prevent-speculative-execution.patch |
| 92 | 92 |
Patch65: 0154-udf-prevent-speculative-execution.patch |
| 93 | 93 |
Patch66: 0155-userns-prevent-speculative-execution.patch |
| 94 | 94 |
|
| 95 |
+# Out-of-tree patches from AppArmor: |
|
| 96 |
+Patch71: 0001-UBUNTU-SAUCE-AppArmor-basic-networking-rules.patch |
|
| 97 |
+Patch72: 0002-apparmor-Fix-quieting-of-audit-messages-for-network-.patch |
|
| 98 |
+Patch73: 0003-UBUNTU-SAUCE-apparmor-Add-the-ability-to-mediate-mou.patch |
|
| 95 | 99 |
|
| 96 | 100 |
# NSX requirements (should be removed) |
| 97 | 101 |
Patch99: LKCM.patch |
| ... | ... |
@@ -232,6 +236,10 @@ EOF |
| 232 | 232 |
%patch65 -p1 |
| 233 | 233 |
%patch66 -p1 |
| 234 | 234 |
|
| 235 |
+%patch71 -p1 |
|
| 236 |
+%patch72 -p1 |
|
| 237 |
+%patch73 -p1 |
|
| 238 |
+ |
|
| 235 | 239 |
# secure |
| 236 | 240 |
%patch13 -p1 |
| 237 | 241 |
%patch14 -p1 |
| ... | ... |
@@ -362,6 +370,8 @@ ln -sf linux-%{uname_r}.cfg /boot/photon.cfg
|
| 362 | 362 |
/usr/src/linux-headers-%{uname_r}
|
| 363 | 363 |
|
| 364 | 364 |
%changelog |
| 365 |
+* Thu Jul 19 2018 Srivatsa S. Bhat <srivatsa@csail.mit.edu> 4.9.111-4 |
|
| 366 |
+- Apply out-of-tree patches needed for AppArmor. |
|
| 365 | 367 |
* Thu Jul 17 2018 Srinidhi Rao <srinidhir@vmware.com> 4.9.111-3 |
| 366 | 368 |
- Fix CVE-2018-10322 |
| 367 | 369 |
* Thu Jul 12 2018 Srinidhi Rao <srinidhir@vmware.com> 4.9.111-2 |
| ... | ... |
@@ -2,7 +2,7 @@ |
| 2 | 2 |
Summary: Kernel |
| 3 | 3 |
Name: linux |
| 4 | 4 |
Version: 4.9.111 |
| 5 |
-Release: 4%{?kat_build:.%kat_build}%{?dist}
|
|
| 5 |
+Release: 5%{?kat_build:.%kat_build}%{?dist}
|
|
| 6 | 6 |
License: GPLv2 |
| 7 | 7 |
URL: http://www.kernel.org/ |
| 8 | 8 |
Group: System Environment/Kernel |
| ... | ... |
@@ -91,6 +91,10 @@ Patch64: 0153-net-mpls-prevent-speculative-execution.patch |
| 91 | 91 |
Patch65: 0154-udf-prevent-speculative-execution.patch |
| 92 | 92 |
Patch66: 0155-userns-prevent-speculative-execution.patch |
| 93 | 93 |
|
| 94 |
+# Out-of-tree patches from AppArmor: |
|
| 95 |
+Patch71: 0001-UBUNTU-SAUCE-AppArmor-basic-networking-rules.patch |
|
| 96 |
+Patch72: 0002-apparmor-Fix-quieting-of-audit-messages-for-network-.patch |
|
| 97 |
+Patch73: 0003-UBUNTU-SAUCE-apparmor-Add-the-ability-to-mediate-mou.patch |
|
| 94 | 98 |
|
| 95 | 99 |
%if 0%{?kat_build:1}
|
| 96 | 100 |
Patch1000: %{kat_build}.patch
|
| ... | ... |
@@ -223,6 +227,9 @@ This package contains the 'perf' performance analysis tools for Linux kernel. |
| 223 | 223 |
%patch65 -p1 |
| 224 | 224 |
%patch66 -p1 |
| 225 | 225 |
|
| 226 |
+%patch71 -p1 |
|
| 227 |
+%patch72 -p1 |
|
| 228 |
+%patch73 -p1 |
|
| 226 | 229 |
|
| 227 | 230 |
%if 0%{?kat_build:1}
|
| 228 | 231 |
%patch1000 -p1 |
| ... | ... |
@@ -390,6 +397,8 @@ ln -sf %{name}-%{uname_r}.cfg /boot/photon.cfg
|
| 390 | 390 |
/usr/share/doc/* |
| 391 | 391 |
|
| 392 | 392 |
%changelog |
| 393 |
+* Thu Jul 19 2018 Srivatsa S. Bhat <srivatsa@csail.mit.edu> 4.9.111-5 |
|
| 394 |
+- Apply out-of-tree patches needed for AppArmor. |
|
| 393 | 395 |
* Thu Jul 17 2018 Srinidhi Rao <srinidhir@vmware.com> 4.9.111-4 |
| 394 | 396 |
- Fix CVE-2018-10322 |
| 395 | 397 |
* Thu Jul 12 2018 Srinidhi Rao <srinidhir@vmware.com> 4.9.111-3 |