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.

apparmor: isolate policy backwards compatibility to its own file

The details of mapping old policy into newer policy formats clutters
up the unpack code and makes it possible to accidentally use old
mappings in code, so isolate the mapping code into its own file.

This will become more important when the dfa remapping code lands,
as it will greatly expand the compat code base.

Signed-off-by: John Johansen <john.johansen@canonical.com>

+359 -287
+2 -1
security/apparmor/Makefile
··· 5 5 6 6 apparmor-y := apparmorfs.o audit.o capability.o task.o ipc.o lib.o match.o \ 7 7 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ 8 - resource.o secid.o file.o policy_ns.o label.o mount.o net.o 8 + resource.o secid.o file.o policy_ns.o label.o mount.o net.o \ 9 + policy_compat.o 9 10 apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o 10 11 11 12 clean-files := capability_names.h rlim_names.h net_names.h
+33
security/apparmor/include/policy_compat.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * AppArmor security module 4 + * 5 + * Code to provide backwards compatibility with older policy versions, 6 + * by converting/mapping older policy formats into the newer internal 7 + * formats. 8 + * 9 + * Copyright 2022 Canonical Ltd. 10 + */ 11 + 12 + #ifndef __POLICY_COMPAT_H 13 + #define __POLICY_COMPAT_H 14 + 15 + #include "policy.h" 16 + 17 + #define K_ABI_MASK 0x3ff 18 + #define FORCE_COMPLAIN_FLAG 0x800 19 + #define VERSION_LT(X, Y) (((X) & K_ABI_MASK) < ((Y) & K_ABI_MASK)) 20 + #define VERSION_LE(X, Y) (((X) & K_ABI_MASK) <= ((Y) & K_ABI_MASK)) 21 + #define VERSION_GT(X, Y) (((X) & K_ABI_MASK) > ((Y) & K_ABI_MASK)) 22 + 23 + #define v5 5 /* base version */ 24 + #define v6 6 /* per entry policydb mediation check */ 25 + #define v7 7 26 + #define v8 8 /* full network masking */ 27 + #define v9 9 /* xbits are used as permission bits in policydb */ 28 + 29 + int aa_compat_map_xmatch(struct aa_policydb *policy); 30 + int aa_compat_map_policy(struct aa_policydb *policy, u32 version); 31 + int aa_compat_map_file(struct aa_policydb *policy); 32 + 33 + #endif /* __POLICY_COMPAT_H */
+1
security/apparmor/include/policy_unpack.h
··· 16 16 #include <linux/dcache.h> 17 17 #include <linux/workqueue.h> 18 18 19 + 19 20 struct aa_load_ent { 20 21 struct list_head list; 21 22 struct aa_profile *new;
+319
security/apparmor/policy_compat.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * AppArmor security module 4 + * 5 + * This file contains AppArmor functions for unpacking policy loaded 6 + * from userspace. 7 + * 8 + * Copyright (C) 1998-2008 Novell/SUSE 9 + * Copyright 2009-2022 Canonical Ltd. 10 + * 11 + * Code to provide backwards compatibility with older policy versions, 12 + * by converting/mapping older policy formats into the newer internal 13 + * formats. 14 + */ 15 + 16 + #include <linux/ctype.h> 17 + #include <linux/errno.h> 18 + 19 + #include "include/lib.h" 20 + #include "include/policy_unpack.h" 21 + #include "include/policy_compat.h" 22 + 23 + /* remap old accept table embedded permissions to separate permission table */ 24 + static u32 dfa_map_xindex(u16 mask) 25 + { 26 + u16 old_index = (mask >> 10) & 0xf; 27 + u32 index = 0; 28 + 29 + if (mask & 0x100) 30 + index |= AA_X_UNSAFE; 31 + if (mask & 0x200) 32 + index |= AA_X_INHERIT; 33 + if (mask & 0x80) 34 + index |= AA_X_UNCONFINED; 35 + 36 + if (old_index == 1) { 37 + index |= AA_X_UNCONFINED; 38 + } else if (old_index == 2) { 39 + index |= AA_X_NAME; 40 + } else if (old_index == 3) { 41 + index |= AA_X_NAME | AA_X_CHILD; 42 + } else if (old_index) { 43 + index |= AA_X_TABLE; 44 + index |= old_index - 4; 45 + } 46 + 47 + return index; 48 + } 49 + 50 + /* 51 + * map old dfa inline permissions to new format 52 + */ 53 + #define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \ 54 + ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) 55 + #define dfa_user_xbits(dfa, state) (((ACCEPT_TABLE(dfa)[state]) >> 7) & 0x7f) 56 + #define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f) 57 + #define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f) 58 + #define dfa_user_xindex(dfa, state) \ 59 + (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff)) 60 + 61 + #define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \ 62 + 0x7f) | \ 63 + ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) 64 + #define dfa_other_xbits(dfa, state) \ 65 + ((((ACCEPT_TABLE(dfa)[state]) >> 7) >> 14) & 0x7f) 66 + #define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f) 67 + #define dfa_other_quiet(dfa, state) \ 68 + ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f) 69 + #define dfa_other_xindex(dfa, state) \ 70 + dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff) 71 + 72 + /** 73 + * map_old_perms - map old file perms layout to the new layout 74 + * @old: permission set in old mapping 75 + * 76 + * Returns: new permission mapping 77 + */ 78 + static u32 map_old_perms(u32 old) 79 + { 80 + u32 new = old & 0xf; 81 + 82 + if (old & MAY_READ) 83 + new |= AA_MAY_GETATTR | AA_MAY_OPEN; 84 + if (old & MAY_WRITE) 85 + new |= AA_MAY_SETATTR | AA_MAY_CREATE | AA_MAY_DELETE | 86 + AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_OPEN; 87 + if (old & 0x10) 88 + new |= AA_MAY_LINK; 89 + /* the old mapping lock and link_subset flags where overlaid 90 + * and use was determined by part of a pair that they were in 91 + */ 92 + if (old & 0x20) 93 + new |= AA_MAY_LOCK | AA_LINK_SUBSET; 94 + if (old & 0x40) /* AA_EXEC_MMAP */ 95 + new |= AA_EXEC_MMAP; 96 + 97 + return new; 98 + } 99 + 100 + static void compute_fperms_allow(struct aa_perms *perms, struct aa_dfa *dfa, 101 + aa_state_t state) 102 + { 103 + perms->allow |= AA_MAY_GETATTR; 104 + 105 + /* change_profile wasn't determined by ownership in old mapping */ 106 + if (ACCEPT_TABLE(dfa)[state] & 0x80000000) 107 + perms->allow |= AA_MAY_CHANGE_PROFILE; 108 + if (ACCEPT_TABLE(dfa)[state] & 0x40000000) 109 + perms->allow |= AA_MAY_ONEXEC; 110 + } 111 + 112 + static struct aa_perms compute_fperms_user(struct aa_dfa *dfa, 113 + aa_state_t state) 114 + { 115 + struct aa_perms perms = { }; 116 + 117 + perms.allow = map_old_perms(dfa_user_allow(dfa, state)); 118 + perms.audit = map_old_perms(dfa_user_audit(dfa, state)); 119 + perms.quiet = map_old_perms(dfa_user_quiet(dfa, state)); 120 + perms.xindex = dfa_user_xindex(dfa, state); 121 + 122 + compute_fperms_allow(&perms, dfa, state); 123 + 124 + return perms; 125 + } 126 + 127 + static struct aa_perms compute_fperms_other(struct aa_dfa *dfa, 128 + aa_state_t state) 129 + { 130 + struct aa_perms perms = { }; 131 + 132 + perms.allow = map_old_perms(dfa_other_allow(dfa, state)); 133 + perms.audit = map_old_perms(dfa_other_audit(dfa, state)); 134 + perms.quiet = map_old_perms(dfa_other_quiet(dfa, state)); 135 + perms.xindex = dfa_other_xindex(dfa, state); 136 + 137 + compute_fperms_allow(&perms, dfa, state); 138 + 139 + return perms; 140 + } 141 + 142 + /** 143 + * aa_compute_fperms - convert dfa compressed perms to internal perms and store 144 + * them so they can be retrieved later. 145 + * @dfa: a dfa using fperms to remap to internal permissions 146 + * 147 + * Returns: remapped perm table 148 + */ 149 + static struct aa_perms *compute_fperms(struct aa_dfa *dfa) 150 + { 151 + aa_state_t state; 152 + unsigned int state_count; 153 + struct aa_perms *table; 154 + 155 + AA_BUG(!dfa); 156 + 157 + state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; 158 + /* DFAs are restricted from having a state_count of less than 2 */ 159 + table = kvcalloc(state_count * 2, sizeof(struct aa_perms), GFP_KERNEL); 160 + if (!table) 161 + return NULL; 162 + 163 + /* zero init so skip the trap state (state == 0) */ 164 + for (state = 1; state < state_count; state++) { 165 + table[state * 2] = compute_fperms_user(dfa, state); 166 + table[state * 2 + 1] = compute_fperms_other(dfa, state); 167 + } 168 + 169 + return table; 170 + } 171 + 172 + static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch) 173 + { 174 + struct aa_perms *perms; 175 + int state; 176 + int state_count; 177 + 178 + AA_BUG(!xmatch); 179 + 180 + state_count = xmatch->tables[YYTD_ID_BASE]->td_lolen; 181 + /* DFAs are restricted from having a state_count of less than 2 */ 182 + perms = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL); 183 + 184 + /* zero init so skip the trap state (state == 0) */ 185 + for (state = 1; state < state_count; state++) 186 + perms[state].allow = dfa_user_allow(xmatch, state); 187 + 188 + return perms; 189 + } 190 + 191 + static u32 map_other(u32 x) 192 + { 193 + return ((x & 0x3) << 8) | /* SETATTR/GETATTR */ 194 + ((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */ 195 + ((x & 0x60) << 19); /* SETOPT/GETOPT */ 196 + } 197 + 198 + static u32 map_xbits(u32 x) 199 + { 200 + return ((x & 0x1) << 7) | 201 + ((x & 0x7e) << 9); 202 + } 203 + 204 + static struct aa_perms compute_perms_entry(struct aa_dfa *dfa, 205 + aa_state_t state, 206 + u32 version) 207 + { 208 + struct aa_perms perms = { }; 209 + 210 + perms.allow = dfa_user_allow(dfa, state); 211 + perms.audit = dfa_user_audit(dfa, state); 212 + perms.quiet = dfa_user_quiet(dfa, state); 213 + 214 + /* 215 + * This mapping is convulated due to history. 216 + * v1-v4: only file perms, which are handled by compute_fperms 217 + * v5: added policydb which dropped user conditional to gain new 218 + * perm bits, but had to map around the xbits because the 219 + * userspace compiler was still munging them. 220 + * v9: adds using the xbits in policydb because the compiler now 221 + * supports treating policydb permission bits different. 222 + * Unfortunately there is no way to force auditing on the 223 + * perms represented by the xbits 224 + */ 225 + perms.allow |= map_other(dfa_other_allow(dfa, state)); 226 + if (VERSION_LE(version, v8)) 227 + perms.allow |= AA_MAY_LOCK; 228 + else 229 + perms.allow |= map_xbits(dfa_user_xbits(dfa, state)); 230 + 231 + /* 232 + * for v5-v9 perm mapping in the policydb, the other set is used 233 + * to extend the general perm set 234 + */ 235 + perms.audit |= map_other(dfa_other_audit(dfa, state)); 236 + perms.quiet |= map_other(dfa_other_quiet(dfa, state)); 237 + if (VERSION_GT(version, v8)) 238 + perms.quiet |= map_xbits(dfa_other_xbits(dfa, state)); 239 + 240 + return perms; 241 + } 242 + 243 + static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version) 244 + { 245 + unsigned int state; 246 + unsigned int state_count; 247 + struct aa_perms *table; 248 + 249 + AA_BUG(!dfa); 250 + 251 + state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; 252 + /* DFAs are restricted from having a state_count of less than 2 */ 253 + table = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL); 254 + if (!table) 255 + return NULL; 256 + 257 + /* zero init so skip the trap state (state == 0) */ 258 + for (state = 1; state < state_count; state++) 259 + table[state] = compute_perms_entry(dfa, state, version); 260 + 261 + return table; 262 + } 263 + 264 + /** 265 + * remap_dfa_accept - remap old dfa accept table to be an index 266 + * @dfa: dfa to do the remapping on 267 + * @factor: scaling factor for the index conversion. 268 + * 269 + * Used in conjunction with compute_Xperms, it converts old style perms 270 + * that are encoded in the dfa accept tables to the new style where 271 + * there is a permission table and the accept table is an index into 272 + * the permission table. 273 + */ 274 + static void remap_dfa_accept(struct aa_dfa *dfa, unsigned int factor) 275 + { 276 + unsigned int state; 277 + unsigned int state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; 278 + 279 + AA_BUG(!dfa); 280 + 281 + for (state = 0; state < state_count; state++) 282 + ACCEPT_TABLE(dfa)[state] = state * factor; 283 + kvfree(dfa->tables[YYTD_ID_ACCEPT2]); 284 + dfa->tables[YYTD_ID_ACCEPT2] = NULL; 285 + } 286 + 287 + /* TODO: merge different dfa mappings into single map_policy fn */ 288 + int aa_compat_map_xmatch(struct aa_policydb *policy) 289 + { 290 + policy->perms = compute_xmatch_perms(policy->dfa); 291 + if (!policy->perms) 292 + return -ENOMEM; 293 + 294 + remap_dfa_accept(policy->dfa, 1); 295 + 296 + return 0; 297 + } 298 + 299 + int aa_compat_map_policy(struct aa_policydb *policy, u32 version) 300 + { 301 + policy->perms = compute_perms(policy->dfa, version); 302 + if (!policy->perms) 303 + return -ENOMEM; 304 + 305 + remap_dfa_accept(policy->dfa, 1); 306 + 307 + return 0; 308 + } 309 + 310 + int aa_compat_map_file(struct aa_policydb *policy) 311 + { 312 + policy->perms = compute_fperms(policy->dfa); 313 + if (!policy->perms) 314 + return -ENOMEM; 315 + 316 + remap_dfa_accept(policy->dfa, 2); 317 + 318 + return 0; 319 + }
+4 -286
security/apparmor/policy_unpack.c
··· 27 27 #include "include/path.h" 28 28 #include "include/policy.h" 29 29 #include "include/policy_unpack.h" 30 + #include "include/policy_compat.h" 30 31 31 - #define K_ABI_MASK 0x3ff 32 - #define FORCE_COMPLAIN_FLAG 0x800 33 - #define VERSION_LT(X, Y) (((X) & K_ABI_MASK) < ((Y) & K_ABI_MASK)) 34 - #define VERSION_LE(X, Y) (((X) & K_ABI_MASK) <= ((Y) & K_ABI_MASK)) 35 - #define VERSION_GT(X, Y) (((X) & K_ABI_MASK) > ((Y) & K_ABI_MASK)) 36 - 37 - #define v5 5 /* base version */ 38 - #define v6 6 /* per entry policydb mediation check */ 39 - #define v7 7 40 - #define v8 8 /* full network masking */ 41 - #define v9 9 /* xbits are used as permission bits in policydb */ 42 32 43 33 /* 44 34 * The AppArmor interface treats data as a type byte followed by the ··· 661 671 return strcmp(data->key, *key); 662 672 } 663 673 664 - /* remap old accept table embedded permissions to separate permission table */ 665 - static u32 dfa_map_xindex(u16 mask) 666 - { 667 - u16 old_index = (mask >> 10) & 0xf; 668 - u32 index = 0; 669 - 670 - if (mask & 0x100) 671 - index |= AA_X_UNSAFE; 672 - if (mask & 0x200) 673 - index |= AA_X_INHERIT; 674 - if (mask & 0x80) 675 - index |= AA_X_UNCONFINED; 676 - 677 - if (old_index == 1) { 678 - index |= AA_X_UNCONFINED; 679 - } else if (old_index == 2) { 680 - index |= AA_X_NAME; 681 - } else if (old_index == 3) { 682 - index |= AA_X_NAME | AA_X_CHILD; 683 - } else if (old_index) { 684 - index |= AA_X_TABLE; 685 - index |= old_index - 4; 686 - } 687 - 688 - return index; 689 - } 690 - 691 - /* 692 - * map old dfa inline permissions to new format 693 - */ 694 - #define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \ 695 - ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) 696 - #define dfa_user_xbits(dfa, state) (((ACCEPT_TABLE(dfa)[state]) >> 7) & 0x7f) 697 - #define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f) 698 - #define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f) 699 - #define dfa_user_xindex(dfa, state) \ 700 - (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff)) 701 - 702 - #define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \ 703 - 0x7f) | \ 704 - ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) 705 - #define dfa_other_xbits(dfa, state) \ 706 - ((((ACCEPT_TABLE(dfa)[state]) >> 7) >> 14) & 0x7f) 707 - #define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f) 708 - #define dfa_other_quiet(dfa, state) \ 709 - ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f) 710 - #define dfa_other_xindex(dfa, state) \ 711 - dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff) 712 - 713 - /** 714 - * map_old_perms - map old file perms layout to the new layout 715 - * @old: permission set in old mapping 716 - * 717 - * Returns: new permission mapping 718 - */ 719 - static u32 map_old_perms(u32 old) 720 - { 721 - u32 new = old & 0xf; 722 - 723 - if (old & MAY_READ) 724 - new |= AA_MAY_GETATTR | AA_MAY_OPEN; 725 - if (old & MAY_WRITE) 726 - new |= AA_MAY_SETATTR | AA_MAY_CREATE | AA_MAY_DELETE | 727 - AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_OPEN; 728 - if (old & 0x10) 729 - new |= AA_MAY_LINK; 730 - /* the old mapping lock and link_subset flags where overlaid 731 - * and use was determined by part of a pair that they were in 732 - */ 733 - if (old & 0x20) 734 - new |= AA_MAY_LOCK | AA_LINK_SUBSET; 735 - if (old & 0x40) /* AA_EXEC_MMAP */ 736 - new |= AA_EXEC_MMAP; 737 - 738 - return new; 739 - } 740 - 741 - static void compute_fperms_allow(struct aa_perms *perms, struct aa_dfa *dfa, 742 - aa_state_t state) 743 - { 744 - perms->allow |= AA_MAY_GETATTR; 745 - 746 - /* change_profile wasn't determined by ownership in old mapping */ 747 - if (ACCEPT_TABLE(dfa)[state] & 0x80000000) 748 - perms->allow |= AA_MAY_CHANGE_PROFILE; 749 - if (ACCEPT_TABLE(dfa)[state] & 0x40000000) 750 - perms->allow |= AA_MAY_ONEXEC; 751 - } 752 - 753 - static struct aa_perms compute_fperms_user(struct aa_dfa *dfa, 754 - aa_state_t state) 755 - { 756 - struct aa_perms perms = { }; 757 - 758 - perms.allow = map_old_perms(dfa_user_allow(dfa, state)); 759 - perms.audit = map_old_perms(dfa_user_audit(dfa, state)); 760 - perms.quiet = map_old_perms(dfa_user_quiet(dfa, state)); 761 - perms.xindex = dfa_user_xindex(dfa, state); 762 - 763 - compute_fperms_allow(&perms, dfa, state); 764 - 765 - return perms; 766 - } 767 - 768 - static struct aa_perms compute_fperms_other(struct aa_dfa *dfa, 769 - aa_state_t state) 770 - { 771 - struct aa_perms perms = { }; 772 - 773 - perms.allow = map_old_perms(dfa_other_allow(dfa, state)); 774 - perms.audit = map_old_perms(dfa_other_audit(dfa, state)); 775 - perms.quiet = map_old_perms(dfa_other_quiet(dfa, state)); 776 - perms.xindex = dfa_other_xindex(dfa, state); 777 - 778 - compute_fperms_allow(&perms, dfa, state); 779 - 780 - return perms; 781 - } 782 - 783 - /** 784 - * aa_compute_fperms - convert dfa compressed perms to internal perms and store 785 - * them so they can be retrieved later. 786 - * @dfa: a dfa using fperms to remap to internal permissions 787 - * 788 - * Returns: remapped perm table 789 - */ 790 - static struct aa_perms *compute_fperms(struct aa_dfa *dfa) 791 - { 792 - aa_state_t state; 793 - unsigned int state_count; 794 - struct aa_perms *table; 795 - 796 - AA_BUG(!dfa); 797 - 798 - state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; 799 - /* DFAs are restricted from having a state_count of less than 2 */ 800 - table = kvcalloc(state_count * 2, sizeof(struct aa_perms), GFP_KERNEL); 801 - if (!table) 802 - return NULL; 803 - 804 - /* zero init so skip the trap state (state == 0) */ 805 - for (state = 1; state < state_count; state++) { 806 - table[state * 2] = compute_fperms_user(dfa, state); 807 - table[state * 2 + 1] = compute_fperms_other(dfa, state); 808 - } 809 - 810 - return table; 811 - } 812 - 813 - static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch) 814 - { 815 - struct aa_perms *perms; 816 - int state; 817 - int state_count; 818 - 819 - AA_BUG(!xmatch); 820 - 821 - state_count = xmatch->tables[YYTD_ID_BASE]->td_lolen; 822 - /* DFAs are restricted from having a state_count of less than 2 */ 823 - perms = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL); 824 - 825 - /* zero init so skip the trap state (state == 0) */ 826 - for (state = 1; state < state_count; state++) 827 - perms[state].allow = dfa_user_allow(xmatch, state); 828 - 829 - return perms; 830 - } 831 - 832 - static u32 map_other(u32 x) 833 - { 834 - return ((x & 0x3) << 8) | /* SETATTR/GETATTR */ 835 - ((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */ 836 - ((x & 0x60) << 19); /* SETOPT/GETOPT */ 837 - } 838 - 839 - static u32 map_xbits(u32 x) 840 - { 841 - return ((x & 0x1) << 7) | 842 - ((x & 0x7e) << 9); 843 - } 844 - 845 - static struct aa_perms compute_perms_entry(struct aa_dfa *dfa, 846 - aa_state_t state, 847 - u32 version) 848 - { 849 - struct aa_perms perms = { }; 850 - 851 - perms.allow = dfa_user_allow(dfa, state); 852 - perms.audit = dfa_user_audit(dfa, state); 853 - perms.quiet = dfa_user_quiet(dfa, state); 854 - 855 - /* 856 - * This mapping is convulated due to history. 857 - * v1-v4: only file perms, which are handled by compute_fperms 858 - * v5: added policydb which dropped user conditional to gain new 859 - * perm bits, but had to map around the xbits because the 860 - * userspace compiler was still munging them. 861 - * v9: adds using the xbits in policydb because the compiler now 862 - * supports treating policydb permission bits different. 863 - * Unfortunately there is no way to force auditing on the 864 - * perms represented by the xbits 865 - */ 866 - perms.allow |= map_other(dfa_other_allow(dfa, state)); 867 - if (VERSION_LE(version, v8)) 868 - perms.allow |= AA_MAY_LOCK; 869 - else 870 - perms.allow |= map_xbits(dfa_user_xbits(dfa, state)); 871 - 872 - /* 873 - * for v5-v9 perm mapping in the policydb, the other set is used 874 - * to extend the general perm set 875 - */ 876 - perms.audit |= map_other(dfa_other_audit(dfa, state)); 877 - perms.quiet |= map_other(dfa_other_quiet(dfa, state)); 878 - if (VERSION_GT(version, v8)) 879 - perms.quiet |= map_xbits(dfa_other_xbits(dfa, state)); 880 - 881 - return perms; 882 - } 883 - 884 - static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version) 885 - { 886 - unsigned int state; 887 - unsigned int state_count; 888 - struct aa_perms *table; 889 - 890 - AA_BUG(!dfa); 891 - 892 - state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; 893 - /* DFAs are restricted from having a state_count of less than 2 */ 894 - table = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL); 895 - if (!table) 896 - return NULL; 897 - 898 - /* zero init so skip the trap state (state == 0) */ 899 - for (state = 1; state < state_count; state++) 900 - table[state] = compute_perms_entry(dfa, state, version); 901 - 902 - return table; 903 - } 904 - 905 - /** 906 - * remap_dfa_accept - remap old dfa accept table to be an index 907 - * @dfa: dfa to do the remapping on 908 - * @factor: scaling factor for the index conversion. 909 - * 910 - * Used in conjunction with compute_Xperms, it converts old style perms 911 - * that are encoded in the dfa accept tables to the new style where 912 - * there is a permission table and the accept table is an index into 913 - * the permission table. 914 - */ 915 - static void remap_dfa_accept(struct aa_dfa *dfa, unsigned int factor) 916 - { 917 - unsigned int state; 918 - unsigned int state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; 919 - 920 - AA_BUG(!dfa); 921 - 922 - for (state = 0; state < state_count; state++) 923 - ACCEPT_TABLE(dfa)[state] = state * factor; 924 - kvfree(dfa->tables[YYTD_ID_ACCEPT2]); 925 - dfa->tables[YYTD_ID_ACCEPT2] = NULL; 926 - } 927 - 928 674 /** 929 675 * unpack_profile - unpack a serialized profile 930 676 * @e: serialized data extent information (NOT NULL) ··· 727 1001 } 728 1002 profile->xmatch_len = tmp; 729 1003 profile->xmatch.start[AA_CLASS_XMATCH] = DFA_START; 730 - profile->xmatch.perms = compute_xmatch_perms(profile->xmatch.dfa); 731 - if (!profile->xmatch.perms) { 1004 + if (aa_compat_map_xmatch(&profile->xmatch)) { 732 1005 info = "failed to convert xmatch permission table"; 733 1006 goto fail; 734 1007 } 735 - remap_dfa_accept(profile->xmatch.dfa, 1); 736 1008 } 737 1009 738 1010 /* disconnected attachment string is optional */ ··· 855 1131 } 856 1132 if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 857 1133 goto fail; 858 - profile->policy.perms = compute_perms(profile->policy.dfa, 859 - e->version); 860 - if (!profile->policy.perms) { 1134 + if (aa_compat_map_policy(&profile->policy, e->version)) { 861 1135 info = "failed to remap policydb permission table"; 862 1136 goto fail; 863 1137 } 864 - /* Do not remap internal dfas */ 865 - remap_dfa_accept(profile->policy.dfa, 1); 866 1138 } else 867 1139 profile->policy.dfa = aa_get_dfa(nulldfa); 868 1140 ··· 874 1154 "dfa_start")) 875 1155 /* default start state */ 876 1156 profile->file.start[AA_CLASS_FILE] = DFA_START; 877 - profile->file.perms = compute_fperms(profile->file.dfa); 878 - if (!profile->file.perms) { 1157 + if (aa_compat_map_file(&profile->file)) { 879 1158 info = "failed to remap file permission table"; 880 1159 goto fail; 881 1160 } 882 - remap_dfa_accept(profile->file.dfa, 2); 883 1161 if (!unpack_trans_table(e, profile)) { 884 1162 info = "failed to unpack profile transition table"; 885 1163 goto fail;