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: add additional flags to extended permission.

This is a step towards merging the file and policy state machines.

With the switch to extended permissions the state machine's ACCEPT2
table became unused freeing it up to store state specific flags. The
first flags to be stored are FLAG_OWNER and FLAG other which paves the
way towards merging the file and policydb perms into a single
permission table.

Currently Lookups based on the objects ownership conditional will
still need separate fns, this will be address in a following patch.

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

+54 -21
+3 -2
security/apparmor/apparmorfs.c
··· 626 626 if (state) { 627 627 struct path_cond cond = { }; 628 628 629 - tmp = *(aa_lookup_fperms(rules->file, state, &cond)); 629 + tmp = *(aa_lookup_condperms(current_fsuid(), 630 + rules->file, state, &cond)); 630 631 } 631 632 } else if (rules->policy->dfa) { 632 633 if (!RULE_MEDIATES(rules, *match_str)) ··· 2366 2365 AA_SFS_FILE_BOOLEAN("set_load", 1), 2367 2366 /* number of out of band transitions supported */ 2368 2367 AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED), 2369 - AA_SFS_FILE_U64("permstable32_version", 1), 2368 + AA_SFS_FILE_U64("permstable32_version", 3), 2370 2369 AA_SFS_FILE_STRING("permstable32", PERMS32STR), 2371 2370 AA_SFS_FILE_U64("state32", 1), 2372 2371 AA_SFS_DIR("unconfined_restrictions", aa_sfs_entry_unconfined),
+6 -3
security/apparmor/domain.c
··· 154 154 if (!state) 155 155 goto fail; 156 156 } 157 - *perms = *(aa_lookup_fperms(rules->file, state, &cond)); 157 + *perms = *(aa_lookup_condperms(current_fsuid(), rules->file, state, 158 + &cond)); 158 159 aa_apply_modes_to_perms(profile, perms); 159 160 if ((perms->allow & request) != request) 160 161 return -EACCES; ··· 210 209 return 0; 211 210 212 211 next: 213 - tmp = *(aa_lookup_fperms(rules->file, state, &cond)); 212 + tmp = *(aa_lookup_condperms(current_fsuid(), rules->file, state, 213 + &cond)); 214 214 aa_apply_modes_to_perms(profile, &tmp); 215 215 aa_perms_accum(perms, &tmp); 216 216 label_for_each_cont(i, label, tp) { ··· 220 218 state = match_component(profile, tp, stack, start); 221 219 if (!state) 222 220 goto fail; 223 - tmp = *(aa_lookup_fperms(rules->file, state, &cond)); 221 + tmp = *(aa_lookup_condperms(current_fsuid(), rules->file, state, 222 + &cond)); 224 223 aa_apply_modes_to_perms(profile, &tmp); 225 224 aa_perms_accum(perms, &tmp); 226 225 }
+14 -9
security/apparmor/file.c
··· 169 169 struct aa_perms default_perms = {}; 170 170 /** 171 171 * aa_lookup_fperms - convert dfa compressed perms to internal perms 172 - * @file_rules: the aa_policydb to lookup perms for (NOT NULL) 172 + * @subj_uid: uid to use for subject owner test 173 + * @rules: the aa_policydb to lookup perms for (NOT NULL) 173 174 * @state: state in dfa 174 175 * @cond: conditions to consider (NOT NULL) 175 176 * ··· 178 177 * 179 178 * Returns: a pointer to a file permission set 180 179 */ 181 - struct aa_perms *aa_lookup_fperms(struct aa_policydb *file_rules, 182 - aa_state_t state, struct path_cond *cond) 180 + struct aa_perms *aa_lookup_condperms(kuid_t subj_uid, struct aa_policydb *rules, 181 + aa_state_t state, struct path_cond *cond) 183 182 { 184 - unsigned int index = ACCEPT_TABLE(file_rules->dfa)[state]; 183 + unsigned int index = ACCEPT_TABLE(rules->dfa)[state]; 185 184 186 - if (!(file_rules->perms)) 185 + if (!(rules->perms)) 187 186 return &default_perms; 188 187 189 - if (uid_eq(current_fsuid(), cond->uid)) 190 - return &(file_rules->perms[index]); 188 + if ((ACCEPT_TABLE2(rules->dfa)[state] & ACCEPT_FLAG_OWNER)) { 189 + if (uid_eq(subj_uid, cond->uid)) 190 + return &(rules->perms[index]); 191 + return &(rules->perms[index + 1]); 192 + } 191 193 192 - return &(file_rules->perms[index + 1]); 194 + return &(rules->perms[index]); 193 195 } 194 196 195 197 /** ··· 211 207 { 212 208 aa_state_t state; 213 209 state = aa_dfa_match(file_rules->dfa, start, name); 214 - *perms = *(aa_lookup_fperms(file_rules, state, cond)); 210 + *perms = *(aa_lookup_condperms(current_fsuid(), file_rules, state, 211 + cond)); 215 212 216 213 return state; 217 214 }
+3 -2
security/apparmor/include/file.h
··· 77 77 const char *target, struct aa_label *tlabel, kuid_t ouid, 78 78 const char *info, int error); 79 79 80 - struct aa_perms *aa_lookup_fperms(struct aa_policydb *file_rules, 81 - aa_state_t state, struct path_cond *cond); 80 + struct aa_perms *aa_lookup_condperms(kuid_t subj_uid, 81 + struct aa_policydb *file_rules, 82 + aa_state_t state, struct path_cond *cond); 82 83 aa_state_t aa_str_perms(struct aa_policydb *file_rules, aa_state_t start, 83 84 const char *name, struct path_cond *cond, 84 85 struct aa_perms *perms);
+6 -1
security/apparmor/include/policy.h
··· 59 59 60 60 #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) 61 61 62 + /* flags in the dfa accept2 table */ 63 + enum dfa_accept_flags { 64 + ACCEPT_FLAG_OWNER = 1, 65 + }; 66 + 62 67 /* 63 68 * FIXME: currently need a clean way to replace and remove profiles as a 64 69 * set. It should be done at the namespace level. ··· 129 124 kref_put(&pdb->count, aa_pdb_free_kref); 130 125 } 131 126 127 + /* lookup perm that doesn't have and object conditional */ 132 128 static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy, 133 129 aa_state_t state) 134 130 { ··· 140 134 141 135 return &(policy->perms[index]); 142 136 } 143 - 144 137 145 138 /* struct aa_data - generic data structure 146 139 * key: name for retrieving this data
+3 -3
security/apparmor/policy_compat.c
··· 286 286 287 287 AA_BUG(!dfa); 288 288 289 - for (state = 0; state < state_count; state++) 289 + for (state = 0; state < state_count; state++) { 290 290 ACCEPT_TABLE(dfa)[state] = state * factor; 291 - kvfree(dfa->tables[YYTD_ID_ACCEPT2]); 292 - dfa->tables[YYTD_ID_ACCEPT2] = NULL; 291 + ACCEPT_TABLE2(dfa)[state] = factor > 1 ? ACCEPT_FLAG_OWNER : 0; 292 + } 293 293 } 294 294 295 295 /* TODO: merge different dfa mappings into single map_policy fn */
+19 -1
security/apparmor/policy_unpack.c
··· 716 716 void *pos = e->pos; 717 717 int i, flags, error = -EPROTO; 718 718 ssize_t size; 719 + u32 version = 0; 719 720 720 721 pdb = aa_alloc_pdb(GFP_KERNEL); 721 722 if (!pdb) ··· 734 733 if (pdb->perms) { 735 734 /* perms table present accept is index */ 736 735 flags = TO_ACCEPT1_FLAG(YYTD_DATA32); 736 + if (aa_unpack_u32(e, &version, "permsv") && version > 2) 737 + /* accept2 used for dfa flags */ 738 + flags |= TO_ACCEPT2_FLAG(YYTD_DATA32); 737 739 } else { 738 740 /* packed perms in accept1 and accept2 */ 739 741 flags = TO_ACCEPT1_FLAG(YYTD_DATA32) | ··· 774 770 } 775 771 } 776 772 773 + if (pdb->perms && version <= 2) { 774 + /* add dfa flags table missing in v2 */ 775 + u32 noents = pdb->dfa->tables[YYTD_ID_ACCEPT]->td_lolen; 776 + u16 tdflags = pdb->dfa->tables[YYTD_ID_ACCEPT]->td_flags; 777 + size_t tsize = table_size(noents, tdflags); 778 + 779 + pdb->dfa->tables[YYTD_ID_ACCEPT2] = kvzalloc(tsize, GFP_KERNEL); 780 + if (!pdb->dfa->tables[YYTD_ID_ACCEPT2]) { 781 + *info = "failed to alloc dfa flags table"; 782 + goto out; 783 + } 784 + pdb->dfa->tables[YYTD_ID_ACCEPT2]->td_lolen = noents; 785 + pdb->dfa->tables[YYTD_ID_ACCEPT2]->td_flags = tdflags; 786 + } 777 787 /* 778 788 * Unfortunately due to a bug in earlier userspaces, a 779 789 * transition table may be present even when the dfa is ··· 803 785 804 786 /* TODO: move compat mapping here, requires dfa merging first */ 805 787 /* TODO: move verify here, it has to be done after compat mappings */ 806 - 788 + out: 807 789 *policy = pdb; 808 790 return 0; 809 791