Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'apparmor-pr-2017-09-22' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor

Pull apparmor updates from John Johansen:
"This is the apparmor pull request, similar to SELinux and seccomp.

It's the same series that I was sent to James' security tree + one
regression fix that was found after the series was sent to James and
would have been sent for v4.14-rc2.

Features:
- in preparation for secid mapping add support for absolute root view
based labels
- add base infastructure for socket mediation
- add mount mediation
- add signal mediation

minor cleanups and changes:
- be defensive, ensure unconfined profiles have dfas initialized
- add more debug asserts to apparmorfs
- enable policy unpacking to audit different reasons for failure
- cleanup conditional check for label in label_print
- Redundant condition: prev_ns. in [label.c:1498]

Bug Fixes:
- fix regression in apparmorfs DAC access permissions
- fix build failure on sparc caused by undeclared signals
- fix sparse report of incorrect type assignment when freeing label proxies
- fix race condition in null profile creation
- Fix an error code in aafs_create()
- Fix logical error in verify_header()
- Fix shadowed local variable in unpack_trans_table()"

* tag 'apparmor-pr-2017-09-22' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
apparmor: fix apparmorfs DAC access permissions
apparmor: fix build failure on sparc caused by undeclared signals
apparmor: fix incorrect type assignment when freeing proxies
apparmor: ensure unconfined profiles have dfas initialized
apparmor: fix race condition in null profile creation
apparmor: move new_null_profile to after profile lookup fns()
apparmor: add base infastructure for socket mediation
apparmor: add more debug asserts to apparmorfs
apparmor: make policy_unpack able to audit different info messages
apparmor: add support for absolute root view based labels
apparmor: cleanup conditional check for label in label_print
apparmor: add mount mediation
apparmor: add the ability to mediate signals
apparmor: Redundant condition: prev_ns. in [label.c:1498]
apparmor: Fix an error code in aafs_create()
apparmor: Fix logical error in verify_header()
apparmor: Fix shadowed local variable in unpack_trans_table()

+2088 -137
+1
security/apparmor/.gitignore
··· 1 1 # 2 2 # Generated include files 3 3 # 4 + net_names.h 4 5 capability_names.h 5 6 rlim_names.h
+41 -2
security/apparmor/Makefile
··· 4 4 5 5 apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ 6 6 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ 7 - resource.o secid.o file.o policy_ns.o label.o 7 + resource.o secid.o file.o policy_ns.o label.o mount.o net.o 8 8 apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o 9 9 10 - clean-files := capability_names.h rlim_names.h 10 + clean-files := capability_names.h rlim_names.h net_names.h 11 11 12 + # Build a lower case string table of address family names 13 + # Transform lines from 14 + # #define AF_LOCAL 1 /* POSIX name for AF_UNIX */ 15 + # #define AF_INET 2 /* Internet IP Protocol */ 16 + # to 17 + # [1] = "local", 18 + # [2] = "inet", 19 + # 20 + # and build the securityfs entries for the mapping. 21 + # Transforms lines from 22 + # #define AF_INET 2 /* Internet IP Protocol */ 23 + # to 24 + # #define AA_SFS_AF_MASK "local inet" 25 + quiet_cmd_make-af = GEN $@ 26 + cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\ 27 + sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \ 28 + 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\ 29 + echo "};" >> $@ ;\ 30 + printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\ 31 + sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \ 32 + 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\ 33 + $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ 34 + 35 + # Build a lower case string table of sock type names 36 + # Transform lines from 37 + # SOCK_STREAM = 1, 38 + # to 39 + # [1] = "stream", 40 + quiet_cmd_make-sock = GEN $@ 41 + cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\ 42 + sed $^ >>$@ -r -n \ 43 + -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\ 44 + echo "};" >> $@ 12 45 13 46 # Build a lower case string table of capability names 14 47 # Transforms lines from ··· 94 61 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ 95 62 96 63 $(obj)/capability.o : $(obj)/capability_names.h 64 + $(obj)/net.o : $(obj)/net_names.h 97 65 $(obj)/resource.o : $(obj)/rlim_names.h 98 66 $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ 99 67 $(src)/Makefile ··· 102 68 $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \ 103 69 $(src)/Makefile 104 70 $(call cmd,make-rlim) 71 + $(obj)/net_names.h : $(srctree)/include/linux/socket.h \ 72 + $(srctree)/include/linux/net.h \ 73 + $(src)/Makefile 74 + $(call cmd,make-af) 75 + $(call cmd,make-sock)
+39 -6
security/apparmor/apparmorfs.c
··· 32 32 #include "include/audit.h" 33 33 #include "include/context.h" 34 34 #include "include/crypto.h" 35 + #include "include/ipc.h" 35 36 #include "include/policy_ns.h" 36 37 #include "include/label.h" 37 38 #include "include/policy.h" ··· 249 248 250 249 inode_lock(dir); 251 250 dentry = lookup_one_len(name, parent, strlen(name)); 252 - if (IS_ERR(dentry)) 251 + if (IS_ERR(dentry)) { 252 + error = PTR_ERR(dentry); 253 253 goto fail_lock; 254 + } 254 255 255 256 if (d_really_is_positive(dentry)) { 256 257 error = -EEXIST; ··· 1446 1443 { 1447 1444 int i; 1448 1445 1446 + AA_BUG(!old); 1447 + AA_BUG(!new); 1448 + AA_BUG(!mutex_is_locked(&profiles_ns(old)->lock)); 1449 + 1449 1450 for (i = 0; i < AAFS_PROF_SIZEOF; i++) { 1450 1451 new->dents[i] = old->dents[i]; 1451 1452 if (new->dents[i]) ··· 1512 1505 struct aa_profile *child; 1513 1506 struct dentry *dent = NULL, *dir; 1514 1507 int error; 1508 + 1509 + AA_BUG(!profile); 1510 + AA_BUG(!mutex_is_locked(&profiles_ns(profile)->lock)); 1515 1511 1516 1512 if (!parent) { 1517 1513 struct aa_profile *p; ··· 1741 1731 1742 1732 if (!ns) 1743 1733 return; 1734 + AA_BUG(!mutex_is_locked(&ns->lock)); 1744 1735 1745 1736 list_for_each_entry(child, &ns->base.profiles, base.list) 1746 1737 __aafs_profile_rmdir(child); ··· 1914 1903 { 1915 1904 struct aa_ns *parent, *next; 1916 1905 1906 + AA_BUG(!root); 1907 + AA_BUG(!ns); 1908 + AA_BUG(ns != root && !mutex_is_locked(&ns->parent->lock)); 1909 + 1917 1910 /* is next namespace a child */ 1918 1911 if (!list_empty(&ns->sub_ns)) { 1919 1912 next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list); ··· 1952 1937 static struct aa_profile *__first_profile(struct aa_ns *root, 1953 1938 struct aa_ns *ns) 1954 1939 { 1940 + AA_BUG(!root); 1941 + AA_BUG(ns && !mutex_is_locked(&ns->lock)); 1942 + 1955 1943 for (; ns; ns = __next_ns(root, ns)) { 1956 1944 if (!list_empty(&ns->base.profiles)) 1957 1945 return list_first_entry(&ns->base.profiles, ··· 1976 1958 { 1977 1959 struct aa_profile *parent; 1978 1960 struct aa_ns *ns = p->ns; 1961 + 1962 + AA_BUG(!mutex_is_locked(&profiles_ns(p)->lock)); 1979 1963 1980 1964 /* is next profile a child */ 1981 1965 if (!list_empty(&p->base.profiles)) ··· 2147 2127 { } 2148 2128 }; 2149 2129 2130 + static struct aa_sfs_entry aa_sfs_entry_signal[] = { 2131 + AA_SFS_FILE_STRING("mask", AA_SFS_SIG_MASK), 2132 + { } 2133 + }; 2134 + 2150 2135 static struct aa_sfs_entry aa_sfs_entry_domain[] = { 2151 2136 AA_SFS_FILE_BOOLEAN("change_hat", 1), 2152 2137 AA_SFS_FILE_BOOLEAN("change_hatv", 1), ··· 2176 2151 { } 2177 2152 }; 2178 2153 2154 + static struct aa_sfs_entry aa_sfs_entry_mount[] = { 2155 + AA_SFS_FILE_STRING("mask", "mount umount pivot_root"), 2156 + { } 2157 + }; 2158 + 2179 2159 static struct aa_sfs_entry aa_sfs_entry_ns[] = { 2180 2160 AA_SFS_FILE_BOOLEAN("profile", 1), 2181 - AA_SFS_FILE_BOOLEAN("pivot_root", 1), 2161 + AA_SFS_FILE_BOOLEAN("pivot_root", 0), 2182 2162 { } 2183 2163 }; 2184 2164 ··· 2202 2172 AA_SFS_DIR("policy", aa_sfs_entry_policy), 2203 2173 AA_SFS_DIR("domain", aa_sfs_entry_domain), 2204 2174 AA_SFS_DIR("file", aa_sfs_entry_file), 2175 + AA_SFS_DIR("network", aa_sfs_entry_network), 2176 + AA_SFS_DIR("mount", aa_sfs_entry_mount), 2205 2177 AA_SFS_DIR("namespaces", aa_sfs_entry_ns), 2206 2178 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), 2207 2179 AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit), 2208 2180 AA_SFS_DIR("caps", aa_sfs_entry_caps), 2209 2181 AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), 2182 + AA_SFS_DIR("signal", aa_sfs_entry_signal), 2210 2183 AA_SFS_DIR("query", aa_sfs_entry_query), 2211 2184 { } 2212 2185 }; 2213 2186 2214 2187 static struct aa_sfs_entry aa_sfs_entry_apparmor[] = { 2215 - AA_SFS_FILE_FOPS(".access", 0640, &aa_sfs_access), 2188 + AA_SFS_FILE_FOPS(".access", 0666, &aa_sfs_access), 2216 2189 AA_SFS_FILE_FOPS(".stacked", 0444, &seq_ns_stacked_fops), 2217 2190 AA_SFS_FILE_FOPS(".ns_stacked", 0444, &seq_ns_nsstacked_fops), 2218 - AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops), 2219 - AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops), 2220 - AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops), 2191 + AA_SFS_FILE_FOPS(".ns_level", 0444, &seq_ns_level_fops), 2192 + AA_SFS_FILE_FOPS(".ns_name", 0444, &seq_ns_name_fops), 2193 + AA_SFS_FILE_FOPS("profiles", 0444, &aa_sfs_profiles_fops), 2221 2194 AA_SFS_DIR("features", aa_sfs_entry_features), 2222 2195 { } 2223 2196 };
+2 -2
security/apparmor/domain.c
··· 374 374 * 375 375 * Returns: refcounted label, or NULL on failure (MAYBE NULL) 376 376 */ 377 - static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, 378 - const char **name) 377 + struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, 378 + const char **name) 379 379 { 380 380 struct aa_label *label = NULL; 381 381 u32 xtype = xindex & AA_X_TYPE_MASK;
+30
security/apparmor/file.c
··· 21 21 #include "include/context.h" 22 22 #include "include/file.h" 23 23 #include "include/match.h" 24 + #include "include/net.h" 24 25 #include "include/path.h" 25 26 #include "include/policy.h" 26 27 #include "include/label.h" ··· 567 566 return error; 568 567 } 569 568 569 + static int __file_sock_perm(const char *op, struct aa_label *label, 570 + struct aa_label *flabel, struct file *file, 571 + u32 request, u32 denied) 572 + { 573 + struct socket *sock = (struct socket *) file->private_data; 574 + int error; 575 + 576 + AA_BUG(!sock); 577 + 578 + /* revalidation due to label out of date. No revocation at this time */ 579 + if (!denied && aa_label_is_subset(flabel, label)) 580 + return 0; 581 + 582 + /* TODO: improve to skip profiles cached in flabel */ 583 + error = aa_sock_file_perm(label, op, request, sock); 584 + if (denied) { 585 + /* TODO: improve to skip profiles checked above */ 586 + /* check every profile in file label to is cached */ 587 + last_error(error, aa_sock_file_perm(flabel, op, request, sock)); 588 + } 589 + if (!error) 590 + update_file_ctx(file_ctx(file), label, request); 591 + 592 + return error; 593 + } 594 + 570 595 /** 571 596 * aa_file_perm - do permission revalidation check & audit for @file 572 597 * @op: operation being checked ··· 637 610 error = __file_path_perm(op, label, flabel, file, request, 638 611 denied); 639 612 613 + else if (S_ISSOCK(file_inode(file)->i_mode)) 614 + error = __file_sock_perm(op, label, flabel, file, request, 615 + denied); 640 616 done: 641 617 rcu_read_unlock(); 642 618
+2
security/apparmor/include/apparmor.h
··· 27 27 #define AA_CLASS_NET 4 28 28 #define AA_CLASS_RLIMITS 5 29 29 #define AA_CLASS_DOMAIN 6 30 + #define AA_CLASS_MOUNT 7 30 31 #define AA_CLASS_PTRACE 9 32 + #define AA_CLASS_SIGNAL 10 31 33 #define AA_CLASS_LABEL 16 32 34 33 35 #define AA_CLASS_LAST AA_CLASS_LABEL
+30 -9
security/apparmor/include/audit.h
··· 71 71 #define OP_FMPROT "file_mprotect" 72 72 #define OP_INHERIT "file_inherit" 73 73 74 + #define OP_PIVOTROOT "pivotroot" 75 + #define OP_MOUNT "mount" 76 + #define OP_UMOUNT "umount" 77 + 74 78 #define OP_CREATE "create" 75 79 #define OP_POST_CREATE "post_create" 76 80 #define OP_BIND "bind" ··· 90 86 #define OP_SHUTDOWN "socket_shutdown" 91 87 92 88 #define OP_PTRACE "ptrace" 89 + #define OP_SIGNAL "signal" 93 90 94 91 #define OP_EXEC "exec" 95 92 ··· 121 116 /* these entries require a custom callback fn */ 122 117 struct { 123 118 struct aa_label *peer; 124 - struct { 125 - const char *target; 126 - kuid_t ouid; 127 - } fs; 119 + union { 120 + struct { 121 + kuid_t ouid; 122 + const char *target; 123 + } fs; 124 + struct { 125 + int type, protocol; 126 + struct sock *peer_sk; 127 + void *addr; 128 + int addrlen; 129 + } net; 130 + int signal; 131 + struct { 132 + int rlim; 133 + unsigned long max; 134 + } rlim; 135 + }; 128 136 }; 129 137 struct { 130 - const char *name; 131 - long pos; 138 + struct aa_profile *profile; 132 139 const char *ns; 140 + long pos; 133 141 } iface; 134 142 struct { 135 - int rlim; 136 - unsigned long max; 137 - } rlim; 143 + const char *src_name; 144 + const char *type; 145 + const char *trans; 146 + const char *data; 147 + unsigned long flags; 148 + } mnt; 138 149 }; 139 150 }; 140 151
+5
security/apparmor/include/domain.h
··· 15 15 #include <linux/binfmts.h> 16 16 #include <linux/types.h> 17 17 18 + #include "label.h" 19 + 18 20 #ifndef __AA_DOMAIN_H 19 21 #define __AA_DOMAIN_H 20 22 ··· 30 28 #define AA_CHANGE_CHILD 2 31 29 #define AA_CHANGE_ONEXEC 4 32 30 #define AA_CHANGE_STACK 8 31 + 32 + struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, 33 + const char **name); 33 34 34 35 int apparmor_bprm_set_creds(struct linux_binprm *bprm); 35 36
+6
security/apparmor/include/ipc.h
··· 27 27 28 28 #define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \ 29 29 AA_MAY_BE_READ | AA_MAY_BE_TRACED) 30 + #define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE) 31 + 32 + #define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \ 33 + "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ 34 + "xcpu xfsz vtalrm prof winch io pwr sys emt lost" 30 35 31 36 int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, 32 37 u32 request); 38 + int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig); 33 39 34 40 #endif /* __AA_IPC_H */
+1
security/apparmor/include/label.h
··· 310 310 #define FLAG_SHOW_MODE 1 311 311 #define FLAG_VIEW_SUBNS 2 312 312 #define FLAG_HIDDEN_UNCONFINED 4 313 + #define FLAG_ABS_ROOT 8 313 314 int aa_label_snxprint(char *str, size_t size, struct aa_ns *view, 314 315 struct aa_label *label, int flags); 315 316 int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label,
+54
security/apparmor/include/mount.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor file mediation function definitions. 5 + * 6 + * Copyright 2017 Canonical Ltd. 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License as 10 + * published by the Free Software Foundation, version 2 of the 11 + * License. 12 + */ 13 + 14 + #ifndef __AA_MOUNT_H 15 + #define __AA_MOUNT_H 16 + 17 + #include <linux/fs.h> 18 + #include <linux/path.h> 19 + 20 + #include "domain.h" 21 + #include "policy.h" 22 + 23 + /* mount perms */ 24 + #define AA_MAY_PIVOTROOT 0x01 25 + #define AA_MAY_MOUNT 0x02 26 + #define AA_MAY_UMOUNT 0x04 27 + #define AA_AUDIT_DATA 0x40 28 + #define AA_MNT_CONT_MATCH 0x40 29 + 30 + #define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN) 31 + 32 + int aa_remount(struct aa_label *label, const struct path *path, 33 + unsigned long flags, void *data); 34 + 35 + int aa_bind_mount(struct aa_label *label, const struct path *path, 36 + const char *old_name, unsigned long flags); 37 + 38 + 39 + int aa_mount_change_type(struct aa_label *label, const struct path *path, 40 + unsigned long flags); 41 + 42 + int aa_move_mount(struct aa_label *label, const struct path *path, 43 + const char *old_name); 44 + 45 + int aa_new_mount(struct aa_label *label, const char *dev_name, 46 + const struct path *path, const char *type, unsigned long flags, 47 + void *data); 48 + 49 + int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags); 50 + 51 + int aa_pivotroot(struct aa_label *label, const struct path *old_path, 52 + const struct path *new_path); 53 + 54 + #endif /* __AA_MOUNT_H */
+114
security/apparmor/include/net.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor network mediation definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2017 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_NET_H 16 + #define __AA_NET_H 17 + 18 + #include <net/sock.h> 19 + #include <linux/path.h> 20 + 21 + #include "apparmorfs.h" 22 + #include "label.h" 23 + #include "perms.h" 24 + #include "policy.h" 25 + 26 + #define AA_MAY_SEND AA_MAY_WRITE 27 + #define AA_MAY_RECEIVE AA_MAY_READ 28 + 29 + #define AA_MAY_SHUTDOWN AA_MAY_DELETE 30 + 31 + #define AA_MAY_CONNECT AA_MAY_OPEN 32 + #define AA_MAY_ACCEPT 0x00100000 33 + 34 + #define AA_MAY_BIND 0x00200000 35 + #define AA_MAY_LISTEN 0x00400000 36 + 37 + #define AA_MAY_SETOPT 0x01000000 38 + #define AA_MAY_GETOPT 0x02000000 39 + 40 + #define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \ 41 + AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN | \ 42 + AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \ 43 + AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT) 44 + 45 + #define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \ 46 + AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\ 47 + AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD | \ 48 + AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK | \ 49 + AA_MAY_MPROT) 50 + 51 + #define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \ 52 + AA_MAY_ACCEPT) 53 + struct aa_sk_ctx { 54 + struct aa_label *label; 55 + struct aa_label *peer; 56 + struct path path; 57 + }; 58 + 59 + #define SK_CTX(X) ((X)->sk_security) 60 + #define SOCK_ctx(X) SOCK_INODE(X)->i_security 61 + #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \ 62 + struct lsm_network_audit NAME ## _net = { .sk = (SK), \ 63 + .family = (F)}; \ 64 + DEFINE_AUDIT_DATA(NAME, \ 65 + ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \ 66 + LSM_AUDIT_DATA_NONE, \ 67 + OP); \ 68 + NAME.u.net = &(NAME ## _net); \ 69 + aad(&NAME)->net.type = (T); \ 70 + aad(&NAME)->net.protocol = (P) 71 + 72 + #define DEFINE_AUDIT_SK(NAME, OP, SK) \ 73 + DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \ 74 + (SK)->sk_protocol) 75 + 76 + /* struct aa_net - network confinement data 77 + * @allow: basic network families permissions 78 + * @audit: which network permissions to force audit 79 + * @quiet: which network permissions to quiet rejects 80 + */ 81 + struct aa_net { 82 + u16 allow[AF_MAX]; 83 + u16 audit[AF_MAX]; 84 + u16 quiet[AF_MAX]; 85 + }; 86 + 87 + 88 + extern struct aa_sfs_entry aa_sfs_entry_network[]; 89 + 90 + void audit_net_cb(struct audit_buffer *ab, void *va); 91 + int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, 92 + u32 request, u16 family, int type); 93 + int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, 94 + int type, int protocol); 95 + static inline int aa_profile_af_sk_perm(struct aa_profile *profile, 96 + struct common_audit_data *sa, 97 + u32 request, 98 + struct sock *sk) 99 + { 100 + return aa_profile_af_perm(profile, sa, request, sk->sk_family, 101 + sk->sk_type); 102 + } 103 + int aa_sk_perm(const char *op, u32 request, struct sock *sk); 104 + 105 + int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, 106 + struct socket *sock); 107 + 108 + 109 + static inline void aa_free_net_rules(struct aa_net *new) 110 + { 111 + /* NOP */ 112 + } 113 + 114 + #endif /* __AA_NET_H */
+3 -2
security/apparmor/include/perms.h
··· 135 135 136 136 137 137 void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask); 138 - void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask); 138 + void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names, 139 + u32 mask); 139 140 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 140 - u32 chrsmask, const char **names, u32 namesmask); 141 + u32 chrsmask, const char * const *names, u32 namesmask); 141 142 void aa_apply_modes_to_perms(struct aa_profile *profile, 142 143 struct aa_perms *perms); 143 144 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
+13
security/apparmor/include/policy.h
··· 30 30 #include "file.h" 31 31 #include "lib.h" 32 32 #include "label.h" 33 + #include "net.h" 33 34 #include "perms.h" 34 35 #include "resource.h" 35 36 ··· 112 111 * @policy: general match rules governing policy 113 112 * @file: The set of rules governing basic file access and domain transitions 114 113 * @caps: capabilities for the profile 114 + * @net: network controls for the profile 115 115 * @rlimits: rlimits for the profile 116 116 * 117 117 * @dents: dentries for the profiles file entries in apparmorfs ··· 150 148 struct aa_policydb policy; 151 149 struct aa_file_rules file; 152 150 struct aa_caps caps; 151 + struct aa_net net; 153 152 struct aa_rlimit rlimits; 154 153 155 154 struct aa_loaddata *rawdata; ··· 221 218 return aa_dfa_match_len(profile->policy.dfa, 222 219 profile->policy.start[0], &class, 1); 223 220 return 0; 221 + } 222 + 223 + static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile, 224 + u16 AF) { 225 + unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET); 226 + u16 be_af = cpu_to_be16(AF); 227 + 228 + if (!state) 229 + return 0; 230 + return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2); 224 231 } 225 232 226 233 /**
+98
security/apparmor/include/sig_names.h
··· 1 + #include <linux/signal.h> 2 + 3 + #define SIGUNKNOWN 0 4 + #define MAXMAPPED_SIG 35 5 + /* provide a mapping of arch signal to internal signal # for mediation 6 + * those that are always an alias SIGCLD for SIGCLHD and SIGPOLL for SIGIO 7 + * map to the same entry those that may/or may not get a separate entry 8 + */ 9 + static const int sig_map[MAXMAPPED_SIG] = { 10 + [0] = MAXMAPPED_SIG, /* existence test */ 11 + [SIGHUP] = 1, 12 + [SIGINT] = 2, 13 + [SIGQUIT] = 3, 14 + [SIGILL] = 4, 15 + [SIGTRAP] = 5, /* -, 5, - */ 16 + [SIGABRT] = 6, /* SIGIOT: -, 6, - */ 17 + [SIGBUS] = 7, /* 10, 7, 10 */ 18 + [SIGFPE] = 8, 19 + [SIGKILL] = 9, 20 + [SIGUSR1] = 10, /* 30, 10, 16 */ 21 + [SIGSEGV] = 11, 22 + [SIGUSR2] = 12, /* 31, 12, 17 */ 23 + [SIGPIPE] = 13, 24 + [SIGALRM] = 14, 25 + [SIGTERM] = 15, 26 + #ifdef SIGSTKFLT 27 + [SIGSTKFLT] = 16, /* -, 16, - */ 28 + #endif 29 + [SIGCHLD] = 17, /* 20, 17, 18. SIGCHLD -, -, 18 */ 30 + [SIGCONT] = 18, /* 19, 18, 25 */ 31 + [SIGSTOP] = 19, /* 17, 19, 23 */ 32 + [SIGTSTP] = 20, /* 18, 20, 24 */ 33 + [SIGTTIN] = 21, /* 21, 21, 26 */ 34 + [SIGTTOU] = 22, /* 22, 22, 27 */ 35 + [SIGURG] = 23, /* 16, 23, 21 */ 36 + [SIGXCPU] = 24, /* 24, 24, 30 */ 37 + [SIGXFSZ] = 25, /* 25, 25, 31 */ 38 + [SIGVTALRM] = 26, /* 26, 26, 28 */ 39 + [SIGPROF] = 27, /* 27, 27, 29 */ 40 + [SIGWINCH] = 28, /* 28, 28, 20 */ 41 + [SIGIO] = 29, /* SIGPOLL: 23, 29, 22 */ 42 + [SIGPWR] = 30, /* 29, 30, 19. SIGINFO 29, -, - */ 43 + #ifdef SIGSYS 44 + [SIGSYS] = 31, /* 12, 31, 12. often SIG LOST/UNUSED */ 45 + #endif 46 + #ifdef SIGEMT 47 + [SIGEMT] = 32, /* 7, - , 7 */ 48 + #endif 49 + #if defined(SIGLOST) && SIGPWR != SIGLOST /* sparc */ 50 + [SIGLOST] = 33, /* unused on Linux */ 51 + #endif 52 + #if defined(SIGUNUSED) && \ 53 + defined(SIGLOST) && defined(SIGSYS) && SIGLOST != SIGSYS 54 + [SIGUNUSED] = 34, /* -, 31, - */ 55 + #endif 56 + }; 57 + 58 + /* this table is ordered post sig_map[sig] mapping */ 59 + static const char *const sig_names[MAXMAPPED_SIG + 1] = { 60 + "unknown", 61 + "hup", 62 + "int", 63 + "quit", 64 + "ill", 65 + "trap", 66 + "abrt", 67 + "bus", 68 + "fpe", 69 + "kill", 70 + "usr1", 71 + "segv", 72 + "usr2", 73 + "pipe", 74 + "alrm", 75 + "term", 76 + "stkflt", 77 + "chld", 78 + "cont", 79 + "stop", 80 + "stp", 81 + "ttin", 82 + "ttou", 83 + "urg", 84 + "xcpu", 85 + "xfsz", 86 + "vtalrm", 87 + "prof", 88 + "winch", 89 + "io", 90 + "pwr", 91 + "sys", 92 + "emt", 93 + "lost", 94 + "unused", 95 + 96 + "exists", /* always last existence test mapped to MAXMAPPED_SIG */ 97 + }; 98 +
+99
security/apparmor/ipc.c
··· 20 20 #include "include/context.h" 21 21 #include "include/policy.h" 22 22 #include "include/ipc.h" 23 + #include "include/sig_names.h" 23 24 24 25 /** 25 26 * audit_ptrace_mask - convert mask to permission string ··· 122 121 } 123 122 124 123 124 + static inline int map_signal_num(int sig) 125 + { 126 + if (sig > SIGRTMAX) 127 + return SIGUNKNOWN; 128 + else if (sig >= SIGRTMIN) 129 + return sig - SIGRTMIN + 128; /* rt sigs mapped to 128 */ 130 + else if (sig <= MAXMAPPED_SIG) 131 + return sig_map[sig]; 132 + return SIGUNKNOWN; 133 + } 134 + 135 + /** 136 + * audit_file_mask - convert mask to permission string 137 + * @buffer: buffer to write string to (NOT NULL) 138 + * @mask: permission mask to convert 139 + */ 140 + static void audit_signal_mask(struct audit_buffer *ab, u32 mask) 141 + { 142 + if (mask & MAY_READ) 143 + audit_log_string(ab, "receive"); 144 + if (mask & MAY_WRITE) 145 + audit_log_string(ab, "send"); 146 + } 147 + 148 + /** 149 + * audit_cb - call back for signal specific audit fields 150 + * @ab: audit_buffer (NOT NULL) 151 + * @va: audit struct to audit values of (NOT NULL) 152 + */ 153 + static void audit_signal_cb(struct audit_buffer *ab, void *va) 154 + { 155 + struct common_audit_data *sa = va; 156 + 157 + if (aad(sa)->request & AA_SIGNAL_PERM_MASK) { 158 + audit_log_format(ab, " requested_mask="); 159 + audit_signal_mask(ab, aad(sa)->request); 160 + if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) { 161 + audit_log_format(ab, " denied_mask="); 162 + audit_signal_mask(ab, aad(sa)->denied); 163 + } 164 + } 165 + if (aad(sa)->signal <= MAXMAPPED_SIG) 166 + audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]); 167 + else 168 + audit_log_format(ab, " signal=rtmin+%d", 169 + aad(sa)->signal - 128); 170 + audit_log_format(ab, " peer="); 171 + aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 172 + FLAGS_NONE, GFP_ATOMIC); 173 + } 174 + 175 + /* TODO: update to handle compound name&name2, conditionals */ 176 + static void profile_match_signal(struct aa_profile *profile, const char *label, 177 + int signal, struct aa_perms *perms) 178 + { 179 + unsigned int state; 180 + 181 + /* TODO: secondary cache check <profile, profile, perm> */ 182 + state = aa_dfa_next(profile->policy.dfa, 183 + profile->policy.start[AA_CLASS_SIGNAL], 184 + signal); 185 + state = aa_dfa_match(profile->policy.dfa, state, label); 186 + aa_compute_perms(profile->policy.dfa, state, perms); 187 + } 188 + 189 + static int profile_signal_perm(struct aa_profile *profile, 190 + struct aa_profile *peer, u32 request, 191 + struct common_audit_data *sa) 192 + { 193 + struct aa_perms perms; 194 + 195 + if (profile_unconfined(profile) || 196 + !PROFILE_MEDIATES(profile, AA_CLASS_SIGNAL)) 197 + return 0; 198 + 199 + aad(sa)->peer = &peer->label; 200 + profile_match_signal(profile, peer->base.hname, aad(sa)->signal, 201 + &perms); 202 + aa_apply_modes_to_perms(profile, &perms); 203 + return aa_check_perms(profile, &perms, request, sa, audit_signal_cb); 204 + } 205 + 206 + static int aa_signal_cross_perm(struct aa_profile *sender, 207 + struct aa_profile *target, 208 + struct common_audit_data *sa) 209 + { 210 + return xcheck(profile_signal_perm(sender, target, MAY_WRITE, sa), 211 + profile_signal_perm(target, sender, MAY_READ, sa)); 212 + } 213 + 214 + int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig) 215 + { 216 + DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SIGNAL); 217 + 218 + aad(&sa)->signal = map_signal_num(sig); 219 + return xcheck_labels_profiles(sender, target, aa_signal_cross_perm, 220 + &sa); 221 + }
+19 -17
security/apparmor/label.c
··· 49 49 /* p->label will not updated any more as p is dead */ 50 50 aa_put_label(rcu_dereference_protected(proxy->label, true)); 51 51 memset(proxy, 0, sizeof(*proxy)); 52 - proxy->label = (struct aa_label *) PROXY_POISON; 52 + RCU_INIT_POINTER(proxy->label, (struct aa_label *)PROXY_POISON); 53 53 kfree(proxy); 54 54 } 55 55 } ··· 1450 1450 * cached label name is present and visible 1451 1451 * @label->hname only exists if label is namespace hierachical 1452 1452 */ 1453 - static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label) 1453 + static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label, 1454 + int flags) 1454 1455 { 1455 - if (label->hname && labels_ns(label) == ns) 1456 + if (label->hname && (!ns || labels_ns(label) == ns) && 1457 + !(flags & ~FLAG_SHOW_MODE)) 1456 1458 return true; 1457 1459 1458 1460 return false; ··· 1497 1495 view = profiles_ns(profile); 1498 1496 1499 1497 if (view != profile->ns && 1500 - (!prev_ns || (prev_ns && *prev_ns != profile->ns))) { 1498 + (!prev_ns || (*prev_ns != profile->ns))) { 1501 1499 if (prev_ns) 1502 1500 *prev_ns = profile->ns; 1503 1501 ns_name = aa_ns_name(view, profile->ns, ··· 1607 1605 AA_BUG(!str && size != 0); 1608 1606 AA_BUG(!label); 1609 1607 1610 - if (!ns) 1608 + if (flags & FLAG_ABS_ROOT) { 1609 + ns = root_ns; 1610 + len = snprintf(str, size, "="); 1611 + update_for_len(total, len, size, str); 1612 + } else if (!ns) { 1611 1613 ns = labels_ns(label); 1614 + } 1612 1615 1613 1616 label_for_each(i, label, profile) { 1614 1617 if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) { ··· 1717 1710 AA_BUG(!ab); 1718 1711 AA_BUG(!label); 1719 1712 1720 - if (!ns) 1721 - ns = labels_ns(label); 1722 - 1723 - if (!use_label_hname(ns, label) || display_mode(ns, label, flags)) { 1713 + if (!use_label_hname(ns, label, flags) || 1714 + display_mode(ns, label, flags)) { 1724 1715 len = aa_label_asxprint(&name, ns, label, flags, gfp); 1725 1716 if (len == -1) { 1726 1717 AA_DEBUG("label print error"); ··· 1743 1738 AA_BUG(!f); 1744 1739 AA_BUG(!label); 1745 1740 1746 - if (!ns) 1747 - ns = labels_ns(label); 1748 - 1749 - if (!use_label_hname(ns, label)) { 1741 + if (!use_label_hname(ns, label, flags)) { 1750 1742 char *str; 1751 1743 int len; 1752 1744 ··· 1766 1764 { 1767 1765 AA_BUG(!label); 1768 1766 1769 - if (!ns) 1770 - ns = labels_ns(label); 1771 - 1772 - if (!use_label_hname(ns, label)) { 1767 + if (!use_label_hname(ns, label, flags)) { 1773 1768 char *str; 1774 1769 int len; 1775 1770 ··· 1873 1874 if (*str == '&') 1874 1875 str++; 1875 1876 } 1877 + if (*str == '=') 1878 + base = &root_ns->unconfined->label; 1879 + 1876 1880 error = vec_setup(profile, vec, len, gfp); 1877 1881 if (error) 1878 1882 return ERR_PTR(error);
+3 -2
security/apparmor/lib.c
··· 211 211 *str = '\0'; 212 212 } 213 213 214 - void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask) 214 + void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names, 215 + u32 mask) 215 216 { 216 217 const char *fmt = "%s"; 217 218 unsigned int i, perm = 1; ··· 230 229 } 231 230 232 231 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 233 - u32 chrsmask, const char **names, u32 namesmask) 232 + u32 chrsmask, const char * const *names, u32 namesmask) 234 233 { 235 234 char str[33]; 236 235
+472
security/apparmor/lsm.c
··· 33 33 #include "include/context.h" 34 34 #include "include/file.h" 35 35 #include "include/ipc.h" 36 + #include "include/net.h" 36 37 #include "include/path.h" 37 38 #include "include/label.h" 38 39 #include "include/policy.h" 39 40 #include "include/policy_ns.h" 40 41 #include "include/procattr.h" 42 + #include "include/mount.h" 41 43 42 44 /* Flag indicating whether initialization completed */ 43 45 int apparmor_initialized; ··· 513 511 !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0); 514 512 } 515 513 514 + static int apparmor_sb_mount(const char *dev_name, const struct path *path, 515 + const char *type, unsigned long flags, void *data) 516 + { 517 + struct aa_label *label; 518 + int error = 0; 519 + 520 + /* Discard magic */ 521 + if ((flags & MS_MGC_MSK) == MS_MGC_VAL) 522 + flags &= ~MS_MGC_MSK; 523 + 524 + flags &= ~AA_MS_IGNORE_MASK; 525 + 526 + label = __begin_current_label_crit_section(); 527 + if (!unconfined(label)) { 528 + if (flags & MS_REMOUNT) 529 + error = aa_remount(label, path, flags, data); 530 + else if (flags & MS_BIND) 531 + error = aa_bind_mount(label, path, dev_name, flags); 532 + else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | 533 + MS_UNBINDABLE)) 534 + error = aa_mount_change_type(label, path, flags); 535 + else if (flags & MS_MOVE) 536 + error = aa_move_mount(label, path, dev_name); 537 + else 538 + error = aa_new_mount(label, dev_name, path, type, 539 + flags, data); 540 + } 541 + __end_current_label_crit_section(label); 542 + 543 + return error; 544 + } 545 + 546 + static int apparmor_sb_umount(struct vfsmount *mnt, int flags) 547 + { 548 + struct aa_label *label; 549 + int error = 0; 550 + 551 + label = __begin_current_label_crit_section(); 552 + if (!unconfined(label)) 553 + error = aa_umount(label, mnt, flags); 554 + __end_current_label_crit_section(label); 555 + 556 + return error; 557 + } 558 + 559 + static int apparmor_sb_pivotroot(const struct path *old_path, 560 + const struct path *new_path) 561 + { 562 + struct aa_label *label; 563 + int error = 0; 564 + 565 + label = aa_get_current_label(); 566 + if (!unconfined(label)) 567 + error = aa_pivotroot(label, old_path, new_path); 568 + aa_put_label(label); 569 + 570 + return error; 571 + } 572 + 516 573 static int apparmor_getprocattr(struct task_struct *task, char *name, 517 574 char **value) 518 575 { ··· 717 656 return error; 718 657 } 719 658 659 + static int apparmor_task_kill(struct task_struct *target, struct siginfo *info, 660 + int sig, u32 secid) 661 + { 662 + struct aa_label *cl, *tl; 663 + int error; 664 + 665 + if (secid) 666 + /* TODO: after secid to label mapping is done. 667 + * Dealing with USB IO specific behavior 668 + */ 669 + return 0; 670 + cl = __begin_current_label_crit_section(); 671 + tl = aa_get_task_label(target); 672 + error = aa_may_signal(cl, tl, sig); 673 + aa_put_label(tl); 674 + __end_current_label_crit_section(cl); 675 + 676 + return error; 677 + } 678 + 679 + /** 680 + * apparmor_sk_alloc_security - allocate and attach the sk_security field 681 + */ 682 + static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags) 683 + { 684 + struct aa_sk_ctx *ctx; 685 + 686 + ctx = kzalloc(sizeof(*ctx), flags); 687 + if (!ctx) 688 + return -ENOMEM; 689 + 690 + SK_CTX(sk) = ctx; 691 + 692 + return 0; 693 + } 694 + 695 + /** 696 + * apparmor_sk_free_security - free the sk_security field 697 + */ 698 + static void apparmor_sk_free_security(struct sock *sk) 699 + { 700 + struct aa_sk_ctx *ctx = SK_CTX(sk); 701 + 702 + SK_CTX(sk) = NULL; 703 + aa_put_label(ctx->label); 704 + aa_put_label(ctx->peer); 705 + path_put(&ctx->path); 706 + kfree(ctx); 707 + } 708 + 709 + /** 710 + * apparmor_clone_security - clone the sk_security field 711 + */ 712 + static void apparmor_sk_clone_security(const struct sock *sk, 713 + struct sock *newsk) 714 + { 715 + struct aa_sk_ctx *ctx = SK_CTX(sk); 716 + struct aa_sk_ctx *new = SK_CTX(newsk); 717 + 718 + new->label = aa_get_label(ctx->label); 719 + new->peer = aa_get_label(ctx->peer); 720 + new->path = ctx->path; 721 + path_get(&new->path); 722 + } 723 + 724 + static int aa_sock_create_perm(struct aa_label *label, int family, int type, 725 + int protocol) 726 + { 727 + AA_BUG(!label); 728 + AA_BUG(in_interrupt()); 729 + 730 + return aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, family, type, 731 + protocol); 732 + } 733 + 734 + 735 + /** 736 + * apparmor_socket_create - check perms before creating a new socket 737 + */ 738 + static int apparmor_socket_create(int family, int type, int protocol, int kern) 739 + { 740 + struct aa_label *label; 741 + int error = 0; 742 + 743 + label = begin_current_label_crit_section(); 744 + if (!(kern || unconfined(label))) 745 + error = aa_sock_create_perm(label, family, type, protocol); 746 + end_current_label_crit_section(label); 747 + 748 + return error; 749 + } 750 + 751 + /** 752 + * apparmor_socket_post_create - setup the per-socket security struct 753 + * 754 + * Note: 755 + * - kernel sockets currently labeled unconfined but we may want to 756 + * move to a special kernel label 757 + * - socket may not have sk here if created with sock_create_lite or 758 + * sock_alloc. These should be accept cases which will be handled in 759 + * sock_graft. 760 + */ 761 + static int apparmor_socket_post_create(struct socket *sock, int family, 762 + int type, int protocol, int kern) 763 + { 764 + struct aa_label *label; 765 + 766 + if (kern) { 767 + struct aa_ns *ns = aa_get_current_ns(); 768 + 769 + label = aa_get_label(ns_unconfined(ns)); 770 + aa_put_ns(ns); 771 + } else 772 + label = aa_get_current_label(); 773 + 774 + if (sock->sk) { 775 + struct aa_sk_ctx *ctx = SK_CTX(sock->sk); 776 + 777 + aa_put_label(ctx->label); 778 + ctx->label = aa_get_label(label); 779 + } 780 + aa_put_label(label); 781 + 782 + return 0; 783 + } 784 + 785 + /** 786 + * apparmor_socket_bind - check perms before bind addr to socket 787 + */ 788 + static int apparmor_socket_bind(struct socket *sock, 789 + struct sockaddr *address, int addrlen) 790 + { 791 + AA_BUG(!sock); 792 + AA_BUG(!sock->sk); 793 + AA_BUG(!address); 794 + AA_BUG(in_interrupt()); 795 + 796 + return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk); 797 + } 798 + 799 + /** 800 + * apparmor_socket_connect - check perms before connecting @sock to @address 801 + */ 802 + static int apparmor_socket_connect(struct socket *sock, 803 + struct sockaddr *address, int addrlen) 804 + { 805 + AA_BUG(!sock); 806 + AA_BUG(!sock->sk); 807 + AA_BUG(!address); 808 + AA_BUG(in_interrupt()); 809 + 810 + return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk); 811 + } 812 + 813 + /** 814 + * apparmor_socket_list - check perms before allowing listen 815 + */ 816 + static int apparmor_socket_listen(struct socket *sock, int backlog) 817 + { 818 + AA_BUG(!sock); 819 + AA_BUG(!sock->sk); 820 + AA_BUG(in_interrupt()); 821 + 822 + return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk); 823 + } 824 + 825 + /** 826 + * apparmor_socket_accept - check perms before accepting a new connection. 827 + * 828 + * Note: while @newsock is created and has some information, the accept 829 + * has not been done. 830 + */ 831 + static int apparmor_socket_accept(struct socket *sock, struct socket *newsock) 832 + { 833 + AA_BUG(!sock); 834 + AA_BUG(!sock->sk); 835 + AA_BUG(!newsock); 836 + AA_BUG(in_interrupt()); 837 + 838 + return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk); 839 + } 840 + 841 + static int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock, 842 + struct msghdr *msg, int size) 843 + { 844 + AA_BUG(!sock); 845 + AA_BUG(!sock->sk); 846 + AA_BUG(!msg); 847 + AA_BUG(in_interrupt()); 848 + 849 + return aa_sk_perm(op, request, sock->sk); 850 + } 851 + 852 + /** 853 + * apparmor_socket_sendmsg - check perms before sending msg to another socket 854 + */ 855 + static int apparmor_socket_sendmsg(struct socket *sock, 856 + struct msghdr *msg, int size) 857 + { 858 + return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size); 859 + } 860 + 861 + /** 862 + * apparmor_socket_recvmsg - check perms before receiving a message 863 + */ 864 + static int apparmor_socket_recvmsg(struct socket *sock, 865 + struct msghdr *msg, int size, int flags) 866 + { 867 + return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size); 868 + } 869 + 870 + /* revaliation, get/set attr, shutdown */ 871 + static int aa_sock_perm(const char *op, u32 request, struct socket *sock) 872 + { 873 + AA_BUG(!sock); 874 + AA_BUG(!sock->sk); 875 + AA_BUG(in_interrupt()); 876 + 877 + return aa_sk_perm(op, request, sock->sk); 878 + } 879 + 880 + /** 881 + * apparmor_socket_getsockname - check perms before getting the local address 882 + */ 883 + static int apparmor_socket_getsockname(struct socket *sock) 884 + { 885 + return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock); 886 + } 887 + 888 + /** 889 + * apparmor_socket_getpeername - check perms before getting remote address 890 + */ 891 + static int apparmor_socket_getpeername(struct socket *sock) 892 + { 893 + return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock); 894 + } 895 + 896 + /* revaliation, get/set attr, opt */ 897 + static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock, 898 + int level, int optname) 899 + { 900 + AA_BUG(!sock); 901 + AA_BUG(!sock->sk); 902 + AA_BUG(in_interrupt()); 903 + 904 + return aa_sk_perm(op, request, sock->sk); 905 + } 906 + 907 + /** 908 + * apparmor_getsockopt - check perms before getting socket options 909 + */ 910 + static int apparmor_socket_getsockopt(struct socket *sock, int level, 911 + int optname) 912 + { 913 + return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock, 914 + level, optname); 915 + } 916 + 917 + /** 918 + * apparmor_setsockopt - check perms before setting socket options 919 + */ 920 + static int apparmor_socket_setsockopt(struct socket *sock, int level, 921 + int optname) 922 + { 923 + return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock, 924 + level, optname); 925 + } 926 + 927 + /** 928 + * apparmor_socket_shutdown - check perms before shutting down @sock conn 929 + */ 930 + static int apparmor_socket_shutdown(struct socket *sock, int how) 931 + { 932 + return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock); 933 + } 934 + 935 + /** 936 + * apparmor_socket_sock_recv_skb - check perms before associating skb to sk 937 + * 938 + * Note: can not sleep may be called with locks held 939 + * 940 + * dont want protocol specific in __skb_recv_datagram() 941 + * to deny an incoming connection socket_sock_rcv_skb() 942 + */ 943 + static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 944 + { 945 + return 0; 946 + } 947 + 948 + 949 + static struct aa_label *sk_peer_label(struct sock *sk) 950 + { 951 + struct aa_sk_ctx *ctx = SK_CTX(sk); 952 + 953 + if (ctx->peer) 954 + return ctx->peer; 955 + 956 + return ERR_PTR(-ENOPROTOOPT); 957 + } 958 + 959 + /** 960 + * apparmor_socket_getpeersec_stream - get security context of peer 961 + * 962 + * Note: for tcp only valid if using ipsec or cipso on lan 963 + */ 964 + static int apparmor_socket_getpeersec_stream(struct socket *sock, 965 + char __user *optval, 966 + int __user *optlen, 967 + unsigned int len) 968 + { 969 + char *name; 970 + int slen, error = 0; 971 + struct aa_label *label; 972 + struct aa_label *peer; 973 + 974 + label = begin_current_label_crit_section(); 975 + peer = sk_peer_label(sock->sk); 976 + if (IS_ERR(peer)) { 977 + error = PTR_ERR(peer); 978 + goto done; 979 + } 980 + slen = aa_label_asxprint(&name, labels_ns(label), peer, 981 + FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | 982 + FLAG_HIDDEN_UNCONFINED, GFP_KERNEL); 983 + /* don't include terminating \0 in slen, it breaks some apps */ 984 + if (slen < 0) { 985 + error = -ENOMEM; 986 + } else { 987 + if (slen > len) { 988 + error = -ERANGE; 989 + } else if (copy_to_user(optval, name, slen)) { 990 + error = -EFAULT; 991 + goto out; 992 + } 993 + if (put_user(slen, optlen)) 994 + error = -EFAULT; 995 + out: 996 + kfree(name); 997 + 998 + } 999 + 1000 + done: 1001 + end_current_label_crit_section(label); 1002 + 1003 + return error; 1004 + } 1005 + 1006 + /** 1007 + * apparmor_socket_getpeersec_dgram - get security label of packet 1008 + * @sock: the peer socket 1009 + * @skb: packet data 1010 + * @secid: pointer to where to put the secid of the packet 1011 + * 1012 + * Sets the netlabel socket state on sk from parent 1013 + */ 1014 + static int apparmor_socket_getpeersec_dgram(struct socket *sock, 1015 + struct sk_buff *skb, u32 *secid) 1016 + 1017 + { 1018 + /* TODO: requires secid support */ 1019 + return -ENOPROTOOPT; 1020 + } 1021 + 1022 + /** 1023 + * apparmor_sock_graft - Initialize newly created socket 1024 + * @sk: child sock 1025 + * @parent: parent socket 1026 + * 1027 + * Note: could set off of SOCK_CTX(parent) but need to track inode and we can 1028 + * just set sk security information off of current creating process label 1029 + * Labeling of sk for accept case - probably should be sock based 1030 + * instead of task, because of the case where an implicitly labeled 1031 + * socket is shared by different tasks. 1032 + */ 1033 + static void apparmor_sock_graft(struct sock *sk, struct socket *parent) 1034 + { 1035 + struct aa_sk_ctx *ctx = SK_CTX(sk); 1036 + 1037 + if (!ctx->label) 1038 + ctx->label = aa_get_current_label(); 1039 + } 1040 + 720 1041 static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { 721 1042 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), 722 1043 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), 723 1044 LSM_HOOK_INIT(capget, apparmor_capget), 724 1045 LSM_HOOK_INIT(capable, apparmor_capable), 1046 + 1047 + LSM_HOOK_INIT(sb_mount, apparmor_sb_mount), 1048 + LSM_HOOK_INIT(sb_umount, apparmor_sb_umount), 1049 + LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot), 725 1050 726 1051 LSM_HOOK_INIT(path_link, apparmor_path_link), 727 1052 LSM_HOOK_INIT(path_unlink, apparmor_path_unlink), ··· 1133 686 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), 1134 687 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), 1135 688 689 + LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security), 690 + LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security), 691 + LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security), 692 + 693 + LSM_HOOK_INIT(socket_create, apparmor_socket_create), 694 + LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create), 695 + LSM_HOOK_INIT(socket_bind, apparmor_socket_bind), 696 + LSM_HOOK_INIT(socket_connect, apparmor_socket_connect), 697 + LSM_HOOK_INIT(socket_listen, apparmor_socket_listen), 698 + LSM_HOOK_INIT(socket_accept, apparmor_socket_accept), 699 + LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg), 700 + LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg), 701 + LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname), 702 + LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername), 703 + LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt), 704 + LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt), 705 + LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown), 706 + LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb), 707 + LSM_HOOK_INIT(socket_getpeersec_stream, 708 + apparmor_socket_getpeersec_stream), 709 + LSM_HOOK_INIT(socket_getpeersec_dgram, 710 + apparmor_socket_getpeersec_dgram), 711 + LSM_HOOK_INIT(sock_graft, apparmor_sock_graft), 712 + 1136 713 LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), 1137 714 LSM_HOOK_INIT(cred_free, apparmor_cred_free), 1138 715 LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare), ··· 1167 696 LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds), 1168 697 1169 698 LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit), 699 + LSM_HOOK_INIT(task_kill, apparmor_task_kill), 1170 700 }; 1171 701 1172 702 /*
+696
security/apparmor/mount.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor mediation of files 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2017 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/fs.h> 16 + #include <linux/mount.h> 17 + #include <linux/namei.h> 18 + 19 + #include "include/apparmor.h" 20 + #include "include/audit.h" 21 + #include "include/context.h" 22 + #include "include/domain.h" 23 + #include "include/file.h" 24 + #include "include/match.h" 25 + #include "include/mount.h" 26 + #include "include/path.h" 27 + #include "include/policy.h" 28 + 29 + 30 + static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags) 31 + { 32 + if (flags & MS_RDONLY) 33 + audit_log_format(ab, "ro"); 34 + else 35 + audit_log_format(ab, "rw"); 36 + if (flags & MS_NOSUID) 37 + audit_log_format(ab, ", nosuid"); 38 + if (flags & MS_NODEV) 39 + audit_log_format(ab, ", nodev"); 40 + if (flags & MS_NOEXEC) 41 + audit_log_format(ab, ", noexec"); 42 + if (flags & MS_SYNCHRONOUS) 43 + audit_log_format(ab, ", sync"); 44 + if (flags & MS_REMOUNT) 45 + audit_log_format(ab, ", remount"); 46 + if (flags & MS_MANDLOCK) 47 + audit_log_format(ab, ", mand"); 48 + if (flags & MS_DIRSYNC) 49 + audit_log_format(ab, ", dirsync"); 50 + if (flags & MS_NOATIME) 51 + audit_log_format(ab, ", noatime"); 52 + if (flags & MS_NODIRATIME) 53 + audit_log_format(ab, ", nodiratime"); 54 + if (flags & MS_BIND) 55 + audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind"); 56 + if (flags & MS_MOVE) 57 + audit_log_format(ab, ", move"); 58 + if (flags & MS_SILENT) 59 + audit_log_format(ab, ", silent"); 60 + if (flags & MS_POSIXACL) 61 + audit_log_format(ab, ", acl"); 62 + if (flags & MS_UNBINDABLE) 63 + audit_log_format(ab, flags & MS_REC ? ", runbindable" : 64 + ", unbindable"); 65 + if (flags & MS_PRIVATE) 66 + audit_log_format(ab, flags & MS_REC ? ", rprivate" : 67 + ", private"); 68 + if (flags & MS_SLAVE) 69 + audit_log_format(ab, flags & MS_REC ? ", rslave" : 70 + ", slave"); 71 + if (flags & MS_SHARED) 72 + audit_log_format(ab, flags & MS_REC ? ", rshared" : 73 + ", shared"); 74 + if (flags & MS_RELATIME) 75 + audit_log_format(ab, ", relatime"); 76 + if (flags & MS_I_VERSION) 77 + audit_log_format(ab, ", iversion"); 78 + if (flags & MS_STRICTATIME) 79 + audit_log_format(ab, ", strictatime"); 80 + if (flags & MS_NOUSER) 81 + audit_log_format(ab, ", nouser"); 82 + } 83 + 84 + /** 85 + * audit_cb - call back for mount specific audit fields 86 + * @ab: audit_buffer (NOT NULL) 87 + * @va: audit struct to audit values of (NOT NULL) 88 + */ 89 + static void audit_cb(struct audit_buffer *ab, void *va) 90 + { 91 + struct common_audit_data *sa = va; 92 + 93 + if (aad(sa)->mnt.type) { 94 + audit_log_format(ab, " fstype="); 95 + audit_log_untrustedstring(ab, aad(sa)->mnt.type); 96 + } 97 + if (aad(sa)->mnt.src_name) { 98 + audit_log_format(ab, " srcname="); 99 + audit_log_untrustedstring(ab, aad(sa)->mnt.src_name); 100 + } 101 + if (aad(sa)->mnt.trans) { 102 + audit_log_format(ab, " trans="); 103 + audit_log_untrustedstring(ab, aad(sa)->mnt.trans); 104 + } 105 + if (aad(sa)->mnt.flags) { 106 + audit_log_format(ab, " flags=\""); 107 + audit_mnt_flags(ab, aad(sa)->mnt.flags); 108 + audit_log_format(ab, "\""); 109 + } 110 + if (aad(sa)->mnt.data) { 111 + audit_log_format(ab, " options="); 112 + audit_log_untrustedstring(ab, aad(sa)->mnt.data); 113 + } 114 + } 115 + 116 + /** 117 + * audit_mount - handle the auditing of mount operations 118 + * @profile: the profile being enforced (NOT NULL) 119 + * @op: operation being mediated (NOT NULL) 120 + * @name: name of object being mediated (MAYBE NULL) 121 + * @src_name: src_name of object being mediated (MAYBE_NULL) 122 + * @type: type of filesystem (MAYBE_NULL) 123 + * @trans: name of trans (MAYBE NULL) 124 + * @flags: filesystem idependent mount flags 125 + * @data: filesystem mount flags 126 + * @request: permissions requested 127 + * @perms: the permissions computed for the request (NOT NULL) 128 + * @info: extra information message (MAYBE NULL) 129 + * @error: 0 if operation allowed else failure error code 130 + * 131 + * Returns: %0 or error on failure 132 + */ 133 + static int audit_mount(struct aa_profile *profile, const char *op, 134 + const char *name, const char *src_name, 135 + const char *type, const char *trans, 136 + unsigned long flags, const void *data, u32 request, 137 + struct aa_perms *perms, const char *info, int error) 138 + { 139 + int audit_type = AUDIT_APPARMOR_AUTO; 140 + DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op); 141 + 142 + if (likely(!error)) { 143 + u32 mask = perms->audit; 144 + 145 + if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) 146 + mask = 0xffff; 147 + 148 + /* mask off perms that are not being force audited */ 149 + request &= mask; 150 + 151 + if (likely(!request)) 152 + return 0; 153 + audit_type = AUDIT_APPARMOR_AUDIT; 154 + } else { 155 + /* only report permissions that were denied */ 156 + request = request & ~perms->allow; 157 + 158 + if (request & perms->kill) 159 + audit_type = AUDIT_APPARMOR_KILL; 160 + 161 + /* quiet known rejects, assumes quiet and kill do not overlap */ 162 + if ((request & perms->quiet) && 163 + AUDIT_MODE(profile) != AUDIT_NOQUIET && 164 + AUDIT_MODE(profile) != AUDIT_ALL) 165 + request &= ~perms->quiet; 166 + 167 + if (!request) 168 + return error; 169 + } 170 + 171 + aad(&sa)->name = name; 172 + aad(&sa)->mnt.src_name = src_name; 173 + aad(&sa)->mnt.type = type; 174 + aad(&sa)->mnt.trans = trans; 175 + aad(&sa)->mnt.flags = flags; 176 + if (data && (perms->audit & AA_AUDIT_DATA)) 177 + aad(&sa)->mnt.data = data; 178 + aad(&sa)->info = info; 179 + aad(&sa)->error = error; 180 + 181 + return aa_audit(audit_type, profile, &sa, audit_cb); 182 + } 183 + 184 + /** 185 + * match_mnt_flags - Do an ordered match on mount flags 186 + * @dfa: dfa to match against 187 + * @state: state to start in 188 + * @flags: mount flags to match against 189 + * 190 + * Mount flags are encoded as an ordered match. This is done instead of 191 + * checking against a simple bitmask, to allow for logical operations 192 + * on the flags. 193 + * 194 + * Returns: next state after flags match 195 + */ 196 + static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state, 197 + unsigned long flags) 198 + { 199 + unsigned int i; 200 + 201 + for (i = 0; i <= 31 ; ++i) { 202 + if ((1 << i) & flags) 203 + state = aa_dfa_next(dfa, state, i + 1); 204 + } 205 + 206 + return state; 207 + } 208 + 209 + /** 210 + * compute_mnt_perms - compute mount permission associated with @state 211 + * @dfa: dfa to match against (NOT NULL) 212 + * @state: state match finished in 213 + * 214 + * Returns: mount permissions 215 + */ 216 + static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa, 217 + unsigned int state) 218 + { 219 + struct aa_perms perms; 220 + 221 + perms.kill = 0; 222 + perms.allow = dfa_user_allow(dfa, state); 223 + perms.audit = dfa_user_audit(dfa, state); 224 + perms.quiet = dfa_user_quiet(dfa, state); 225 + perms.xindex = dfa_user_xindex(dfa, state); 226 + 227 + return perms; 228 + } 229 + 230 + static const char * const mnt_info_table[] = { 231 + "match succeeded", 232 + "failed mntpnt match", 233 + "failed srcname match", 234 + "failed type match", 235 + "failed flags match", 236 + "failed data match" 237 + }; 238 + 239 + /* 240 + * Returns 0 on success else element that match failed in, this is the 241 + * index into the mnt_info_table above 242 + */ 243 + static int do_match_mnt(struct aa_dfa *dfa, unsigned int start, 244 + const char *mntpnt, const char *devname, 245 + const char *type, unsigned long flags, 246 + void *data, bool binary, struct aa_perms *perms) 247 + { 248 + unsigned int state; 249 + 250 + AA_BUG(!dfa); 251 + AA_BUG(!perms); 252 + 253 + state = aa_dfa_match(dfa, start, mntpnt); 254 + state = aa_dfa_null_transition(dfa, state); 255 + if (!state) 256 + return 1; 257 + 258 + if (devname) 259 + state = aa_dfa_match(dfa, state, devname); 260 + state = aa_dfa_null_transition(dfa, state); 261 + if (!state) 262 + return 2; 263 + 264 + if (type) 265 + state = aa_dfa_match(dfa, state, type); 266 + state = aa_dfa_null_transition(dfa, state); 267 + if (!state) 268 + return 3; 269 + 270 + state = match_mnt_flags(dfa, state, flags); 271 + if (!state) 272 + return 4; 273 + *perms = compute_mnt_perms(dfa, state); 274 + if (perms->allow & AA_MAY_MOUNT) 275 + return 0; 276 + 277 + /* only match data if not binary and the DFA flags data is expected */ 278 + if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) { 279 + state = aa_dfa_null_transition(dfa, state); 280 + if (!state) 281 + return 4; 282 + 283 + state = aa_dfa_match(dfa, state, data); 284 + if (!state) 285 + return 5; 286 + *perms = compute_mnt_perms(dfa, state); 287 + if (perms->allow & AA_MAY_MOUNT) 288 + return 0; 289 + } 290 + 291 + /* failed at end of flags match */ 292 + return 4; 293 + } 294 + 295 + 296 + static int path_flags(struct aa_profile *profile, const struct path *path) 297 + { 298 + AA_BUG(!profile); 299 + AA_BUG(!path); 300 + 301 + return profile->path_flags | 302 + (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0); 303 + } 304 + 305 + /** 306 + * match_mnt_path_str - handle path matching for mount 307 + * @profile: the confining profile 308 + * @mntpath: for the mntpnt (NOT NULL) 309 + * @buffer: buffer to be used to lookup mntpath 310 + * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR) 311 + * @type: string for the dev type (MAYBE NULL) 312 + * @flags: mount flags to match 313 + * @data: fs mount data (MAYBE NULL) 314 + * @binary: whether @data is binary 315 + * @devinfo: error str if (IS_ERR(@devname)) 316 + * 317 + * Returns: 0 on success else error 318 + */ 319 + static int match_mnt_path_str(struct aa_profile *profile, 320 + const struct path *mntpath, char *buffer, 321 + const char *devname, const char *type, 322 + unsigned long flags, void *data, bool binary, 323 + const char *devinfo) 324 + { 325 + struct aa_perms perms = { }; 326 + const char *mntpnt = NULL, *info = NULL; 327 + int pos, error; 328 + 329 + AA_BUG(!profile); 330 + AA_BUG(!mntpath); 331 + AA_BUG(!buffer); 332 + 333 + error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer, 334 + &mntpnt, &info, profile->disconnected); 335 + if (error) 336 + goto audit; 337 + if (IS_ERR(devname)) { 338 + error = PTR_ERR(devname); 339 + devname = NULL; 340 + info = devinfo; 341 + goto audit; 342 + } 343 + 344 + error = -EACCES; 345 + pos = do_match_mnt(profile->policy.dfa, 346 + profile->policy.start[AA_CLASS_MOUNT], 347 + mntpnt, devname, type, flags, data, binary, &perms); 348 + if (pos) { 349 + info = mnt_info_table[pos]; 350 + goto audit; 351 + } 352 + error = 0; 353 + 354 + audit: 355 + return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL, 356 + flags, data, AA_MAY_MOUNT, &perms, info, error); 357 + } 358 + 359 + /** 360 + * match_mnt - handle path matching for mount 361 + * @profile: the confining profile 362 + * @mntpath: for the mntpnt (NOT NULL) 363 + * @buffer: buffer to be used to lookup mntpath 364 + * @devpath: path devname/src_name (MAYBE NULL) 365 + * @devbuffer: buffer to be used to lookup devname/src_name 366 + * @type: string for the dev type (MAYBE NULL) 367 + * @flags: mount flags to match 368 + * @data: fs mount data (MAYBE NULL) 369 + * @binary: whether @data is binary 370 + * 371 + * Returns: 0 on success else error 372 + */ 373 + static int match_mnt(struct aa_profile *profile, const struct path *path, 374 + char *buffer, struct path *devpath, char *devbuffer, 375 + const char *type, unsigned long flags, void *data, 376 + bool binary) 377 + { 378 + const char *devname = NULL, *info = NULL; 379 + int error = -EACCES; 380 + 381 + AA_BUG(!profile); 382 + AA_BUG(devpath && !devbuffer); 383 + 384 + if (devpath) { 385 + error = aa_path_name(devpath, path_flags(profile, devpath), 386 + devbuffer, &devname, &info, 387 + profile->disconnected); 388 + if (error) 389 + devname = ERR_PTR(error); 390 + } 391 + 392 + return match_mnt_path_str(profile, path, buffer, devname, type, flags, 393 + data, binary, info); 394 + } 395 + 396 + int aa_remount(struct aa_label *label, const struct path *path, 397 + unsigned long flags, void *data) 398 + { 399 + struct aa_profile *profile; 400 + char *buffer = NULL; 401 + bool binary; 402 + int error; 403 + 404 + AA_BUG(!label); 405 + AA_BUG(!path); 406 + 407 + binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA; 408 + 409 + get_buffers(buffer); 410 + error = fn_for_each_confined(label, profile, 411 + match_mnt(profile, path, buffer, NULL, NULL, NULL, 412 + flags, data, binary)); 413 + put_buffers(buffer); 414 + 415 + return error; 416 + } 417 + 418 + int aa_bind_mount(struct aa_label *label, const struct path *path, 419 + const char *dev_name, unsigned long flags) 420 + { 421 + struct aa_profile *profile; 422 + char *buffer = NULL, *old_buffer = NULL; 423 + struct path old_path; 424 + int error; 425 + 426 + AA_BUG(!label); 427 + AA_BUG(!path); 428 + 429 + if (!dev_name || !*dev_name) 430 + return -EINVAL; 431 + 432 + flags &= MS_REC | MS_BIND; 433 + 434 + error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path); 435 + if (error) 436 + return error; 437 + 438 + get_buffers(buffer, old_buffer); 439 + error = fn_for_each_confined(label, profile, 440 + match_mnt(profile, path, buffer, &old_path, old_buffer, 441 + NULL, flags, NULL, false)); 442 + put_buffers(buffer, old_buffer); 443 + path_put(&old_path); 444 + 445 + return error; 446 + } 447 + 448 + int aa_mount_change_type(struct aa_label *label, const struct path *path, 449 + unsigned long flags) 450 + { 451 + struct aa_profile *profile; 452 + char *buffer = NULL; 453 + int error; 454 + 455 + AA_BUG(!label); 456 + AA_BUG(!path); 457 + 458 + /* These are the flags allowed by do_change_type() */ 459 + flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE | 460 + MS_UNBINDABLE); 461 + 462 + get_buffers(buffer); 463 + error = fn_for_each_confined(label, profile, 464 + match_mnt(profile, path, buffer, NULL, NULL, NULL, 465 + flags, NULL, false)); 466 + put_buffers(buffer); 467 + 468 + return error; 469 + } 470 + 471 + int aa_move_mount(struct aa_label *label, const struct path *path, 472 + const char *orig_name) 473 + { 474 + struct aa_profile *profile; 475 + char *buffer = NULL, *old_buffer = NULL; 476 + struct path old_path; 477 + int error; 478 + 479 + AA_BUG(!label); 480 + AA_BUG(!path); 481 + 482 + if (!orig_name || !*orig_name) 483 + return -EINVAL; 484 + 485 + error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path); 486 + if (error) 487 + return error; 488 + 489 + get_buffers(buffer, old_buffer); 490 + error = fn_for_each_confined(label, profile, 491 + match_mnt(profile, path, buffer, &old_path, old_buffer, 492 + NULL, MS_MOVE, NULL, false)); 493 + put_buffers(buffer, old_buffer); 494 + path_put(&old_path); 495 + 496 + return error; 497 + } 498 + 499 + int aa_new_mount(struct aa_label *label, const char *dev_name, 500 + const struct path *path, const char *type, unsigned long flags, 501 + void *data) 502 + { 503 + struct aa_profile *profile; 504 + char *buffer = NULL, *dev_buffer = NULL; 505 + bool binary = true; 506 + int error; 507 + int requires_dev = 0; 508 + struct path tmp_path, *dev_path = NULL; 509 + 510 + AA_BUG(!label); 511 + AA_BUG(!path); 512 + 513 + if (type) { 514 + struct file_system_type *fstype; 515 + 516 + fstype = get_fs_type(type); 517 + if (!fstype) 518 + return -ENODEV; 519 + binary = fstype->fs_flags & FS_BINARY_MOUNTDATA; 520 + requires_dev = fstype->fs_flags & FS_REQUIRES_DEV; 521 + put_filesystem(fstype); 522 + 523 + if (requires_dev) { 524 + if (!dev_name || !*dev_name) 525 + return -ENOENT; 526 + 527 + error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path); 528 + if (error) 529 + return error; 530 + dev_path = &tmp_path; 531 + } 532 + } 533 + 534 + get_buffers(buffer, dev_buffer); 535 + if (dev_path) { 536 + error = fn_for_each_confined(label, profile, 537 + match_mnt(profile, path, buffer, dev_path, dev_buffer, 538 + type, flags, data, binary)); 539 + } else { 540 + error = fn_for_each_confined(label, profile, 541 + match_mnt_path_str(profile, path, buffer, dev_name, 542 + type, flags, data, binary, NULL)); 543 + } 544 + put_buffers(buffer, dev_buffer); 545 + if (dev_path) 546 + path_put(dev_path); 547 + 548 + return error; 549 + } 550 + 551 + static int profile_umount(struct aa_profile *profile, struct path *path, 552 + char *buffer) 553 + { 554 + struct aa_perms perms = { }; 555 + const char *name = NULL, *info = NULL; 556 + unsigned int state; 557 + int error; 558 + 559 + AA_BUG(!profile); 560 + AA_BUG(!path); 561 + 562 + error = aa_path_name(path, path_flags(profile, path), buffer, &name, 563 + &info, profile->disconnected); 564 + if (error) 565 + goto audit; 566 + 567 + state = aa_dfa_match(profile->policy.dfa, 568 + profile->policy.start[AA_CLASS_MOUNT], 569 + name); 570 + perms = compute_mnt_perms(profile->policy.dfa, state); 571 + if (AA_MAY_UMOUNT & ~perms.allow) 572 + error = -EACCES; 573 + 574 + audit: 575 + return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL, 576 + AA_MAY_UMOUNT, &perms, info, error); 577 + } 578 + 579 + int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags) 580 + { 581 + struct aa_profile *profile; 582 + char *buffer = NULL; 583 + int error; 584 + struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; 585 + 586 + AA_BUG(!label); 587 + AA_BUG(!mnt); 588 + 589 + get_buffers(buffer); 590 + error = fn_for_each_confined(label, profile, 591 + profile_umount(profile, &path, buffer)); 592 + put_buffers(buffer); 593 + 594 + return error; 595 + } 596 + 597 + /* helper fn for transition on pivotroot 598 + * 599 + * Returns: label for transition or ERR_PTR. Does not return NULL 600 + */ 601 + static struct aa_label *build_pivotroot(struct aa_profile *profile, 602 + const struct path *new_path, 603 + char *new_buffer, 604 + const struct path *old_path, 605 + char *old_buffer) 606 + { 607 + const char *old_name, *new_name = NULL, *info = NULL; 608 + const char *trans_name = NULL; 609 + struct aa_perms perms = { }; 610 + unsigned int state; 611 + int error; 612 + 613 + AA_BUG(!profile); 614 + AA_BUG(!new_path); 615 + AA_BUG(!old_path); 616 + 617 + if (profile_unconfined(profile)) 618 + return aa_get_newest_label(&profile->label); 619 + 620 + error = aa_path_name(old_path, path_flags(profile, old_path), 621 + old_buffer, &old_name, &info, 622 + profile->disconnected); 623 + if (error) 624 + goto audit; 625 + error = aa_path_name(new_path, path_flags(profile, new_path), 626 + new_buffer, &new_name, &info, 627 + profile->disconnected); 628 + if (error) 629 + goto audit; 630 + 631 + error = -EACCES; 632 + state = aa_dfa_match(profile->policy.dfa, 633 + profile->policy.start[AA_CLASS_MOUNT], 634 + new_name); 635 + state = aa_dfa_null_transition(profile->policy.dfa, state); 636 + state = aa_dfa_match(profile->policy.dfa, state, old_name); 637 + perms = compute_mnt_perms(profile->policy.dfa, state); 638 + 639 + if (AA_MAY_PIVOTROOT & perms.allow) 640 + error = 0; 641 + 642 + audit: 643 + error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name, 644 + NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT, 645 + &perms, info, error); 646 + if (error) 647 + return ERR_PTR(error); 648 + 649 + return aa_get_newest_label(&profile->label); 650 + } 651 + 652 + int aa_pivotroot(struct aa_label *label, const struct path *old_path, 653 + const struct path *new_path) 654 + { 655 + struct aa_profile *profile; 656 + struct aa_label *target = NULL; 657 + char *old_buffer = NULL, *new_buffer = NULL, *info = NULL; 658 + int error; 659 + 660 + AA_BUG(!label); 661 + AA_BUG(!old_path); 662 + AA_BUG(!new_path); 663 + 664 + get_buffers(old_buffer, new_buffer); 665 + target = fn_label_build(label, profile, GFP_ATOMIC, 666 + build_pivotroot(profile, new_path, new_buffer, 667 + old_path, old_buffer)); 668 + if (!target) { 669 + info = "label build failed"; 670 + error = -ENOMEM; 671 + goto fail; 672 + } else if (!IS_ERR(target)) { 673 + error = aa_replace_current_label(target); 674 + if (error) { 675 + /* TODO: audit target */ 676 + aa_put_label(target); 677 + goto out; 678 + } 679 + } else 680 + /* already audited error */ 681 + error = PTR_ERR(target); 682 + out: 683 + put_buffers(old_buffer, new_buffer); 684 + 685 + return error; 686 + 687 + fail: 688 + /* TODO: add back in auditing of new_name and old_name */ 689 + error = fn_for_each(label, profile, 690 + audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */, 691 + NULL /* old_name */, 692 + NULL, NULL, 693 + 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info, 694 + error)); 695 + goto out; 696 + }
+184
security/apparmor/net.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor network mediation 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2017 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include "include/apparmor.h" 16 + #include "include/audit.h" 17 + #include "include/context.h" 18 + #include "include/label.h" 19 + #include "include/net.h" 20 + #include "include/policy.h" 21 + 22 + #include "net_names.h" 23 + 24 + 25 + struct aa_sfs_entry aa_sfs_entry_network[] = { 26 + AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK), 27 + { } 28 + }; 29 + 30 + static const char * const net_mask_names[] = { 31 + "unknown", 32 + "send", 33 + "receive", 34 + "unknown", 35 + 36 + "create", 37 + "shutdown", 38 + "connect", 39 + "unknown", 40 + 41 + "setattr", 42 + "getattr", 43 + "setcred", 44 + "getcred", 45 + 46 + "chmod", 47 + "chown", 48 + "chgrp", 49 + "lock", 50 + 51 + "mmap", 52 + "mprot", 53 + "unknown", 54 + "unknown", 55 + 56 + "accept", 57 + "bind", 58 + "listen", 59 + "unknown", 60 + 61 + "setopt", 62 + "getopt", 63 + "unknown", 64 + "unknown", 65 + 66 + "unknown", 67 + "unknown", 68 + "unknown", 69 + "unknown", 70 + }; 71 + 72 + 73 + /* audit callback for net specific fields */ 74 + void audit_net_cb(struct audit_buffer *ab, void *va) 75 + { 76 + struct common_audit_data *sa = va; 77 + 78 + audit_log_format(ab, " family="); 79 + if (address_family_names[sa->u.net->family]) 80 + audit_log_string(ab, address_family_names[sa->u.net->family]); 81 + else 82 + audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family); 83 + audit_log_format(ab, " sock_type="); 84 + if (sock_type_names[aad(sa)->net.type]) 85 + audit_log_string(ab, sock_type_names[aad(sa)->net.type]); 86 + else 87 + audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type); 88 + audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol); 89 + 90 + if (aad(sa)->request & NET_PERMS_MASK) { 91 + audit_log_format(ab, " requested_mask="); 92 + aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0, 93 + net_mask_names, NET_PERMS_MASK); 94 + 95 + if (aad(sa)->denied & NET_PERMS_MASK) { 96 + audit_log_format(ab, " denied_mask="); 97 + aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0, 98 + net_mask_names, NET_PERMS_MASK); 99 + } 100 + } 101 + if (aad(sa)->peer) { 102 + audit_log_format(ab, " peer="); 103 + aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 104 + FLAGS_NONE, GFP_ATOMIC); 105 + } 106 + } 107 + 108 + 109 + /* Generic af perm */ 110 + int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, 111 + u32 request, u16 family, int type) 112 + { 113 + struct aa_perms perms = { }; 114 + 115 + AA_BUG(family >= AF_MAX); 116 + AA_BUG(type < 0 || type >= SOCK_MAX); 117 + 118 + if (profile_unconfined(profile)) 119 + return 0; 120 + 121 + perms.allow = (profile->net.allow[family] & (1 << type)) ? 122 + ALL_PERMS_MASK : 0; 123 + perms.audit = (profile->net.audit[family] & (1 << type)) ? 124 + ALL_PERMS_MASK : 0; 125 + perms.quiet = (profile->net.quiet[family] & (1 << type)) ? 126 + ALL_PERMS_MASK : 0; 127 + aa_apply_modes_to_perms(profile, &perms); 128 + 129 + return aa_check_perms(profile, &perms, request, sa, audit_net_cb); 130 + } 131 + 132 + int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, 133 + int type, int protocol) 134 + { 135 + struct aa_profile *profile; 136 + DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol); 137 + 138 + return fn_for_each_confined(label, profile, 139 + aa_profile_af_perm(profile, &sa, request, family, 140 + type)); 141 + } 142 + 143 + static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, 144 + struct sock *sk) 145 + { 146 + struct aa_profile *profile; 147 + DEFINE_AUDIT_SK(sa, op, sk); 148 + 149 + AA_BUG(!label); 150 + AA_BUG(!sk); 151 + 152 + if (unconfined(label)) 153 + return 0; 154 + 155 + return fn_for_each_confined(label, profile, 156 + aa_profile_af_sk_perm(profile, &sa, request, sk)); 157 + } 158 + 159 + int aa_sk_perm(const char *op, u32 request, struct sock *sk) 160 + { 161 + struct aa_label *label; 162 + int error; 163 + 164 + AA_BUG(!sk); 165 + AA_BUG(in_interrupt()); 166 + 167 + /* TODO: switch to begin_current_label ???? */ 168 + label = begin_current_label_crit_section(); 169 + error = aa_label_sk_perm(label, op, request, sk); 170 + end_current_label_crit_section(label); 171 + 172 + return error; 173 + } 174 + 175 + 176 + int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, 177 + struct socket *sock) 178 + { 179 + AA_BUG(!label); 180 + AA_BUG(!sock); 181 + AA_BUG(!sock->sk); 182 + 183 + return aa_label_sk_perm(label, op, request, sock->sk); 184 + }
+87 -79
security/apparmor/policy.c
··· 289 289 return NULL; 290 290 } 291 291 292 - /** 293 - * aa_new_null_profile - create or find a null-X learning profile 294 - * @parent: profile that caused this profile to be created (NOT NULL) 295 - * @hat: true if the null- learning profile is a hat 296 - * @base: name to base the null profile off of 297 - * @gfp: type of allocation 298 - * 299 - * Find/Create a null- complain mode profile used in learning mode. The 300 - * name of the profile is unique and follows the format of parent//null-XXX. 301 - * where XXX is based on the @name or if that fails or is not supplied 302 - * a unique number 303 - * 304 - * null profiles are added to the profile list but the list does not 305 - * hold a count on them so that they are automatically released when 306 - * not in use. 307 - * 308 - * Returns: new refcounted profile else NULL on failure 309 - */ 310 - struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, 311 - const char *base, gfp_t gfp) 312 - { 313 - struct aa_profile *profile; 314 - char *name; 315 - 316 - AA_BUG(!parent); 317 - 318 - if (base) { 319 - name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base), 320 - gfp); 321 - if (name) { 322 - sprintf(name, "%s//null-%s", parent->base.hname, base); 323 - goto name; 324 - } 325 - /* fall through to try shorter uniq */ 326 - } 327 - 328 - name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp); 329 - if (!name) 330 - return NULL; 331 - sprintf(name, "%s//null-%x", parent->base.hname, 332 - atomic_inc_return(&parent->ns->uniq_null)); 333 - 334 - name: 335 - /* lookup to see if this is a dup creation */ 336 - profile = aa_find_child(parent, basename(name)); 337 - if (profile) 338 - goto out; 339 - 340 - profile = aa_alloc_profile(name, NULL, gfp); 341 - if (!profile) 342 - goto fail; 343 - 344 - profile->mode = APPARMOR_COMPLAIN; 345 - profile->label.flags |= FLAG_NULL; 346 - if (hat) 347 - profile->label.flags |= FLAG_HAT; 348 - profile->path_flags = parent->path_flags; 349 - 350 - /* released on free_profile */ 351 - rcu_assign_pointer(profile->parent, aa_get_profile(parent)); 352 - profile->ns = aa_get_ns(parent->ns); 353 - profile->file.dfa = aa_get_dfa(nulldfa); 354 - profile->policy.dfa = aa_get_dfa(nulldfa); 355 - 356 - mutex_lock(&profile->ns->lock); 357 - __add_profile(&parent->base.profiles, profile); 358 - mutex_unlock(&profile->ns->lock); 359 - 360 - /* refcount released by caller */ 361 - out: 362 - kfree(name); 363 - 364 - return profile; 365 - 366 - fail: 367 - aa_free_profile(profile); 368 - return NULL; 369 - } 370 - 371 292 /* TODO: profile accounting - setup in remove */ 372 293 373 294 /** ··· 477 556 aa_put_ns(ns); 478 557 479 558 return profile; 559 + } 560 + 561 + /** 562 + * aa_new_null_profile - create or find a null-X learning profile 563 + * @parent: profile that caused this profile to be created (NOT NULL) 564 + * @hat: true if the null- learning profile is a hat 565 + * @base: name to base the null profile off of 566 + * @gfp: type of allocation 567 + * 568 + * Find/Create a null- complain mode profile used in learning mode. The 569 + * name of the profile is unique and follows the format of parent//null-XXX. 570 + * where XXX is based on the @name or if that fails or is not supplied 571 + * a unique number 572 + * 573 + * null profiles are added to the profile list but the list does not 574 + * hold a count on them so that they are automatically released when 575 + * not in use. 576 + * 577 + * Returns: new refcounted profile else NULL on failure 578 + */ 579 + struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, 580 + const char *base, gfp_t gfp) 581 + { 582 + struct aa_profile *p, *profile; 583 + const char *bname; 584 + char *name; 585 + 586 + AA_BUG(!parent); 587 + 588 + if (base) { 589 + name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base), 590 + gfp); 591 + if (name) { 592 + sprintf(name, "%s//null-%s", parent->base.hname, base); 593 + goto name; 594 + } 595 + /* fall through to try shorter uniq */ 596 + } 597 + 598 + name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp); 599 + if (!name) 600 + return NULL; 601 + sprintf(name, "%s//null-%x", parent->base.hname, 602 + atomic_inc_return(&parent->ns->uniq_null)); 603 + 604 + name: 605 + /* lookup to see if this is a dup creation */ 606 + bname = basename(name); 607 + profile = aa_find_child(parent, bname); 608 + if (profile) 609 + goto out; 610 + 611 + profile = aa_alloc_profile(name, NULL, gfp); 612 + if (!profile) 613 + goto fail; 614 + 615 + profile->mode = APPARMOR_COMPLAIN; 616 + profile->label.flags |= FLAG_NULL; 617 + if (hat) 618 + profile->label.flags |= FLAG_HAT; 619 + profile->path_flags = parent->path_flags; 620 + 621 + /* released on free_profile */ 622 + rcu_assign_pointer(profile->parent, aa_get_profile(parent)); 623 + profile->ns = aa_get_ns(parent->ns); 624 + profile->file.dfa = aa_get_dfa(nulldfa); 625 + profile->policy.dfa = aa_get_dfa(nulldfa); 626 + 627 + mutex_lock(&profile->ns->lock); 628 + p = __find_child(&parent->base.profiles, bname); 629 + if (p) { 630 + aa_free_profile(profile); 631 + profile = aa_get_profile(p); 632 + } else { 633 + __add_profile(&parent->base.profiles, profile); 634 + } 635 + mutex_unlock(&profile->ns->lock); 636 + 637 + /* refcount released by caller */ 638 + out: 639 + kfree(name); 640 + 641 + return profile; 642 + 643 + fail: 644 + aa_free_profile(profile); 645 + return NULL; 480 646 } 481 647 482 648 /**
+2
security/apparmor/policy_ns.c
··· 112 112 ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR | 113 113 FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; 114 114 ns->unconfined->mode = APPARMOR_UNCONFINED; 115 + ns->unconfined->file.dfa = aa_get_dfa(nulldfa); 116 + ns->unconfined->policy.dfa = aa_get_dfa(nulldfa); 115 117 116 118 /* ns and ns->unconfined share ns->unconfined refcount */ 117 119 ns->unconfined->ns = ns;
+87 -18
security/apparmor/policy_unpack.c
··· 85 85 audit_log_format(ab, " ns="); 86 86 audit_log_untrustedstring(ab, aad(sa)->iface.ns); 87 87 } 88 - if (aad(sa)->iface.name) { 88 + if (aad(sa)->name) { 89 89 audit_log_format(ab, " name="); 90 - audit_log_untrustedstring(ab, aad(sa)->iface.name); 90 + audit_log_untrustedstring(ab, aad(sa)->name); 91 91 } 92 92 if (aad(sa)->iface.pos) 93 93 audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos); ··· 114 114 aad(&sa)->iface.pos = e->pos - e->start; 115 115 aad(&sa)->iface.ns = ns_name; 116 116 if (new) 117 - aad(&sa)->iface.name = new->base.hname; 117 + aad(&sa)->name = new->base.hname; 118 118 else 119 - aad(&sa)->iface.name = name; 119 + aad(&sa)->name = name; 120 120 aad(&sa)->info = info; 121 121 aad(&sa)->error = error; 122 122 ··· 272 272 273 273 fail: 274 274 e->pos = pos; 275 + return 0; 276 + } 277 + 278 + static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name) 279 + { 280 + if (unpack_nameX(e, AA_U16, name)) { 281 + if (!inbounds(e, sizeof(u16))) 282 + return 0; 283 + if (data) 284 + *data = le16_to_cpu(get_unaligned((__le16 *) e->pos)); 285 + e->pos += sizeof(u16); 286 + return 1; 287 + } 275 288 return 0; 276 289 } 277 290 ··· 461 448 */ 462 449 static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) 463 450 { 464 - void *pos = e->pos; 451 + void *saved_pos = e->pos; 465 452 466 453 /* exec table is optional */ 467 454 if (unpack_nameX(e, AA_STRUCT, "xtable")) { ··· 524 511 525 512 fail: 526 513 aa_free_domain_entries(&profile->file.trans); 527 - e->pos = pos; 514 + e->pos = saved_pos; 528 515 return 0; 529 516 } 530 517 ··· 596 583 { 597 584 struct aa_profile *profile = NULL; 598 585 const char *tmpname, *tmpns = NULL, *name = NULL; 599 - size_t ns_len; 586 + const char *info = "failed to unpack profile"; 587 + size_t size = 0, ns_len; 600 588 struct rhashtable_params params = { 0 }; 601 589 char *key = NULL; 602 590 struct aa_data *data; ··· 618 604 tmpname = aa_splitn_fqname(name, strlen(name), &tmpns, &ns_len); 619 605 if (tmpns) { 620 606 *ns_name = kstrndup(tmpns, ns_len, GFP_KERNEL); 621 - if (!*ns_name) 607 + if (!*ns_name) { 608 + info = "out of memory"; 622 609 goto fail; 610 + } 623 611 name = tmpname; 624 612 } 625 613 ··· 640 624 if (IS_ERR(profile->xmatch)) { 641 625 error = PTR_ERR(profile->xmatch); 642 626 profile->xmatch = NULL; 627 + info = "bad xmatch"; 643 628 goto fail; 644 629 } 645 630 /* xmatch_len is not optional if xmatch is set */ 646 631 if (profile->xmatch) { 647 - if (!unpack_u32(e, &tmp, NULL)) 632 + if (!unpack_u32(e, &tmp, NULL)) { 633 + info = "missing xmatch len"; 648 634 goto fail; 635 + } 649 636 profile->xmatch_len = tmp; 650 637 } 651 638 ··· 656 637 (void) unpack_str(e, &profile->disconnected, "disconnected"); 657 638 658 639 /* per profile debug flags (complain, audit) */ 659 - if (!unpack_nameX(e, AA_STRUCT, "flags")) 640 + if (!unpack_nameX(e, AA_STRUCT, "flags")) { 641 + info = "profile missing flags"; 660 642 goto fail; 643 + } 644 + info = "failed to unpack profile flags"; 661 645 if (!unpack_u32(e, &tmp, NULL)) 662 646 goto fail; 663 647 if (tmp & PACKED_FLAG_HAT) ··· 689 667 /* set a default value if path_flags field is not present */ 690 668 profile->path_flags = PATH_MEDIATE_DELETED; 691 669 670 + info = "failed to unpack profile capabilities"; 692 671 if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) 693 672 goto fail; 694 673 if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL)) ··· 699 676 if (!unpack_u32(e, &tmpcap.cap[0], NULL)) 700 677 goto fail; 701 678 679 + info = "failed to unpack upper profile capabilities"; 702 680 if (unpack_nameX(e, AA_STRUCT, "caps64")) { 703 681 /* optional upper half of 64 bit caps */ 704 682 if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL)) ··· 714 690 goto fail; 715 691 } 716 692 693 + info = "failed to unpack extended profile capabilities"; 717 694 if (unpack_nameX(e, AA_STRUCT, "capsx")) { 718 695 /* optional extended caps mediation mask */ 719 696 if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL)) ··· 725 700 goto fail; 726 701 } 727 702 728 - if (!unpack_rlimits(e, profile)) 703 + if (!unpack_rlimits(e, profile)) { 704 + info = "failed to unpack profile rlimits"; 729 705 goto fail; 706 + } 707 + 708 + size = unpack_array(e, "net_allowed_af"); 709 + if (size) { 710 + 711 + for (i = 0; i < size; i++) { 712 + /* discard extraneous rules that this kernel will 713 + * never request 714 + */ 715 + if (i >= AF_MAX) { 716 + u16 tmp; 717 + 718 + if (!unpack_u16(e, &tmp, NULL) || 719 + !unpack_u16(e, &tmp, NULL) || 720 + !unpack_u16(e, &tmp, NULL)) 721 + goto fail; 722 + continue; 723 + } 724 + if (!unpack_u16(e, &profile->net.allow[i], NULL)) 725 + goto fail; 726 + if (!unpack_u16(e, &profile->net.audit[i], NULL)) 727 + goto fail; 728 + if (!unpack_u16(e, &profile->net.quiet[i], NULL)) 729 + goto fail; 730 + } 731 + if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 732 + goto fail; 733 + } 734 + if (VERSION_LT(e->version, v7)) { 735 + /* pre v7 policy always allowed these */ 736 + profile->net.allow[AF_UNIX] = 0xffff; 737 + profile->net.allow[AF_NETLINK] = 0xffff; 738 + } 730 739 731 740 if (unpack_nameX(e, AA_STRUCT, "policydb")) { 732 741 /* generic policy dfa - optional and may be NULL */ 742 + info = "failed to unpack policydb"; 733 743 profile->policy.dfa = unpack_dfa(e); 734 744 if (IS_ERR(profile->policy.dfa)) { 735 745 error = PTR_ERR(profile->policy.dfa); ··· 794 734 if (IS_ERR(profile->file.dfa)) { 795 735 error = PTR_ERR(profile->file.dfa); 796 736 profile->file.dfa = NULL; 737 + info = "failed to unpack profile file rules"; 797 738 goto fail; 798 739 } else if (profile->file.dfa) { 799 740 if (!unpack_u32(e, &profile->file.start, "dfa_start")) ··· 807 746 } else 808 747 profile->file.dfa = aa_get_dfa(nulldfa); 809 748 810 - if (!unpack_trans_table(e, profile)) 749 + if (!unpack_trans_table(e, profile)) { 750 + info = "failed to unpack profile transition table"; 811 751 goto fail; 752 + } 812 753 813 754 if (unpack_nameX(e, AA_STRUCT, "data")) { 755 + info = "out of memory"; 814 756 profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL); 815 757 if (!profile->data) 816 758 goto fail; ··· 825 761 params.hashfn = strhash; 826 762 params.obj_cmpfn = datacmp; 827 763 828 - if (rhashtable_init(profile->data, &params)) 764 + if (rhashtable_init(profile->data, &params)) { 765 + info = "failed to init key, value hash table"; 829 766 goto fail; 767 + } 830 768 831 769 while (unpack_strdup(e, &key, NULL)) { 832 770 data = kzalloc(sizeof(*data), GFP_KERNEL); ··· 850 784 profile->data->p); 851 785 } 852 786 853 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 787 + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) { 788 + info = "failed to unpack end of key, value data table"; 854 789 goto fail; 790 + } 855 791 } 856 792 857 - if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 793 + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) { 794 + info = "failed to unpack end of profile"; 858 795 goto fail; 796 + } 859 797 860 798 return profile; 861 799 ··· 868 798 name = NULL; 869 799 else if (!name) 870 800 name = "unknown"; 871 - audit_iface(profile, NULL, name, "failed to unpack profile", e, 872 - error); 801 + audit_iface(profile, NULL, name, info, e, error); 873 802 aa_free_profile(profile); 874 803 875 804 return ERR_PTR(error); ··· 901 832 * if not specified use previous version 902 833 * Mask off everything that is not kernel abi version 903 834 */ 904 - if (VERSION_LT(e->version, v5) && VERSION_GT(e->version, v7)) { 835 + if (VERSION_LT(e->version, v5) || VERSION_GT(e->version, v7)) { 905 836 audit_iface(NULL, NULL, NULL, "unsupported interface version", 906 837 e, error); 907 838 return error;