Skip to content

Commit 70806ee

Browse files
committed
Merge tag 'apparmor-pr-2023-07-06' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
Pull apparmor updates from John Johansen: - fix missing error check for rhashtable_insert_fast - add missing failure check in compute_xmatch_perms - fix policy_compat permission remap with extended permissions - fix profile verification and enable it - fix kzalloc perms tables for shared dfas - Fix kernel-doc header for verify_dfa_accept_index - aa_buffer: Convert 1-element array to flexible array - Return directly after a failed kzalloc() in two functions - fix use of strcpy in policy_unpack_test - fix kernel-doc complaints - Fix some kernel-doc comments * tag 'apparmor-pr-2023-07-06' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: apparmor: Fix kernel-doc header for verify_dfa_accept_index apparmor: fix: kzalloc perms tables for shared dfas apparmor: fix profile verification and enable it apparmor: fix policy_compat permission remap with extended permissions apparmor: aa_buffer: Convert 1-element array to flexible array apparmor: add missing failure check in compute_xmatch_perms apparmor: fix missing error check for rhashtable_insert_fast apparmor: Return directly after a failed kzalloc() in two functions AppArmor: Fix some kernel-doc comments apparmor: fix use of strcpy in policy_unpack_test apparmor: fix kernel-doc complaints
2 parents 5133c9e + 3f069c4 commit 70806ee

File tree

8 files changed

+110
-68
lines changed

8 files changed

+110
-68
lines changed

security/apparmor/crypto.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ unsigned int aa_hash_size(void)
2828
char *aa_calc_hash(void *data, size_t len)
2929
{
3030
SHASH_DESC_ON_STACK(desc, apparmor_tfm);
31-
char *hash = NULL;
32-
int error = -ENOMEM;
31+
char *hash;
32+
int error;
3333

3434
if (!apparmor_tfm)
3535
return NULL;
3636

3737
hash = kzalloc(apparmor_hash_size, GFP_KERNEL);
3838
if (!hash)
39-
goto fail;
39+
return ERR_PTR(-ENOMEM);
4040

4141
desc->tfm = apparmor_tfm;
4242

@@ -62,7 +62,7 @@ int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
6262
size_t len)
6363
{
6464
SHASH_DESC_ON_STACK(desc, apparmor_tfm);
65-
int error = -ENOMEM;
65+
int error;
6666
__le32 le32_version = cpu_to_le32(version);
6767

6868
if (!aa_g_hash_policy)
@@ -73,7 +73,7 @@ int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
7373

7474
profile->hash = kzalloc(apparmor_hash_size, GFP_KERNEL);
7575
if (!profile->hash)
76-
goto fail;
76+
return -ENOMEM;
7777

7878
desc->tfm = apparmor_tfm;
7979

security/apparmor/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ static int path_name(const char *op, struct aa_label *label,
161161
return 0;
162162
}
163163

164+
struct aa_perms default_perms = {};
164165
/**
165166
* aa_lookup_fperms - convert dfa compressed perms to internal perms
166167
* @dfa: dfa to lookup perms for (NOT NULL)
@@ -171,7 +172,6 @@ static int path_name(const char *op, struct aa_label *label,
171172
*
172173
* Returns: a pointer to a file permission set
173174
*/
174-
struct aa_perms default_perms = {};
175175
struct aa_perms *aa_lookup_fperms(struct aa_policydb *file_rules,
176176
aa_state_t state, struct path_cond *cond)
177177
{

security/apparmor/lsm.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ int apparmor_initialized;
4646

4747
union aa_buffer {
4848
struct list_head list;
49-
char buffer[1];
49+
DECLARE_FLEX_ARRAY(char, buffer);
5050
};
5151

5252
#define RESERVE_COUNT 2
@@ -1647,7 +1647,7 @@ char *aa_get_buffer(bool in_atomic)
16471647
list_del(&aa_buf->list);
16481648
buffer_count--;
16491649
spin_unlock(&aa_buffers_lock);
1650-
return &aa_buf->buffer[0];
1650+
return aa_buf->buffer;
16511651
}
16521652
if (in_atomic) {
16531653
/*
@@ -1670,7 +1670,7 @@ char *aa_get_buffer(bool in_atomic)
16701670
pr_warn_once("AppArmor: Failed to allocate a memory buffer.\n");
16711671
return NULL;
16721672
}
1673-
return &aa_buf->buffer[0];
1673+
return aa_buf->buffer;
16741674
}
16751675

16761676
void aa_put_buffer(char *buf)
@@ -1747,7 +1747,7 @@ static int __init alloc_buffers(void)
17471747
destroy_buffers();
17481748
return -ENOMEM;
17491749
}
1750-
aa_put_buffer(&aa_buf->buffer[0]);
1750+
aa_put_buffer(aa_buf->buffer);
17511751
}
17521752
return 0;
17531753
}

security/apparmor/policy.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -430,11 +430,9 @@ static struct aa_policy *__lookup_parent(struct aa_ns *ns,
430430
* @hname: hierarchical profile name to find parent of (NOT NULL)
431431
* @gfp: type of allocation.
432432
*
433-
* Returns: NULL on error, parent profile on success
434-
*
435433
* Requires: ns mutex lock held
436434
*
437-
* Returns: unrefcounted parent policy or NULL if error creating
435+
* Return: unrefcounted parent policy on success or %NULL if error creating
438436
* place holder profiles.
439437
*/
440438
static struct aa_policy *__create_missing_ancestors(struct aa_ns *ns,
@@ -591,7 +589,15 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name,
591589
profile->label.flags |= FLAG_NULL;
592590
rules = list_first_entry(&profile->rules, typeof(*rules), list);
593591
rules->file.dfa = aa_get_dfa(nulldfa);
592+
rules->file.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL);
593+
if (!rules->file.perms)
594+
goto fail;
595+
rules->file.size = 2;
594596
rules->policy.dfa = aa_get_dfa(nulldfa);
597+
rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL);
598+
if (!rules->policy.perms)
599+
goto fail;
600+
rules->policy.size = 2;
595601

596602
if (parent) {
597603
profile->path_flags = parent->path_flags;
@@ -602,6 +608,11 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name,
602608
}
603609

604610
return profile;
611+
612+
fail:
613+
aa_free_profile(profile);
614+
615+
return NULL;
605616
}
606617

607618
/**
@@ -828,7 +839,7 @@ bool aa_current_policy_admin_capable(struct aa_ns *ns)
828839
/**
829840
* aa_may_manage_policy - can the current task manage policy
830841
* @label: label to check if it can manage policy
831-
* @op: the policy manipulation operation being done
842+
* @mask: contains the policy manipulation operation being done
832843
*
833844
* Returns: 0 if the task is allowed to manipulate policy else error
834845
*/
@@ -883,7 +894,6 @@ static struct aa_profile *__list_lookup_parent(struct list_head *lh,
883894
* __replace_profile - replace @old with @new on a list
884895
* @old: profile to be replaced (NOT NULL)
885896
* @new: profile to replace @old with (NOT NULL)
886-
* @share_proxy: transfer @old->proxy to @new
887897
*
888898
* Will duplicate and refcount elements that @new inherits from @old
889899
* and will inherit @old children.

security/apparmor/policy_compat.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ static struct aa_perms compute_fperms_other(struct aa_dfa *dfa,
146146
*
147147
* Returns: remapped perm table
148148
*/
149-
static struct aa_perms *compute_fperms(struct aa_dfa *dfa)
149+
static struct aa_perms *compute_fperms(struct aa_dfa *dfa,
150+
u32 *size)
150151
{
151152
aa_state_t state;
152153
unsigned int state_count;
@@ -159,6 +160,7 @@ static struct aa_perms *compute_fperms(struct aa_dfa *dfa)
159160
table = kvcalloc(state_count * 2, sizeof(struct aa_perms), GFP_KERNEL);
160161
if (!table)
161162
return NULL;
163+
*size = state_count * 2;
162164

163165
for (state = 0; state < state_count; state++) {
164166
table[state * 2] = compute_fperms_user(dfa, state);
@@ -168,7 +170,8 @@ static struct aa_perms *compute_fperms(struct aa_dfa *dfa)
168170
return table;
169171
}
170172

171-
static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch)
173+
static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch,
174+
u32 *size)
172175
{
173176
struct aa_perms *perms;
174177
int state;
@@ -179,6 +182,9 @@ static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch)
179182
state_count = xmatch->tables[YYTD_ID_BASE]->td_lolen;
180183
/* DFAs are restricted from having a state_count of less than 2 */
181184
perms = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL);
185+
if (!perms)
186+
return NULL;
187+
*size = state_count;
182188

183189
/* zero init so skip the trap state (state == 0) */
184190
for (state = 1; state < state_count; state++)
@@ -239,7 +245,8 @@ static struct aa_perms compute_perms_entry(struct aa_dfa *dfa,
239245
return perms;
240246
}
241247

242-
static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version)
248+
static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version,
249+
u32 *size)
243250
{
244251
unsigned int state;
245252
unsigned int state_count;
@@ -252,6 +259,7 @@ static struct aa_perms *compute_perms(struct aa_dfa *dfa, u32 version)
252259
table = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL);
253260
if (!table)
254261
return NULL;
262+
*size = state_count;
255263

256264
/* zero init so skip the trap state (state == 0) */
257265
for (state = 1; state < state_count; state++)
@@ -286,7 +294,7 @@ static void remap_dfa_accept(struct aa_dfa *dfa, unsigned int factor)
286294
/* TODO: merge different dfa mappings into single map_policy fn */
287295
int aa_compat_map_xmatch(struct aa_policydb *policy)
288296
{
289-
policy->perms = compute_xmatch_perms(policy->dfa);
297+
policy->perms = compute_xmatch_perms(policy->dfa, &policy->size);
290298
if (!policy->perms)
291299
return -ENOMEM;
292300

@@ -297,7 +305,7 @@ int aa_compat_map_xmatch(struct aa_policydb *policy)
297305

298306
int aa_compat_map_policy(struct aa_policydb *policy, u32 version)
299307
{
300-
policy->perms = compute_perms(policy->dfa, version);
308+
policy->perms = compute_perms(policy->dfa, version, &policy->size);
301309
if (!policy->perms)
302310
return -ENOMEM;
303311

@@ -308,7 +316,7 @@ int aa_compat_map_policy(struct aa_policydb *policy, u32 version)
308316

309317
int aa_compat_map_file(struct aa_policydb *policy)
310318
{
311-
policy->perms = compute_fperms(policy->dfa);
319+
policy->perms = compute_fperms(policy->dfa, &policy->size);
312320
if (!policy->perms)
313321
return -ENOMEM;
314322

security/apparmor/policy_unpack.c

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ static struct aa_dfa *unpack_dfa(struct aa_ext *e, int flags)
448448
/**
449449
* unpack_trans_table - unpack a profile transition table
450450
* @e: serialized data extent information (NOT NULL)
451-
* @table: str table to unpack to (NOT NULL)
451+
* @strs: str table to unpack to (NOT NULL)
452452
*
453453
* Returns: true if table successfully unpacked or not present
454454
*/
@@ -860,10 +860,12 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
860860
}
861861
profile->attach.xmatch_len = tmp;
862862
profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START;
863-
error = aa_compat_map_xmatch(&profile->attach.xmatch);
864-
if (error) {
865-
info = "failed to convert xmatch permission table";
866-
goto fail;
863+
if (!profile->attach.xmatch.perms) {
864+
error = aa_compat_map_xmatch(&profile->attach.xmatch);
865+
if (error) {
866+
info = "failed to convert xmatch permission table";
867+
goto fail;
868+
}
867869
}
868870
}
869871

@@ -983,31 +985,54 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
983985
AA_CLASS_FILE);
984986
if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL))
985987
goto fail;
986-
error = aa_compat_map_policy(&rules->policy, e->version);
987-
if (error) {
988-
info = "failed to remap policydb permission table";
989-
goto fail;
988+
if (!rules->policy.perms) {
989+
error = aa_compat_map_policy(&rules->policy,
990+
e->version);
991+
if (error) {
992+
info = "failed to remap policydb permission table";
993+
goto fail;
994+
}
990995
}
991-
} else
996+
} else {
992997
rules->policy.dfa = aa_get_dfa(nulldfa);
993-
998+
rules->policy.perms = kcalloc(2, sizeof(struct aa_perms),
999+
GFP_KERNEL);
1000+
if (!rules->policy.perms)
1001+
goto fail;
1002+
rules->policy.size = 2;
1003+
}
9941004
/* get file rules */
9951005
error = unpack_pdb(e, &rules->file, false, true, &info);
9961006
if (error) {
9971007
goto fail;
9981008
} else if (rules->file.dfa) {
999-
error = aa_compat_map_file(&rules->file);
1000-
if (error) {
1001-
info = "failed to remap file permission table";
1002-
goto fail;
1009+
if (!rules->file.perms) {
1010+
error = aa_compat_map_file(&rules->file);
1011+
if (error) {
1012+
info = "failed to remap file permission table";
1013+
goto fail;
1014+
}
10031015
}
10041016
} else if (rules->policy.dfa &&
10051017
rules->policy.start[AA_CLASS_FILE]) {
10061018
rules->file.dfa = aa_get_dfa(rules->policy.dfa);
10071019
rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE];
1008-
} else
1020+
rules->file.perms = kcalloc(rules->policy.size,
1021+
sizeof(struct aa_perms),
1022+
GFP_KERNEL);
1023+
if (!rules->file.perms)
1024+
goto fail;
1025+
memcpy(rules->file.perms, rules->policy.perms,
1026+
rules->policy.size * sizeof(struct aa_perms));
1027+
rules->file.size = rules->policy.size;
1028+
} else {
10091029
rules->file.dfa = aa_get_dfa(nulldfa);
1010-
1030+
rules->file.perms = kcalloc(2, sizeof(struct aa_perms),
1031+
GFP_KERNEL);
1032+
if (!rules->file.perms)
1033+
goto fail;
1034+
rules->file.size = 2;
1035+
}
10111036
error = -EPROTO;
10121037
if (aa_unpack_nameX(e, AA_STRUCT, "data")) {
10131038
info = "out of memory";
@@ -1046,8 +1071,13 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
10461071
goto fail;
10471072
}
10481073

1049-
rhashtable_insert_fast(profile->data, &data->head,
1050-
profile->data->p);
1074+
if (rhashtable_insert_fast(profile->data, &data->head,
1075+
profile->data->p)) {
1076+
kfree_sensitive(data->key);
1077+
kfree_sensitive(data);
1078+
info = "failed to insert data to table";
1079+
goto fail;
1080+
}
10511081
}
10521082

10531083
if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) {
@@ -1134,22 +1164,16 @@ static int verify_header(struct aa_ext *e, int required, const char **ns)
11341164
return 0;
11351165
}
11361166

1137-
static bool verify_xindex(int xindex, int table_size)
1138-
{
1139-
int index, xtype;
1140-
xtype = xindex & AA_X_TYPE_MASK;
1141-
index = xindex & AA_X_INDEX_MASK;
1142-
if (xtype == AA_X_TABLE && index >= table_size)
1143-
return false;
1144-
return true;
1145-
}
1146-
1147-
/* verify dfa xindexes are in range of transition tables */
1148-
static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
1167+
/**
1168+
* verify_dfa_accept_index - verify accept indexes are in range of perms table
1169+
* @dfa: the dfa to check accept indexes are in range
1170+
* table_size: the permission table size the indexes should be within
1171+
*/
1172+
static bool verify_dfa_accept_index(struct aa_dfa *dfa, int table_size)
11491173
{
11501174
int i;
11511175
for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
1152-
if (!verify_xindex(ACCEPT_TABLE(dfa)[i], table_size))
1176+
if (ACCEPT_TABLE(dfa)[i] >= table_size)
11531177
return false;
11541178
}
11551179
return true;
@@ -1186,11 +1210,13 @@ static bool verify_perms(struct aa_policydb *pdb)
11861210
if (!verify_perm(&pdb->perms[i]))
11871211
return false;
11881212
/* verify indexes into str table */
1189-
if (pdb->perms[i].xindex >= pdb->trans.size)
1213+
if ((pdb->perms[i].xindex & AA_X_TYPE_MASK) == AA_X_TABLE &&
1214+
(pdb->perms[i].xindex & AA_X_INDEX_MASK) >= pdb->trans.size)
11901215
return false;
1191-
if (pdb->perms[i].tag >= pdb->trans.size)
1216+
if (pdb->perms[i].tag && pdb->perms[i].tag >= pdb->trans.size)
11921217
return false;
1193-
if (pdb->perms[i].label >= pdb->trans.size)
1218+
if (pdb->perms[i].label &&
1219+
pdb->perms[i].label >= pdb->trans.size)
11941220
return false;
11951221
}
11961222

@@ -1212,10 +1238,10 @@ static int verify_profile(struct aa_profile *profile)
12121238
if (!rules)
12131239
return 0;
12141240

1215-
if ((rules->file.dfa && !verify_dfa_xindex(rules->file.dfa,
1216-
rules->file.trans.size)) ||
1241+
if ((rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa,
1242+
rules->file.size)) ||
12171243
(rules->policy.dfa &&
1218-
!verify_dfa_xindex(rules->policy.dfa, rules->policy.trans.size))) {
1244+
!verify_dfa_accept_index(rules->policy.dfa, rules->policy.size))) {
12191245
audit_iface(profile, NULL, NULL,
12201246
"Unpack: Invalid named transition", NULL, -EPROTO);
12211247
return -EPROTO;

0 commit comments

Comments
 (0)