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

Merge tag 'apparmor-pr-2022-08-08' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor

Pull AppArmor updates from John Johansen:
"This is mostly cleanups and bug fixes with the one bigger change being
Mathew Wilcox's patch to use XArrays instead of the IDR from the
thread around the locking weirdness.

Features:
- Convert secid mapping to XArrays instead of IDR
- Add a kernel label to use on kernel objects
- Extend policydb permission set by making use of the xbits
- Make export of raw binary profile to userspace optional
- Enable tuning of policy paranoid load for embedded systems
- Don't create raw_sha1 symlink if sha1 hashing is disabled
- Allow labels to carry debug flags

Cleanups:
- Update MAINTAINERS file
- Use struct_size() helper in kmalloc()
- Move ptrace mediation to more logical task.{h,c}
- Resolve uninitialized symbol warnings
- Remove redundant ret variable
- Mark alloc_unconfined() as static
- Update help description of policy hash for introspection
- Remove some casts which are no-longer required

Bug Fixes:
- Fix aa_label_asxprint return check
- Fix reference count leak in aa_pivotroot()
- Fix memleak in aa_simple_write_to_buffer()
- Fix kernel doc comments
- Fix absroot causing audited secids to begin with =
- Fix quiet_denied for file rules
- Fix failed mount permission check error message
- Disable showing the mode as part of a secid to secctx
- Fix setting unconfined mode on a loaded profile
- Fix overlapping attachment computation
- Fix undefined reference to `zlib_deflate_workspacesize'"

* tag 'apparmor-pr-2022-08-08' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: (34 commits)
apparmor: Update MAINTAINERS file with new email address
apparmor: correct config reference to intended one
apparmor: move ptrace mediation to more logical task.{h,c}
apparmor: extend policydb permission set by making use of the xbits
apparmor: allow label to carry debug flags
apparmor: fix overlapping attachment computation
apparmor: fix setting unconfined mode on a loaded profile
apparmor: Fix some kernel-doc comments
apparmor: Mark alloc_unconfined() as static
apparmor: disable showing the mode as part of a secid to secctx
apparmor: Convert secid mapping to XArrays instead of IDR
apparmor: add a kernel label to use on kernel objects
apparmor: test: Remove some casts which are no-longer required
apparmor: Fix memleak in aa_simple_write_to_buffer()
apparmor: fix reference count leak in aa_pivotroot()
apparmor: Fix some kernel-doc comments
apparmor: Fix undefined reference to `zlib_deflate_workspacesize'
apparmor: fix aa_label_asxprint return check
apparmor: Fix some kernel-doc comments
apparmor: Fix some kernel-doc comments
...

+491 -339
+6 -2
MAINTAINERS
··· 1390 1390 1391 1391 APPARMOR SECURITY MODULE 1392 1392 M: John Johansen <john.johansen@canonical.com> 1393 - L: apparmor@lists.ubuntu.com (subscribers-only, general discussion) 1393 + M: John Johansen <john@apparmor.net> 1394 + L: apparmor@lists.ubuntu.com (moderated for non-subscribers) 1394 1395 S: Supported 1395 - W: wiki.apparmor.net 1396 + W: apparmor.net 1397 + B: https://gitlab.com/apparmor/apparmor-kernel 1398 + C: irc://irc.oftc.net/apparmor 1396 1399 T: git git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor 1400 + T: https://gitlab.com/apparmor/apparmor-kernel.git 1397 1401 F: Documentation/admin-guide/LSM/apparmor.rst 1398 1402 F: security/apparmor/ 1399 1403
+61 -25
security/apparmor/Kconfig
··· 6 6 select SECURITY_PATH 7 7 select SECURITYFS 8 8 select SECURITY_NETWORK 9 - select ZLIB_INFLATE 10 - select ZLIB_DEFLATE 11 9 default n 12 10 help 13 11 This enables the AppArmor security module. ··· 14 16 http://apparmor.wiki.kernel.org 15 17 16 18 If you are unsure how to answer this question, answer N. 17 - 18 - config SECURITY_APPARMOR_HASH 19 - bool "Enable introspection of sha1 hashes for loaded profiles" 20 - depends on SECURITY_APPARMOR 21 - select CRYPTO 22 - select CRYPTO_SHA1 23 - default y 24 - help 25 - This option selects whether introspection of loaded policy 26 - is available to userspace via the apparmor filesystem. 27 - 28 - config SECURITY_APPARMOR_HASH_DEFAULT 29 - bool "Enable policy hash introspection by default" 30 - depends on SECURITY_APPARMOR_HASH 31 - default y 32 - help 33 - This option selects whether sha1 hashing of loaded policy 34 - is enabled by default. The generation of sha1 hashes for 35 - loaded policy provide system administrators a quick way 36 - to verify that policy in the kernel matches what is expected, 37 - however it can slow down policy load on some devices. In 38 - these cases policy hashing can be disabled by default and 39 - enabled only if needed. 40 19 41 20 config SECURITY_APPARMOR_DEBUG 42 21 bool "Build AppArmor with debug code" ··· 43 68 Set the default value of the apparmor.debug kernel parameter. 44 69 When enabled, various debug messages will be logged to 45 70 the kernel message buffer. 71 + 72 + config SECURITY_APPARMOR_INTROSPECT_POLICY 73 + bool "Allow loaded policy to be introspected" 74 + depends on SECURITY_APPARMOR 75 + default y 76 + help 77 + This option selects whether introspection of loaded policy 78 + is available to userspace via the apparmor filesystem. This 79 + adds to kernel memory usage. It is required for introspection 80 + of loaded policy, and check point and restore support. It 81 + can be disabled for embedded systems where reducing memory and 82 + cpu is paramount. 83 + 84 + config SECURITY_APPARMOR_HASH 85 + bool "Enable introspection of sha1 hashes for loaded profiles" 86 + depends on SECURITY_APPARMOR_INTROSPECT_POLICY 87 + select CRYPTO 88 + select CRYPTO_SHA1 89 + default y 90 + help 91 + This option selects whether introspection of loaded policy 92 + hashes is available to userspace via the apparmor 93 + filesystem. This option provides a light weight means of 94 + checking loaded policy. This option adds to policy load 95 + time and can be disabled for small embedded systems. 96 + 97 + config SECURITY_APPARMOR_HASH_DEFAULT 98 + bool "Enable policy hash introspection by default" 99 + depends on SECURITY_APPARMOR_HASH 100 + default y 101 + help 102 + This option selects whether sha1 hashing of loaded policy 103 + is enabled by default. The generation of sha1 hashes for 104 + loaded policy provide system administrators a quick way 105 + to verify that policy in the kernel matches what is expected, 106 + however it can slow down policy load on some devices. In 107 + these cases policy hashing can be disabled by default and 108 + enabled only if needed. 109 + 110 + config SECURITY_APPARMOR_EXPORT_BINARY 111 + bool "Allow exporting the raw binary policy" 112 + depends on SECURITY_APPARMOR_INTROSPECT_POLICY 113 + select ZLIB_INFLATE 114 + select ZLIB_DEFLATE 115 + default y 116 + help 117 + This option allows reading back binary policy as it was loaded. 118 + It increases the amount of kernel memory needed by policy and 119 + also increases policy load time. This option is required for 120 + checkpoint and restore support, and debugging of loaded policy. 121 + 122 + config SECURITY_APPARMOR_PARANOID_LOAD 123 + bool "Perform full verification of loaded policy" 124 + depends on SECURITY_APPARMOR 125 + default y 126 + help 127 + This options allows controlling whether apparmor does a full 128 + verification of loaded policy. This should not be disabled 129 + except for embedded systems where the image is read only, 130 + includes policy, and has some form of integrity check. 131 + Disabling the check will speed up policy loads. 46 132 47 133 config SECURITY_APPARMOR_KUNIT_TEST 48 134 bool "Build KUnit tests for policy_unpack.c" if !KUNIT_ALL_TESTS
+58 -45
security/apparmor/apparmorfs.c
··· 36 36 #include "include/policy_ns.h" 37 37 #include "include/resource.h" 38 38 #include "include/policy_unpack.h" 39 + #include "include/task.h" 39 40 40 41 /* 41 42 * The apparmor filesystem interface used for policy load and introspection ··· 71 70 struct aa_loaddata *loaddata; 72 71 }; 73 72 73 + #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY 74 74 #define RAWDATA_F_DATA_BUF(p) (char *)(p + 1) 75 75 76 76 static void rawdata_f_data_free(struct rawdata_f_data *private) ··· 96 94 97 95 return ret; 98 96 } 97 + #endif 99 98 100 99 /** 101 - * aa_mangle_name - mangle a profile name to std profile layout form 100 + * mangle_name - mangle a profile name to std profile layout form 102 101 * @name: profile name to mangle (NOT NULL) 103 102 * @target: buffer to store mangled name, same length as @name (MAYBE NULL) 104 103 * ··· 404 401 405 402 data->size = copy_size; 406 403 if (copy_from_user(data->data, userbuf, copy_size)) { 407 - kvfree(data); 404 + aa_put_loaddata(data); 408 405 return ERR_PTR(-EFAULT); 409 406 } 410 407 ··· 1204 1201 1205 1202 1206 1203 /* policy/raw_data/ * file ops */ 1207 - 1204 + #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY 1208 1205 #define SEQ_RAWDATA_FOPS(NAME) \ 1209 1206 static int seq_rawdata_ ##NAME ##_open(struct inode *inode, struct file *file)\ 1210 1207 { \ ··· 1297 1294 1298 1295 static int deflate_decompress(char *src, size_t slen, char *dst, size_t dlen) 1299 1296 { 1300 - int error; 1301 - struct z_stream_s strm; 1297 + #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY 1298 + if (aa_g_rawdata_compression_level != 0) { 1299 + int error = 0; 1300 + struct z_stream_s strm; 1302 1301 1303 - if (aa_g_rawdata_compression_level == 0) { 1304 - if (dlen < slen) 1305 - return -EINVAL; 1306 - memcpy(dst, src, slen); 1307 - return 0; 1308 - } 1302 + memset(&strm, 0, sizeof(strm)); 1309 1303 1310 - memset(&strm, 0, sizeof(strm)); 1304 + strm.workspace = kvzalloc(zlib_inflate_workspacesize(), GFP_KERNEL); 1305 + if (!strm.workspace) 1306 + return -ENOMEM; 1311 1307 1312 - strm.workspace = kvzalloc(zlib_inflate_workspacesize(), GFP_KERNEL); 1313 - if (!strm.workspace) 1314 - return -ENOMEM; 1308 + strm.next_in = src; 1309 + strm.avail_in = slen; 1315 1310 1316 - strm.next_in = src; 1317 - strm.avail_in = slen; 1311 + error = zlib_inflateInit(&strm); 1312 + if (error != Z_OK) { 1313 + error = -ENOMEM; 1314 + goto fail_inflate_init; 1315 + } 1318 1316 1319 - error = zlib_inflateInit(&strm); 1320 - if (error != Z_OK) { 1321 - error = -ENOMEM; 1322 - goto fail_inflate_init; 1323 - } 1317 + strm.next_out = dst; 1318 + strm.avail_out = dlen; 1324 1319 1325 - strm.next_out = dst; 1326 - strm.avail_out = dlen; 1320 + error = zlib_inflate(&strm, Z_FINISH); 1321 + if (error != Z_STREAM_END) 1322 + error = -EINVAL; 1323 + else 1324 + error = 0; 1327 1325 1328 - error = zlib_inflate(&strm, Z_FINISH); 1329 - if (error != Z_STREAM_END) 1330 - error = -EINVAL; 1331 - else 1332 - error = 0; 1333 - 1334 - zlib_inflateEnd(&strm); 1326 + zlib_inflateEnd(&strm); 1335 1327 fail_inflate_init: 1336 - kvfree(strm.workspace); 1337 - return error; 1328 + kvfree(strm.workspace); 1329 + 1330 + return error; 1331 + } 1332 + #endif 1333 + 1334 + if (dlen < slen) 1335 + return -EINVAL; 1336 + memcpy(dst, src, slen); 1337 + return 0; 1338 1338 } 1339 1339 1340 1340 static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size, ··· 1498 1492 1499 1493 return PTR_ERR(dent); 1500 1494 } 1495 + #endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ 1496 + 1501 1497 1502 1498 /** fns to setup dynamic per profile/namespace files **/ 1503 1499 1504 - /** 1500 + /* 1505 1501 * 1506 1502 * Requires: @profile->ns->lock held 1507 1503 */ ··· 1530 1522 } 1531 1523 } 1532 1524 1533 - /** 1525 + /* 1534 1526 * 1535 1527 * Requires: @old->ns->lock held 1536 1528 */ ··· 1565 1557 return dent; 1566 1558 } 1567 1559 1560 + #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY 1568 1561 static int profile_depth(struct aa_profile *profile) 1569 1562 { 1570 1563 int depth = 0; ··· 1667 1658 static const struct inode_operations rawdata_link_data_iops = { 1668 1659 .get_link = rawdata_get_link_data, 1669 1660 }; 1670 - 1661 + #endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ 1671 1662 1672 1663 /* 1673 1664 * Requires: @profile->ns->lock held ··· 1738 1729 profile->dents[AAFS_PROF_HASH] = dent; 1739 1730 } 1740 1731 1732 + #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY 1741 1733 if (profile->rawdata) { 1742 - dent = aafs_create("raw_sha1", S_IFLNK | 0444, dir, 1743 - profile->label.proxy, NULL, NULL, 1744 - &rawdata_link_sha1_iops); 1745 - if (IS_ERR(dent)) 1746 - goto fail; 1747 - aa_get_proxy(profile->label.proxy); 1748 - profile->dents[AAFS_PROF_RAW_HASH] = dent; 1749 - 1734 + if (aa_g_hash_policy) { 1735 + dent = aafs_create("raw_sha1", S_IFLNK | 0444, dir, 1736 + profile->label.proxy, NULL, NULL, 1737 + &rawdata_link_sha1_iops); 1738 + if (IS_ERR(dent)) 1739 + goto fail; 1740 + aa_get_proxy(profile->label.proxy); 1741 + profile->dents[AAFS_PROF_RAW_HASH] = dent; 1742 + } 1750 1743 dent = aafs_create("raw_abi", S_IFLNK | 0444, dir, 1751 1744 profile->label.proxy, NULL, NULL, 1752 1745 &rawdata_link_abi_iops); ··· 1765 1754 aa_get_proxy(profile->label.proxy); 1766 1755 profile->dents[AAFS_PROF_RAW_DATA] = dent; 1767 1756 } 1757 + #endif /*CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ 1768 1758 1769 1759 list_for_each_entry(child, &profile->base.profiles, base.list) { 1770 1760 error = __aafs_profile_mkdir(child, prof_child_dir(profile)); ··· 1892 1880 __aa_fs_remove_rawdata(ent); 1893 1881 } 1894 1882 1895 - /** 1883 + /* 1896 1884 * 1897 1885 * Requires: @ns->lock held 1898 1886 */ ··· 2335 2323 AA_SFS_FILE_BOOLEAN("v6", 1), 2336 2324 AA_SFS_FILE_BOOLEAN("v7", 1), 2337 2325 AA_SFS_FILE_BOOLEAN("v8", 1), 2326 + AA_SFS_FILE_BOOLEAN("v9", 1), 2338 2327 { } 2339 2328 }; 2340 2329
+1 -1
security/apparmor/audit.c
··· 137 137 } 138 138 if (AUDIT_MODE(profile) == AUDIT_QUIET || 139 139 (type == AUDIT_APPARMOR_DENIED && 140 - AUDIT_MODE(profile) == AUDIT_QUIET)) 140 + AUDIT_MODE(profile) == AUDIT_QUIET_DENIED)) 141 141 return aad(sa)->error; 142 142 143 143 if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
+2 -3
security/apparmor/domain.c
··· 119 119 * @profile: profile to find perms for 120 120 * @label: label to check access permissions for 121 121 * @stack: whether this is a stacking request 122 - * @start: state to start match in 122 + * @state: state to start match in 123 123 * @subns: whether to do permission checks on components in a subns 124 124 * @request: permissions to request 125 125 * @perms: perms struct to set ··· 466 466 * xattrs, or a longer match 467 467 */ 468 468 candidate = profile; 469 - candidate_len = profile->xmatch_len; 469 + candidate_len = max(count, profile->xmatch_len); 470 470 candidate_xattrs = ret; 471 471 conflict = false; 472 472 } ··· 1279 1279 /** 1280 1280 * aa_change_profile - perform a one-way profile transition 1281 1281 * @fqname: name of profile may include namespace (NOT NULL) 1282 - * @onexec: whether this transition is to take place immediately or at exec 1283 1282 * @flags: flags affecting change behavior 1284 1283 * 1285 1284 * Change to new profile @name. Unlike with hats, there is no way
+1
security/apparmor/include/apparmor.h
··· 36 36 extern bool aa_g_audit_header; 37 37 extern bool aa_g_debug; 38 38 extern bool aa_g_hash_policy; 39 + extern bool aa_g_export_binary; 39 40 extern int aa_g_rawdata_compression_level; 40 41 extern bool aa_g_lock_policy; 41 42 extern bool aa_g_logsyscall;
+14
security/apparmor/include/apparmorfs.h
··· 114 114 struct dentry *dent); 115 115 116 116 struct aa_loaddata; 117 + 118 + #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY 117 119 void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata); 118 120 int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata); 121 + #else 122 + static inline void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata) 123 + { 124 + /* empty stub */ 125 + } 126 + 127 + static inline int __aa_fs_create_rawdata(struct aa_ns *ns, 128 + struct aa_loaddata *rawdata) 129 + { 130 + return 0; 131 + } 132 + #endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */ 119 133 120 134 #endif /* __AA_APPARMORFS_H */
+3
security/apparmor/include/file.h
··· 142 142 */ 143 143 #define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \ 144 144 ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) 145 + #define dfa_user_xbits(dfa, state) (((ACCEPT_TABLE(dfa)[state]) >> 7) & 0x7f) 145 146 #define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f) 146 147 #define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f) 147 148 #define dfa_user_xindex(dfa, state) \ ··· 151 150 #define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \ 152 151 0x7f) | \ 153 152 ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) 153 + #define dfa_other_xbits(dfa, state) \ 154 + ((((ACCEPT_TABLE(dfa)[state]) >> 7) >> 14) & 0x7f) 154 155 #define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f) 155 156 #define dfa_other_quiet(dfa, state) \ 156 157 ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
-18
security/apparmor/include/ipc.h
··· 13 13 14 14 #include <linux/sched.h> 15 15 16 - struct aa_profile; 17 - 18 - #define AA_PTRACE_TRACE MAY_WRITE 19 - #define AA_PTRACE_READ MAY_READ 20 - #define AA_MAY_BE_TRACED AA_MAY_APPEND 21 - #define AA_MAY_BE_READ AA_MAY_CREATE 22 - #define PTRACE_PERM_SHIFT 2 23 - 24 - #define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \ 25 - AA_MAY_BE_READ | AA_MAY_BE_TRACED) 26 - #define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE) 27 - 28 - #define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \ 29 - "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ 30 - "xcpu xfsz vtalrm prof winch io pwr sys emt lost" 31 - 32 - int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, 33 - u32 request); 34 16 int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig); 35 17 36 18 #endif /* __AA_IPC_H */
+2
security/apparmor/include/label.h
··· 92 92 FLAG_STALE = 0x800, /* replaced/removed */ 93 93 FLAG_RENAMED = 0x1000, /* label has renaming in it */ 94 94 FLAG_REVOKED = 0x2000, /* label has revocation in it */ 95 + FLAG_DEBUG1 = 0x4000, 96 + FLAG_DEBUG2 = 0x8000, 95 97 96 98 /* These flags must correspond with PATH_flags */ 97 99 /* TODO: add new path flags */
+5
security/apparmor/include/lib.h
··· 22 22 */ 23 23 24 24 #define DEBUG_ON (aa_g_debug) 25 + /* 26 + * split individual debug cases out in preparation for finer grained 27 + * debug controls in the future. 28 + */ 29 + #define AA_DEBUG_LABEL DEBUG_ON 25 30 #define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args) 26 31 #define AA_DEBUG(fmt, args...) \ 27 32 do { \
+2 -2
security/apparmor/include/path.h
··· 17 17 PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */ 18 18 PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */ 19 19 20 - PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */ 21 - PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ 20 + PATH_DELEGATE_DELETED = 0x10000, /* delegate deleted files */ 21 + PATH_MEDIATE_DELETED = 0x20000, /* mediate deleted paths */ 22 22 }; 23 23 24 24 int aa_path_name(const struct path *path, int flags, char *buffer,
+5 -1
security/apparmor/include/policy.h
··· 48 48 49 49 #define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT) 50 50 51 + #define CHECK_DEBUG1(_profile) ((_profile)->label.flags & FLAG_DEBUG1) 52 + 53 + #define CHECK_DEBUG2(_profile) ((_profile)->label.flags & FLAG_DEBUG2) 54 + 51 55 #define profile_is_stale(_profile) (label_is_stale(&(_profile)->label)) 52 56 53 57 #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) ··· 139 135 140 136 const char *attach; 141 137 struct aa_dfa *xmatch; 142 - int xmatch_len; 138 + unsigned int xmatch_len; 143 139 enum audit_mode audit; 144 140 long mode; 145 141 u32 path_flags;
+1
security/apparmor/include/policy_ns.h
··· 74 74 struct dentry *dents[AAFS_NS_SIZEOF]; 75 75 }; 76 76 77 + extern struct aa_label *kernel_t; 77 78 extern struct aa_ns *root_ns; 78 79 79 80 extern const char *aa_hidden_ns_name;
+2
security/apparmor/include/policy_unpack.h
··· 28 28 struct aa_load_ent *aa_load_ent_alloc(void); 29 29 30 30 #define PACKED_FLAG_HAT 1 31 + #define PACKED_FLAG_DEBUG1 2 32 + #define PACKED_FLAG_DEBUG2 4 31 33 32 34 #define PACKED_MODE_ENFORCE 0 33 35 #define PACKED_MODE_COMPLAIN 1
+3 -2
security/apparmor/include/secid.h
··· 21 21 /* secid value that matches any other secid */ 22 22 #define AA_SECID_WILDCARD 1 23 23 24 + /* sysctl to enable displaying mode when converting secid to secctx */ 25 + extern int apparmor_display_secid_mode; 26 + 24 27 struct aa_label *aa_secid_to_label(u32 secid); 25 28 int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); 26 29 int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); ··· 33 30 int aa_alloc_secid(struct aa_label *label, gfp_t gfp); 34 31 void aa_free_secid(u32 secid); 35 32 void aa_secid_update(u32 secid, struct aa_label *label); 36 - 37 - void aa_secids_init(void); 38 33 39 34 #endif /* __AA_SECID_H */
+18
security/apparmor/include/task.h
··· 77 77 ctx->token = 0; 78 78 } 79 79 80 + #define AA_PTRACE_TRACE MAY_WRITE 81 + #define AA_PTRACE_READ MAY_READ 82 + #define AA_MAY_BE_TRACED AA_MAY_APPEND 83 + #define AA_MAY_BE_READ AA_MAY_CREATE 84 + #define PTRACE_PERM_SHIFT 2 85 + 86 + #define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \ 87 + AA_MAY_BE_READ | AA_MAY_BE_TRACED) 88 + #define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE) 89 + 90 + #define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \ 91 + "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ 92 + "xcpu xfsz vtalrm prof winch io pwr sys emt lost" 93 + 94 + int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, 95 + u32 request); 96 + 97 + 80 98 #endif /* __AA_TASK_H */
-110
security/apparmor/ipc.c
··· 9 9 */ 10 10 11 11 #include <linux/gfp.h> 12 - #include <linux/ptrace.h> 13 12 14 13 #include "include/audit.h" 15 14 #include "include/capability.h" ··· 16 17 #include "include/policy.h" 17 18 #include "include/ipc.h" 18 19 #include "include/sig_names.h" 19 - 20 - /** 21 - * audit_ptrace_mask - convert mask to permission string 22 - * @mask: permission mask to convert 23 - * 24 - * Returns: pointer to static string 25 - */ 26 - static const char *audit_ptrace_mask(u32 mask) 27 - { 28 - switch (mask) { 29 - case MAY_READ: 30 - return "read"; 31 - case MAY_WRITE: 32 - return "trace"; 33 - case AA_MAY_BE_READ: 34 - return "readby"; 35 - case AA_MAY_BE_TRACED: 36 - return "tracedby"; 37 - } 38 - return ""; 39 - } 40 - 41 - /* call back to audit ptrace fields */ 42 - static void audit_ptrace_cb(struct audit_buffer *ab, void *va) 43 - { 44 - struct common_audit_data *sa = va; 45 - 46 - if (aad(sa)->request & AA_PTRACE_PERM_MASK) { 47 - audit_log_format(ab, " requested_mask=\"%s\"", 48 - audit_ptrace_mask(aad(sa)->request)); 49 - 50 - if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { 51 - audit_log_format(ab, " denied_mask=\"%s\"", 52 - audit_ptrace_mask(aad(sa)->denied)); 53 - } 54 - } 55 - audit_log_format(ab, " peer="); 56 - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 57 - FLAGS_NONE, GFP_ATOMIC); 58 - } 59 - 60 - /* assumes check for PROFILE_MEDIATES is already done */ 61 - /* TODO: conditionals */ 62 - static int profile_ptrace_perm(struct aa_profile *profile, 63 - struct aa_label *peer, u32 request, 64 - struct common_audit_data *sa) 65 - { 66 - struct aa_perms perms = { }; 67 - 68 - aad(sa)->peer = peer; 69 - aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request, 70 - &perms); 71 - aa_apply_modes_to_perms(profile, &perms); 72 - return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); 73 - } 74 - 75 - static int profile_tracee_perm(struct aa_profile *tracee, 76 - struct aa_label *tracer, u32 request, 77 - struct common_audit_data *sa) 78 - { 79 - if (profile_unconfined(tracee) || unconfined(tracer) || 80 - !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) 81 - return 0; 82 - 83 - return profile_ptrace_perm(tracee, tracer, request, sa); 84 - } 85 - 86 - static int profile_tracer_perm(struct aa_profile *tracer, 87 - struct aa_label *tracee, u32 request, 88 - struct common_audit_data *sa) 89 - { 90 - if (profile_unconfined(tracer)) 91 - return 0; 92 - 93 - if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) 94 - return profile_ptrace_perm(tracer, tracee, request, sa); 95 - 96 - /* profile uses the old style capability check for ptrace */ 97 - if (&tracer->label == tracee) 98 - return 0; 99 - 100 - aad(sa)->label = &tracer->label; 101 - aad(sa)->peer = tracee; 102 - aad(sa)->request = 0; 103 - aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 104 - CAP_OPT_NONE); 105 - 106 - return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); 107 - } 108 - 109 - /** 110 - * aa_may_ptrace - test if tracer task can trace the tracee 111 - * @tracer: label of the task doing the tracing (NOT NULL) 112 - * @tracee: task label to be traced 113 - * @request: permission request 114 - * 115 - * Returns: %0 else error code if permission denied or error 116 - */ 117 - int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, 118 - u32 request) 119 - { 120 - struct aa_profile *profile; 121 - u32 xrequest = request << PTRACE_PERM_SHIFT; 122 - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); 123 - 124 - return xcheck_labels(tracer, tracee, profile, 125 - profile_tracer_perm(profile, tracee, request, &sa), 126 - profile_tracee_perm(profile, tracer, xrequest, &sa)); 127 - } 128 20 129 21 130 22 static inline int map_signal_num(int sig)
+15 -14
security/apparmor/label.c
··· 197 197 return false; 198 198 } 199 199 200 - static bool vec_unconfined(struct aa_profile **vec, int n) 200 + static long union_vec_flags(struct aa_profile **vec, int n, long mask) 201 201 { 202 + long u = 0; 202 203 int i; 203 204 204 205 AA_BUG(!vec); 205 206 206 207 for (i = 0; i < n; i++) { 207 - if (!profile_unconfined(vec[i])) 208 - return false; 208 + u |= vec[i]->label.flags & mask; 209 209 } 210 210 211 - return true; 211 + return u; 212 212 } 213 213 214 214 static int sort_cmp(const void *a, const void *b) ··· 485 485 } 486 486 487 487 /** 488 - * aa_label_next_not_in_set - return the next profile of @sub not in @set 488 + * __aa_label_next_not_in_set - return the next profile of @sub not in @set 489 489 * @I: label iterator 490 490 * @set: label to test against 491 491 * @sub: label to if is subset of @set ··· 1097 1097 else if (k == b->size) 1098 1098 return aa_get_label(b); 1099 1099 } 1100 - if (vec_unconfined(new->vec, new->size)) 1101 - new->flags |= FLAG_UNCONFINED; 1100 + new->flags |= union_vec_flags(new->vec, new->size, FLAG_UNCONFINED | 1101 + FLAG_DEBUG1 | FLAG_DEBUG2); 1102 1102 ls = labels_set(new); 1103 1103 write_lock_irqsave(&ls->lock, flags); 1104 1104 label = __label_insert(labels_set(new), new, false); ··· 1631 1631 AA_BUG(!str && size != 0); 1632 1632 AA_BUG(!label); 1633 1633 1634 - if (flags & FLAG_ABS_ROOT) { 1634 + if (AA_DEBUG_LABEL && (flags & FLAG_ABS_ROOT)) { 1635 1635 ns = root_ns; 1636 - len = snprintf(str, size, "="); 1636 + len = snprintf(str, size, "_"); 1637 1637 update_for_len(total, len, size, str); 1638 1638 } else if (!ns) { 1639 1639 ns = labels_ns(label); ··· 1744 1744 if (!use_label_hname(ns, label, flags) || 1745 1745 display_mode(ns, label, flags)) { 1746 1746 len = aa_label_asxprint(&name, ns, label, flags, gfp); 1747 - if (len == -1) { 1747 + if (len < 0) { 1748 1748 AA_DEBUG("label print error"); 1749 1749 return; 1750 1750 } ··· 1772 1772 int len; 1773 1773 1774 1774 len = aa_label_asxprint(&str, ns, label, flags, gfp); 1775 - if (len == -1) { 1775 + if (len < 0) { 1776 1776 AA_DEBUG("label print error"); 1777 1777 return; 1778 1778 } ··· 1795 1795 int len; 1796 1796 1797 1797 len = aa_label_asxprint(&str, ns, label, flags, gfp); 1798 - if (len == -1) { 1798 + if (len < 0) { 1799 1799 AA_DEBUG("label print error"); 1800 1800 return; 1801 1801 } ··· 1895 1895 AA_BUG(!str); 1896 1896 1897 1897 str = skipn_spaces(str, n); 1898 - if (str == NULL || (*str == '=' && base != &root_ns->unconfined->label)) 1898 + if (str == NULL || (AA_DEBUG_LABEL && *str == '_' && 1899 + base != &root_ns->unconfined->label)) 1899 1900 return ERR_PTR(-EINVAL); 1900 1901 1901 1902 len = label_count_strn_entries(str, end - str); ··· 2137 2136 } 2138 2137 2139 2138 /** 2140 - * __aa_labelset_udate_subtree - update all labels with a stale component 2139 + * __aa_labelset_update_subtree - update all labels with a stale component 2141 2140 * @ns: ns to start update at (NOT NULL) 2142 2141 * 2143 2142 * Requires: @ns lock be held
+22 -5
security/apparmor/lib.c
··· 136 136 { 137 137 struct counted_str *str; 138 138 139 - str = kmalloc(sizeof(struct counted_str) + size, gfp); 139 + str = kmalloc(struct_size(str, name, size), gfp); 140 140 if (!str) 141 141 return NULL; 142 142 ··· 322 322 ((x & 0x60) << 19); /* SETOPT/GETOPT */ 323 323 } 324 324 325 + static u32 map_xbits(u32 x) 326 + { 327 + return ((x & 0x1) << 7) | 328 + ((x & 0x7e) << 9); 329 + } 330 + 325 331 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, 326 332 struct aa_perms *perms) 327 333 { 334 + /* This mapping is convulated due to history. 335 + * v1-v4: only file perms 336 + * v5: added policydb which dropped in perm user conditional to 337 + * gain new perm bits, but had to map around the xbits because 338 + * the userspace compiler was still munging them. 339 + * v9: adds using the xbits in policydb because the compiler now 340 + * supports treating policydb permission bits different. 341 + * Unfortunately there is not way to force auditing on the 342 + * perms represented by the xbits 343 + */ 328 344 *perms = (struct aa_perms) { 329 - .allow = dfa_user_allow(dfa, state), 345 + .allow = dfa_user_allow(dfa, state) | 346 + map_xbits(dfa_user_xbits(dfa, state)), 330 347 .audit = dfa_user_audit(dfa, state), 331 - .quiet = dfa_user_quiet(dfa, state), 348 + .quiet = dfa_user_quiet(dfa, state) | 349 + map_xbits(dfa_other_xbits(dfa, state)), 332 350 }; 333 351 334 - /* for v5 perm mapping in the policydb, the other set is used 352 + /* for v5-v9 perm mapping in the policydb, the other set is used 335 353 * to extend the general perm set 336 354 */ 337 355 perms->allow |= map_other(dfa_other_allow(dfa, state)); 338 356 perms->audit |= map_other(dfa_other_audit(dfa, state)); 339 357 perms->quiet |= map_other(dfa_other_quiet(dfa, state)); 340 - // perms->xindex = dfa_user_xindex(dfa, state); 341 358 } 342 359 343 360 /**
+22 -16
security/apparmor/lsm.c
··· 832 832 } 833 833 834 834 /** 835 - * apparmor_clone_security - clone the sk_security field 835 + * apparmor_sk_clone_security - clone the sk_security field 836 836 */ 837 837 static void apparmor_sk_clone_security(const struct sock *sk, 838 838 struct sock *newsk) ··· 886 886 struct aa_label *label; 887 887 888 888 if (kern) { 889 - struct aa_ns *ns = aa_get_current_ns(); 890 - 891 - label = aa_get_label(ns_unconfined(ns)); 892 - aa_put_ns(ns); 889 + label = aa_get_label(kernel_t); 893 890 } else 894 891 label = aa_get_current_label(); 895 892 ··· 934 937 } 935 938 936 939 /** 937 - * apparmor_socket_list - check perms before allowing listen 940 + * apparmor_socket_listen - check perms before allowing listen 938 941 */ 939 942 static int apparmor_socket_listen(struct socket *sock, int backlog) 940 943 { ··· 1038 1041 } 1039 1042 1040 1043 /** 1041 - * apparmor_getsockopt - check perms before getting socket options 1044 + * apparmor_socket_getsockopt - check perms before getting socket options 1042 1045 */ 1043 1046 static int apparmor_socket_getsockopt(struct socket *sock, int level, 1044 1047 int optname) ··· 1048 1051 } 1049 1052 1050 1053 /** 1051 - * apparmor_setsockopt - check perms before setting socket options 1054 + * apparmor_socket_setsockopt - check perms before setting socket options 1052 1055 */ 1053 1056 static int apparmor_socket_setsockopt(struct socket *sock, int level, 1054 1057 int optname) ··· 1067 1070 1068 1071 #ifdef CONFIG_NETWORK_SECMARK 1069 1072 /** 1070 - * apparmor_socket_sock_recv_skb - check perms before associating skb to sk 1073 + * apparmor_socket_sock_rcv_skb - check perms before associating skb to sk 1071 1074 * 1072 1075 * Note: can not sleep may be called with locks held 1073 1076 * ··· 1354 1357 module_param_named(hash_policy, aa_g_hash_policy, aabool, S_IRUSR | S_IWUSR); 1355 1358 #endif 1356 1359 1360 + /* whether policy exactly as loaded is retained for debug and checkpointing */ 1361 + bool aa_g_export_binary = IS_ENABLED(CONFIG_SECURITY_APPARMOR_EXPORT_BINARY); 1362 + #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY 1363 + module_param_named(export_binary, aa_g_export_binary, aabool, 0600); 1364 + #endif 1365 + 1357 1366 /* policy loaddata compression level */ 1358 1367 int aa_g_rawdata_compression_level = Z_DEFAULT_COMPRESSION; 1359 1368 module_param_named(rawdata_compression_level, aa_g_rawdata_compression_level, ··· 1402 1399 * DEPRECATED: read only as strict checking of load is always done now 1403 1400 * that none root users (user namespaces) can load policy. 1404 1401 */ 1405 - bool aa_g_paranoid_load = true; 1402 + bool aa_g_paranoid_load = IS_ENABLED(CONFIG_SECURITY_APPARMOR_PARANOID_LOAD); 1406 1403 module_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO); 1407 1404 1408 1405 static int param_get_aaintbool(char *buffer, const struct kernel_param *kp); ··· 1764 1761 .mode = 0600, 1765 1762 .proc_handler = apparmor_dointvec, 1766 1763 }, 1764 + { 1765 + .procname = "apparmor_display_secid_mode", 1766 + .data = &apparmor_display_secid_mode, 1767 + .maxlen = sizeof(int), 1768 + .mode = 0600, 1769 + .proc_handler = apparmor_dointvec, 1770 + }, 1771 + 1767 1772 { } 1768 1773 }; 1769 1774 ··· 1830 1819 1831 1820 static int __net_init apparmor_nf_register(struct net *net) 1832 1821 { 1833 - int ret; 1834 - 1835 - ret = nf_register_net_hooks(net, apparmor_nf_ops, 1822 + return nf_register_net_hooks(net, apparmor_nf_ops, 1836 1823 ARRAY_SIZE(apparmor_nf_ops)); 1837 - return ret; 1838 1824 } 1839 1825 1840 1826 static void __net_exit apparmor_nf_unregister(struct net *net) ··· 1864 1856 static int __init apparmor_init(void) 1865 1857 { 1866 1858 int error; 1867 - 1868 - aa_secids_init(); 1869 1859 1870 1860 error = aa_setup_dfa_engine(); 1871 1861 if (error) {
+7 -6
security/apparmor/mount.c
··· 217 217 .allow = dfa_user_allow(dfa, state), 218 218 .audit = dfa_user_audit(dfa, state), 219 219 .quiet = dfa_user_quiet(dfa, state), 220 - .xindex = dfa_user_xindex(dfa, state), 221 220 }; 222 221 223 222 return perms; ··· 228 229 "failed srcname match", 229 230 "failed type match", 230 231 "failed flags match", 231 - "failed data match" 232 + "failed data match", 233 + "failed perms check" 232 234 }; 233 235 234 236 /* ··· 284 284 return 0; 285 285 } 286 286 287 - /* failed at end of flags match */ 288 - return 4; 287 + /* failed at perms check, don't confuse with flags match */ 288 + return 6; 289 289 } 290 290 291 291 ··· 303 303 * @profile: the confining profile 304 304 * @mntpath: for the mntpnt (NOT NULL) 305 305 * @buffer: buffer to be used to lookup mntpath 306 - * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR) 306 + * @devname: string for the devname/src_name (MAY BE NULL OR ERRPTR) 307 307 * @type: string for the dev type (MAYBE NULL) 308 308 * @flags: mount flags to match 309 309 * @data: fs mount data (MAYBE NULL) ··· 358 358 /** 359 359 * match_mnt - handle path matching for mount 360 360 * @profile: the confining profile 361 - * @mntpath: for the mntpnt (NOT NULL) 361 + * @path: for the mntpnt (NOT NULL) 362 362 * @buffer: buffer to be used to lookup mntpath 363 363 * @devpath: path devname/src_name (MAYBE NULL) 364 364 * @devbuffer: buffer to be used to lookup devname/src_name ··· 718 718 aa_put_label(target); 719 719 goto out; 720 720 } 721 + aa_put_label(target); 721 722 } else 722 723 /* already audited error */ 723 724 error = PTR_ERR(target);
+2 -1
security/apparmor/net.c
··· 145 145 static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, 146 146 struct sock *sk) 147 147 { 148 + struct aa_sk_ctx *ctx = SK_CTX(sk); 148 149 int error = 0; 149 150 150 151 AA_BUG(!label); 151 152 AA_BUG(!sk); 152 153 153 - if (!unconfined(label)) { 154 + if (ctx->label != kernel_t && !unconfined(label)) { 154 155 struct aa_profile *profile; 155 156 DEFINE_AUDIT_SK(sa, op, sk); 156 157
+19 -14
security/apparmor/policy.c
··· 422 422 } 423 423 424 424 /** 425 - * aa_lookup_profile - find a profile by its full or partial name 425 + * aa_lookupn_profile - find a profile by its full or partial name 426 426 * @ns: the namespace to start from (NOT NULL) 427 427 * @hname: name to do lookup on. Does not contain namespace prefix (NOT NULL) 428 428 * @n: size of @hname ··· 952 952 953 953 mutex_lock_nested(&ns->lock, ns->level); 954 954 /* check for duplicate rawdata blobs: space and file dedup */ 955 - list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) { 956 - if (aa_rawdata_eq(rawdata_ent, udata)) { 957 - struct aa_loaddata *tmp; 955 + if (!list_empty(&ns->rawdata_list)) { 956 + list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) { 957 + if (aa_rawdata_eq(rawdata_ent, udata)) { 958 + struct aa_loaddata *tmp; 958 959 959 - tmp = __aa_get_loaddata(rawdata_ent); 960 - /* check we didn't fail the race */ 961 - if (tmp) { 962 - aa_put_loaddata(udata); 963 - udata = tmp; 964 - break; 960 + tmp = __aa_get_loaddata(rawdata_ent); 961 + /* check we didn't fail the race */ 962 + if (tmp) { 963 + aa_put_loaddata(udata); 964 + udata = tmp; 965 + break; 966 + } 965 967 } 966 968 } 967 969 } ··· 971 969 list_for_each_entry(ent, &lh, list) { 972 970 struct aa_policy *policy; 973 971 974 - ent->new->rawdata = aa_get_loaddata(udata); 972 + if (aa_g_export_binary) 973 + ent->new->rawdata = aa_get_loaddata(udata); 975 974 error = __lookup_replace(ns, ent->new->base.hname, 976 975 !(mask & AA_MAY_REPLACE_POLICY), 977 976 &ent->old, &info); ··· 1012 1009 } 1013 1010 1014 1011 /* create new fs entries for introspection if needed */ 1015 - if (!udata->dents[AAFS_LOADDATA_DIR]) { 1012 + if (!udata->dents[AAFS_LOADDATA_DIR] && aa_g_export_binary) { 1016 1013 error = __aa_fs_create_rawdata(ns, udata); 1017 1014 if (error) { 1018 1015 info = "failed to create raw_data dir and files"; ··· 1040 1037 1041 1038 /* Done with checks that may fail - do actual replacement */ 1042 1039 __aa_bump_ns_revision(ns); 1043 - __aa_loaddata_update(udata, ns->revision); 1040 + if (aa_g_export_binary) 1041 + __aa_loaddata_update(udata, ns->revision); 1044 1042 list_for_each_entry_safe(ent, tmp, &lh, list) { 1045 1043 list_del_init(&ent->list); 1046 1044 op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL; 1047 1045 1048 - if (ent->old && ent->old->rawdata == ent->new->rawdata) { 1046 + if (ent->old && ent->old->rawdata == ent->new->rawdata && 1047 + ent->new->rawdata) { 1049 1048 /* dedup actual profile replacement */ 1050 1049 audit_policy(label, op, ns_name, ent->new->base.hname, 1051 1050 "same as current profile, skipping",
+39 -14
security/apparmor/policy_ns.c
··· 22 22 #include "include/label.h" 23 23 #include "include/policy.h" 24 24 25 + /* kernel label */ 26 + struct aa_label *kernel_t; 27 + 25 28 /* root profile namespace */ 26 29 struct aa_ns *root_ns; 27 30 const char *aa_hidden_ns_name = "---"; ··· 54 51 } 55 52 56 53 /** 57 - * aa_na_name - Find the ns name to display for @view from @curr 58 - * @curr - current namespace (NOT NULL) 59 - * @view - namespace attempting to view (NOT NULL) 60 - * @subns - are subns visible 54 + * aa_ns_name - Find the ns name to display for @view from @curr 55 + * @curr: current namespace (NOT NULL) 56 + * @view: namespace attempting to view (NOT NULL) 57 + * @subns: are subns visible 61 58 * 62 59 * Returns: name of @view visible from @curr 63 60 */ ··· 78 75 } 79 76 80 77 return aa_hidden_ns_name; 78 + } 79 + 80 + static struct aa_profile *alloc_unconfined(const char *name) 81 + { 82 + struct aa_profile *profile; 83 + 84 + profile = aa_alloc_profile(name, NULL, GFP_KERNEL); 85 + if (!profile) 86 + return NULL; 87 + 88 + profile->label.flags |= FLAG_IX_ON_NAME_ERROR | 89 + FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; 90 + profile->mode = APPARMOR_UNCONFINED; 91 + profile->file.dfa = aa_get_dfa(nulldfa); 92 + profile->policy.dfa = aa_get_dfa(nulldfa); 93 + 94 + return profile; 81 95 } 82 96 83 97 /** ··· 121 101 init_waitqueue_head(&ns->wait); 122 102 123 103 /* released by aa_free_ns() */ 124 - ns->unconfined = aa_alloc_profile("unconfined", NULL, GFP_KERNEL); 104 + ns->unconfined = alloc_unconfined("unconfined"); 125 105 if (!ns->unconfined) 126 106 goto fail_unconfined; 127 - 128 - ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR | 129 - FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; 130 - ns->unconfined->mode = APPARMOR_UNCONFINED; 131 - ns->unconfined->file.dfa = aa_get_dfa(nulldfa); 132 - ns->unconfined->policy.dfa = aa_get_dfa(nulldfa); 133 - 134 107 /* ns and ns->unconfined share ns->unconfined refcount */ 135 108 ns->unconfined->ns = ns; 136 109 ··· 200 187 201 188 /** 202 189 * __aa_lookupn_ns - lookup the namespace matching @hname 203 - * @base: base list to start looking up profile name from (NOT NULL) 190 + * @view: namespace to search in (NOT NULL) 204 191 * @hname: hierarchical ns name (NOT NULL) 205 192 * @n: length of @hname 206 193 * ··· 285 272 } 286 273 287 274 /** 288 - * aa_create_ns - create an ns, fail if it already exists 275 + * __aa_find_or_create_ns - create an ns, fail if it already exists 289 276 * @parent: the parent of the namespace being created 290 277 * @name: the name of the namespace 291 278 * @dir: if not null the dir to put the ns entries in ··· 401 388 */ 402 389 int __init aa_alloc_root_ns(void) 403 390 { 391 + struct aa_profile *kernel_p; 392 + 404 393 /* released by aa_free_root_ns - used as list ref*/ 405 394 root_ns = alloc_ns(NULL, "root"); 406 395 if (!root_ns) 407 396 return -ENOMEM; 397 + 398 + kernel_p = alloc_unconfined("kernel_t"); 399 + if (!kernel_p) { 400 + destroy_ns(root_ns); 401 + aa_free_ns(root_ns); 402 + return -ENOMEM; 403 + } 404 + kernel_t = &kernel_p->label; 405 + root_ns->unconfined->ns = aa_get_ns(root_ns); 408 406 409 407 return 0; 410 408 } ··· 429 405 430 406 root_ns = NULL; 431 407 408 + aa_label_free(kernel_t); 432 409 destroy_ns(ns); 433 410 aa_put_ns(ns); 434 411 }
+36 -17
security/apparmor/policy_unpack.c
··· 125 125 { 126 126 AA_BUG(!data); 127 127 AA_BUG(!data->ns); 128 - AA_BUG(!data->dents[AAFS_LOADDATA_REVISION]); 129 128 AA_BUG(!mutex_is_locked(&data->ns->lock)); 130 129 AA_BUG(data->revision > revision); 131 130 132 131 data->revision = revision; 133 - d_inode(data->dents[AAFS_LOADDATA_DIR])->i_mtime = 134 - current_time(d_inode(data->dents[AAFS_LOADDATA_DIR])); 135 - d_inode(data->dents[AAFS_LOADDATA_REVISION])->i_mtime = 136 - current_time(d_inode(data->dents[AAFS_LOADDATA_REVISION])); 132 + if ((data->dents[AAFS_LOADDATA_REVISION])) { 133 + d_inode(data->dents[AAFS_LOADDATA_DIR])->i_mtime = 134 + current_time(d_inode(data->dents[AAFS_LOADDATA_DIR])); 135 + d_inode(data->dents[AAFS_LOADDATA_REVISION])->i_mtime = 136 + current_time(d_inode(data->dents[AAFS_LOADDATA_REVISION])); 137 + } 137 138 } 138 139 139 140 bool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r) ··· 214 213 } 215 214 216 215 /** 217 - * aa_u16_chunck - test and do bounds checking for a u16 size based chunk 216 + * unpack_u16_chunk - test and do bounds checking for a u16 size based chunk 218 217 * @e: serialized data read head (NOT NULL) 219 218 * @chunk: start address for chunk of data (NOT NULL) 220 219 * ··· 457 456 ((e->pos - e->start) & 7); 458 457 size_t pad = ALIGN(sz, 8) - sz; 459 458 int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) | 460 - TO_ACCEPT2_FLAG(YYTD_DATA32) | DFA_FLAG_VERIFY_STATES; 459 + TO_ACCEPT2_FLAG(YYTD_DATA32); 460 + if (aa_g_paranoid_load) 461 + flags |= DFA_FLAG_VERIFY_STATES; 461 462 dfa = aa_dfa_unpack(blob + pad, size - pad, flags); 462 463 463 464 if (IS_ERR(dfa)) ··· 671 668 /** 672 669 * unpack_profile - unpack a serialized profile 673 670 * @e: serialized data extent information (NOT NULL) 671 + * @ns_name: pointer of newly allocated copy of %NULL in case of error 674 672 * 675 673 * NOTE: unpack profile sets audit struct if there is a failure 676 674 */ ··· 748 744 goto fail; 749 745 if (tmp & PACKED_FLAG_HAT) 750 746 profile->label.flags |= FLAG_HAT; 747 + if (tmp & PACKED_FLAG_DEBUG1) 748 + profile->label.flags |= FLAG_DEBUG1; 749 + if (tmp & PACKED_FLAG_DEBUG2) 750 + profile->label.flags |= FLAG_DEBUG2; 751 751 if (!unpack_u32(e, &tmp, NULL)) 752 752 goto fail; 753 - if (tmp == PACKED_MODE_COMPLAIN || (e->version & FORCE_COMPLAIN_FLAG)) 753 + if (tmp == PACKED_MODE_COMPLAIN || (e->version & FORCE_COMPLAIN_FLAG)) { 754 754 profile->mode = APPARMOR_COMPLAIN; 755 - else if (tmp == PACKED_MODE_ENFORCE) 755 + } else if (tmp == PACKED_MODE_ENFORCE) { 756 756 profile->mode = APPARMOR_ENFORCE; 757 - else if (tmp == PACKED_MODE_KILL) 757 + } else if (tmp == PACKED_MODE_KILL) { 758 758 profile->mode = APPARMOR_KILL; 759 - else if (tmp == PACKED_MODE_UNCONFINED) 759 + } else if (tmp == PACKED_MODE_UNCONFINED) { 760 760 profile->mode = APPARMOR_UNCONFINED; 761 - else 761 + profile->label.flags |= FLAG_UNCONFINED; 762 + } else { 762 763 goto fail; 764 + } 763 765 if (!unpack_u32(e, &tmp, NULL)) 764 766 goto fail; 765 767 if (tmp) ··· 946 936 } 947 937 948 938 /** 949 - * verify_head - unpack serialized stream header 939 + * verify_header - unpack serialized stream header 950 940 * @e: serialized data read head (NOT NULL) 951 941 * @required: whether the header is required or optional 952 942 * @ns: Returns - namespace if one is specified else NULL (NOT NULL) ··· 1062 1052 static int deflate_compress(const char *src, size_t slen, char **dst, 1063 1053 size_t *dlen) 1064 1054 { 1055 + #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY 1065 1056 int error; 1066 1057 struct z_stream_s strm; 1067 1058 void *stgbuf, *dstbuf; ··· 1134 1123 fail_deflate: 1135 1124 kvfree(stgbuf); 1136 1125 goto fail_stg_alloc; 1126 + #else 1127 + *dlen = slen; 1128 + return 0; 1129 + #endif 1137 1130 } 1138 1131 1139 1132 static int compress_loaddata(struct aa_loaddata *data) ··· 1156 1141 if (error) 1157 1142 return error; 1158 1143 1159 - kvfree(udata); 1144 + if (udata != data->data) 1145 + kvfree(udata); 1160 1146 } else 1161 1147 data->compressed_size = data->size; 1162 1148 ··· 1232 1216 goto fail; 1233 1217 } 1234 1218 } 1235 - error = compress_loaddata(udata); 1236 - if (error) 1237 - goto fail; 1219 + 1220 + if (aa_g_export_binary) { 1221 + error = compress_loaddata(udata); 1222 + if (error) 1223 + goto fail; 1224 + } 1238 1225 return 0; 1239 1226 1240 1227 fail_profile:
+8 -8
security/apparmor/policy_unpack_test.c
··· 48 48 size_t e_size; 49 49 }; 50 50 51 - struct aa_ext *build_aa_ext_struct(struct policy_unpack_fixture *puf, 52 - struct kunit *test, size_t buf_size) 51 + static struct aa_ext *build_aa_ext_struct(struct policy_unpack_fixture *puf, 52 + struct kunit *test, size_t buf_size) 53 53 { 54 54 char *buf; 55 55 struct aa_ext *e; ··· 439 439 { 440 440 struct policy_unpack_fixture *puf = test->priv; 441 441 bool success; 442 - u32 data; 442 + u32 data = 0; 443 443 444 444 puf->e->pos += TEST_U32_BUF_OFFSET; 445 445 ··· 456 456 struct policy_unpack_fixture *puf = test->priv; 457 457 const char name[] = TEST_U32_NAME; 458 458 bool success; 459 - u32 data; 459 + u32 data = 0; 460 460 461 461 puf->e->pos += TEST_NAMED_U32_BUF_OFFSET; 462 462 ··· 473 473 struct policy_unpack_fixture *puf = test->priv; 474 474 const char name[] = TEST_U32_NAME; 475 475 bool success; 476 - u32 data; 476 + u32 data = 0; 477 477 478 478 puf->e->pos += TEST_NAMED_U32_BUF_OFFSET; 479 479 puf->e->end = puf->e->start + TEST_U32_BUF_OFFSET + sizeof(u32); ··· 489 489 { 490 490 struct policy_unpack_fixture *puf = test->priv; 491 491 bool success; 492 - u64 data; 492 + u64 data = 0; 493 493 494 494 puf->e->pos += TEST_U64_BUF_OFFSET; 495 495 ··· 506 506 struct policy_unpack_fixture *puf = test->priv; 507 507 const char name[] = TEST_U64_NAME; 508 508 bool success; 509 - u64 data; 509 + u64 data = 0; 510 510 511 511 puf->e->pos += TEST_NAMED_U64_BUF_OFFSET; 512 512 ··· 523 523 struct policy_unpack_fixture *puf = test->priv; 524 524 const char name[] = TEST_U64_NAME; 525 525 bool success; 526 - u64 data; 526 + u64 data = 0; 527 527 528 528 puf->e->pos += TEST_NAMED_U64_BUF_OFFSET; 529 529 puf->e->end = puf->e->start + TEST_U64_BUF_OFFSET + sizeof(u64);
+1 -1
security/apparmor/procattr.c
··· 90 90 } 91 91 92 92 /** 93 - * aa_setprocattr_chagnehat - handle procattr interface to change_hat 93 + * aa_setprocattr_changehat - handle procattr interface to change_hat 94 94 * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL) 95 95 * @size: size of the args 96 96 * @flags: set of flags governing behavior
+22 -34
security/apparmor/secid.c
··· 13 13 #include <linux/errno.h> 14 14 #include <linux/err.h> 15 15 #include <linux/gfp.h> 16 - #include <linux/idr.h> 17 16 #include <linux/slab.h> 18 17 #include <linux/spinlock.h> 18 + #include <linux/xarray.h> 19 19 20 20 #include "include/cred.h" 21 21 #include "include/lib.h" ··· 29 29 */ 30 30 #define AA_FIRST_SECID 2 31 31 32 - static DEFINE_IDR(aa_secids); 33 - static DEFINE_SPINLOCK(secid_lock); 32 + static DEFINE_XARRAY_FLAGS(aa_secids, XA_FLAGS_LOCK_IRQ | XA_FLAGS_TRACK_FREE); 33 + 34 + int apparmor_display_secid_mode; 34 35 35 36 /* 36 37 * TODO: allow policy to reserve a secid range? ··· 48 47 { 49 48 unsigned long flags; 50 49 51 - spin_lock_irqsave(&secid_lock, flags); 52 - idr_replace(&aa_secids, label, secid); 53 - spin_unlock_irqrestore(&secid_lock, flags); 50 + xa_lock_irqsave(&aa_secids, flags); 51 + __xa_store(&aa_secids, secid, label, 0); 52 + xa_unlock_irqrestore(&aa_secids, flags); 54 53 } 55 54 56 55 /** ··· 59 58 */ 60 59 struct aa_label *aa_secid_to_label(u32 secid) 61 60 { 62 - struct aa_label *label; 63 - 64 - rcu_read_lock(); 65 - label = idr_find(&aa_secids, secid); 66 - rcu_read_unlock(); 67 - 68 - return label; 61 + return xa_load(&aa_secids, secid); 69 62 } 70 63 71 64 int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) 72 65 { 73 66 /* TODO: cache secctx and ref count so we don't have to recreate */ 74 67 struct aa_label *label = aa_secid_to_label(secid); 68 + int flags = FLAG_VIEW_SUBNS | FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT; 75 69 int len; 76 70 77 71 AA_BUG(!seclen); ··· 74 78 if (!label) 75 79 return -EINVAL; 76 80 81 + if (apparmor_display_secid_mode) 82 + flags |= FLAG_SHOW_MODE; 83 + 77 84 if (secdata) 78 85 len = aa_label_asxprint(secdata, root_ns, label, 79 - FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | 80 - FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT, 81 - GFP_ATOMIC); 86 + flags, GFP_ATOMIC); 82 87 else 83 - len = aa_label_snxprint(NULL, 0, root_ns, label, 84 - FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | 85 - FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT); 88 + len = aa_label_snxprint(NULL, 0, root_ns, label, flags); 89 + 86 90 if (len < 0) 87 91 return -ENOMEM; 88 92 ··· 122 126 unsigned long flags; 123 127 int ret; 124 128 125 - idr_preload(gfp); 126 - spin_lock_irqsave(&secid_lock, flags); 127 - ret = idr_alloc(&aa_secids, label, AA_FIRST_SECID, 0, GFP_ATOMIC); 128 - spin_unlock_irqrestore(&secid_lock, flags); 129 - idr_preload_end(); 129 + xa_lock_irqsave(&aa_secids, flags); 130 + ret = __xa_alloc(&aa_secids, &label->secid, label, 131 + XA_LIMIT(AA_FIRST_SECID, INT_MAX), gfp); 132 + xa_unlock_irqrestore(&aa_secids, flags); 130 133 131 134 if (ret < 0) { 132 135 label->secid = AA_SECID_INVALID; 133 136 return ret; 134 137 } 135 138 136 - AA_BUG(ret == AA_SECID_INVALID); 137 - label->secid = ret; 138 139 return 0; 139 140 } 140 141 ··· 143 150 { 144 151 unsigned long flags; 145 152 146 - spin_lock_irqsave(&secid_lock, flags); 147 - idr_remove(&aa_secids, secid); 148 - spin_unlock_irqrestore(&secid_lock, flags); 149 - } 150 - 151 - void aa_secids_init(void) 152 - { 153 - idr_init_base(&aa_secids, AA_FIRST_SECID); 153 + xa_lock_irqsave(&aa_secids, flags); 154 + __xa_erase(&aa_secids, secid); 155 + xa_unlock_irqrestore(&aa_secids, flags); 154 156 }
+114
security/apparmor/task.c
··· 12 12 * should return to the previous cred if it has not been modified. 13 13 */ 14 14 15 + #include <linux/gfp.h> 16 + #include <linux/ptrace.h> 17 + 18 + #include "include/audit.h" 15 19 #include "include/cred.h" 20 + #include "include/policy.h" 16 21 #include "include/task.h" 17 22 18 23 /** ··· 181 176 commit_creds(new); 182 177 183 178 return 0; 179 + } 180 + 181 + /** 182 + * audit_ptrace_mask - convert mask to permission string 183 + * @mask: permission mask to convert 184 + * 185 + * Returns: pointer to static string 186 + */ 187 + static const char *audit_ptrace_mask(u32 mask) 188 + { 189 + switch (mask) { 190 + case MAY_READ: 191 + return "read"; 192 + case MAY_WRITE: 193 + return "trace"; 194 + case AA_MAY_BE_READ: 195 + return "readby"; 196 + case AA_MAY_BE_TRACED: 197 + return "tracedby"; 198 + } 199 + return ""; 200 + } 201 + 202 + /* call back to audit ptrace fields */ 203 + static void audit_ptrace_cb(struct audit_buffer *ab, void *va) 204 + { 205 + struct common_audit_data *sa = va; 206 + 207 + if (aad(sa)->request & AA_PTRACE_PERM_MASK) { 208 + audit_log_format(ab, " requested_mask=\"%s\"", 209 + audit_ptrace_mask(aad(sa)->request)); 210 + 211 + if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { 212 + audit_log_format(ab, " denied_mask=\"%s\"", 213 + audit_ptrace_mask(aad(sa)->denied)); 214 + } 215 + } 216 + audit_log_format(ab, " peer="); 217 + aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 218 + FLAGS_NONE, GFP_ATOMIC); 219 + } 220 + 221 + /* assumes check for PROFILE_MEDIATES is already done */ 222 + /* TODO: conditionals */ 223 + static int profile_ptrace_perm(struct aa_profile *profile, 224 + struct aa_label *peer, u32 request, 225 + struct common_audit_data *sa) 226 + { 227 + struct aa_perms perms = { }; 228 + 229 + aad(sa)->peer = peer; 230 + aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request, 231 + &perms); 232 + aa_apply_modes_to_perms(profile, &perms); 233 + return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); 234 + } 235 + 236 + static int profile_tracee_perm(struct aa_profile *tracee, 237 + struct aa_label *tracer, u32 request, 238 + struct common_audit_data *sa) 239 + { 240 + if (profile_unconfined(tracee) || unconfined(tracer) || 241 + !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) 242 + return 0; 243 + 244 + return profile_ptrace_perm(tracee, tracer, request, sa); 245 + } 246 + 247 + static int profile_tracer_perm(struct aa_profile *tracer, 248 + struct aa_label *tracee, u32 request, 249 + struct common_audit_data *sa) 250 + { 251 + if (profile_unconfined(tracer)) 252 + return 0; 253 + 254 + if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) 255 + return profile_ptrace_perm(tracer, tracee, request, sa); 256 + 257 + /* profile uses the old style capability check for ptrace */ 258 + if (&tracer->label == tracee) 259 + return 0; 260 + 261 + aad(sa)->label = &tracer->label; 262 + aad(sa)->peer = tracee; 263 + aad(sa)->request = 0; 264 + aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 265 + CAP_OPT_NONE); 266 + 267 + return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); 268 + } 269 + 270 + /** 271 + * aa_may_ptrace - test if tracer task can trace the tracee 272 + * @tracer: label of the task doing the tracing (NOT NULL) 273 + * @tracee: task label to be traced 274 + * @request: permission request 275 + * 276 + * Returns: %0 else error code if permission denied or error 277 + */ 278 + int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, 279 + u32 request) 280 + { 281 + struct aa_profile *profile; 282 + u32 xrequest = request << PTRACE_PERM_SHIFT; 283 + DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); 284 + 285 + return xcheck_labels(tracer, tracee, profile, 286 + profile_tracer_perm(profile, tracee, request, &sa), 287 + profile_tracee_perm(profile, tracer, xrequest, &sa)); 184 288 }