Skip to content

Commit 2b3a003

Browse files
WOnder93pcmoore
authored andcommitted
selinux: convert cond_av_list to array
Since it is fixed-size after allocation and we know the size beforehand, using a plain old array is simpler and more efficient. Signed-off-by: Ondrej Mosnacek <[email protected]> Reviewed-by: Stephen Smalley <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent 60abd31 commit 2b3a003

File tree

2 files changed

+53
-79
lines changed

2 files changed

+53
-79
lines changed

security/selinux/ss/conditional.c

Lines changed: 49 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -87,28 +87,31 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
8787
*/
8888
void evaluate_cond_node(struct policydb *p, struct cond_node *node)
8989
{
90+
struct avtab_node *avnode;
9091
int new_state;
91-
struct cond_av_list *cur;
92+
u32 i;
9293

9394
new_state = cond_evaluate_expr(p, node->expr);
9495
if (new_state != node->cur_state) {
9596
node->cur_state = new_state;
9697
if (new_state == -1)
9798
pr_err("SELinux: expression result was undefined - disabling all rules.\n");
9899
/* turn the rules on or off */
99-
for (cur = node->true_list; cur; cur = cur->next) {
100+
for (i = 0; i < node->true_list.len; i++) {
101+
avnode = node->true_list.nodes[i];
100102
if (new_state <= 0)
101-
cur->node->key.specified &= ~AVTAB_ENABLED;
103+
avnode->key.specified &= ~AVTAB_ENABLED;
102104
else
103-
cur->node->key.specified |= AVTAB_ENABLED;
105+
avnode->key.specified |= AVTAB_ENABLED;
104106
}
105107

106-
for (cur = node->false_list; cur; cur = cur->next) {
108+
for (i = 0; i < node->false_list.len; i++) {
109+
avnode = node->false_list.nodes[i];
107110
/* -1 or 1 */
108111
if (new_state)
109-
cur->node->key.specified &= ~AVTAB_ENABLED;
112+
avnode->key.specified &= ~AVTAB_ENABLED;
110113
else
111-
cur->node->key.specified |= AVTAB_ENABLED;
114+
avnode->key.specified |= AVTAB_ENABLED;
112115
}
113116
}
114117
}
@@ -128,16 +131,6 @@ int cond_policydb_init(struct policydb *p)
128131
return 0;
129132
}
130133

131-
static void cond_av_list_destroy(struct cond_av_list *list)
132-
{
133-
struct cond_av_list *cur, *next;
134-
for (cur = list; cur; cur = next) {
135-
next = cur->next;
136-
/* the avtab_ptr_t node is destroy by the avtab */
137-
kfree(cur);
138-
}
139-
}
140-
141134
static void cond_node_destroy(struct cond_node *node)
142135
{
143136
struct cond_expr *cur_expr, *next_expr;
@@ -146,8 +139,9 @@ static void cond_node_destroy(struct cond_node *node)
146139
next_expr = cur_expr->next;
147140
kfree(cur_expr);
148141
}
149-
cond_av_list_destroy(node->true_list);
150-
cond_av_list_destroy(node->false_list);
142+
/* the avtab_ptr_t nodes are destroyed by the avtab */
143+
kfree(node->true_list.nodes);
144+
kfree(node->false_list.nodes);
151145
}
152146

153147
static void cond_list_destroy(struct policydb *p)
@@ -255,19 +249,18 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
255249

256250
struct cond_insertf_data {
257251
struct policydb *p;
252+
struct avtab_node **dst;
258253
struct cond_av_list *other;
259-
struct cond_av_list *head;
260-
struct cond_av_list *tail;
261254
};
262255

263256
static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr)
264257
{
265258
struct cond_insertf_data *data = ptr;
266259
struct policydb *p = data->p;
267-
struct cond_av_list *other = data->other, *list, *cur;
260+
struct cond_av_list *other = data->other;
268261
struct avtab_node *node_ptr;
269-
u8 found;
270-
int rc = -EINVAL;
262+
u32 i;
263+
bool found;
271264

272265
/*
273266
* For type rules we have to make certain there aren't any
@@ -277,7 +270,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
277270
if (k->specified & AVTAB_TYPE) {
278271
if (avtab_search(&p->te_avtab, k)) {
279272
pr_err("SELinux: type rule already exists outside of a conditional.\n");
280-
goto err;
273+
return -EINVAL;
281274
}
282275
/*
283276
* If we are reading the false list other will be a pointer to
@@ -292,64 +285,47 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
292285
if (node_ptr) {
293286
if (avtab_search_node_next(node_ptr, k->specified)) {
294287
pr_err("SELinux: too many conflicting type rules.\n");
295-
goto err;
288+
return -EINVAL;
296289
}
297-
found = 0;
298-
for (cur = other; cur; cur = cur->next) {
299-
if (cur->node == node_ptr) {
300-
found = 1;
290+
found = false;
291+
for (i = 0; i < other->len; i++) {
292+
if (other->nodes[i] == node_ptr) {
293+
found = true;
301294
break;
302295
}
303296
}
304297
if (!found) {
305298
pr_err("SELinux: conflicting type rules.\n");
306-
goto err;
299+
return -EINVAL;
307300
}
308301
}
309302
} else {
310303
if (avtab_search(&p->te_cond_avtab, k)) {
311304
pr_err("SELinux: conflicting type rules when adding type rule for true.\n");
312-
goto err;
305+
return -EINVAL;
313306
}
314307
}
315308
}
316309

317310
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
318311
if (!node_ptr) {
319312
pr_err("SELinux: could not insert rule.\n");
320-
rc = -ENOMEM;
321-
goto err;
322-
}
323-
324-
list = kzalloc(sizeof(*list), GFP_KERNEL);
325-
if (!list) {
326-
rc = -ENOMEM;
327-
goto err;
313+
return -ENOMEM;
328314
}
329315

330-
list->node = node_ptr;
331-
if (!data->head)
332-
data->head = list;
333-
else
334-
data->tail->next = list;
335-
data->tail = list;
316+
*data->dst = node_ptr;
336317
return 0;
337-
338-
err:
339-
cond_av_list_destroy(data->head);
340-
data->head = NULL;
341-
return rc;
342318
}
343319

344-
static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other)
320+
static int cond_read_av_list(struct policydb *p, void *fp,
321+
struct cond_av_list *list,
322+
struct cond_av_list *other)
345323
{
346-
int i, rc;
324+
int rc;
347325
__le32 buf[1];
348-
u32 len;
326+
u32 i, len;
349327
struct cond_insertf_data data;
350328

351-
*ret_list = NULL;
352-
353329
rc = next_entry(buf, fp, sizeof(u32));
354330
if (rc)
355331
return rc;
@@ -358,18 +334,24 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
358334
if (len == 0)
359335
return 0;
360336

337+
list->nodes = kcalloc(len, sizeof(*list->nodes), GFP_KERNEL);
338+
if (!list->nodes)
339+
return -ENOMEM;
340+
361341
data.p = p;
362342
data.other = other;
363-
data.head = NULL;
364-
data.tail = NULL;
365343
for (i = 0; i < len; i++) {
344+
data.dst = &list->nodes[i];
366345
rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
367346
&data);
368-
if (rc)
347+
if (rc) {
348+
kfree(list->nodes);
349+
list->nodes = NULL;
369350
return rc;
351+
}
370352
}
371353

372-
*ret_list = data.head;
354+
list->len = len;
373355
return 0;
374356
}
375357

@@ -432,7 +414,7 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
432414
rc = cond_read_av_list(p, fp, &node->true_list, NULL);
433415
if (rc)
434416
goto err;
435-
rc = cond_read_av_list(p, fp, &node->false_list, node->true_list);
417+
rc = cond_read_av_list(p, fp, &node->false_list, &node->true_list);
436418
if (rc)
437419
goto err;
438420
return 0;
@@ -511,24 +493,16 @@ static int cond_write_av_list(struct policydb *p,
511493
struct cond_av_list *list, struct policy_file *fp)
512494
{
513495
__le32 buf[1];
514-
struct cond_av_list *cur_list;
515-
u32 len;
496+
u32 i;
516497
int rc;
517498

518-
len = 0;
519-
for (cur_list = list; cur_list != NULL; cur_list = cur_list->next)
520-
len++;
521-
522-
buf[0] = cpu_to_le32(len);
499+
buf[0] = cpu_to_le32(list->len);
523500
rc = put_entry(buf, sizeof(u32), 1, fp);
524501
if (rc)
525502
return rc;
526503

527-
if (len == 0)
528-
return 0;
529-
530-
for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
531-
rc = avtab_write_item(p, cur_list->node, fp);
504+
for (i = 0; i < list->len; i++) {
505+
rc = avtab_write_item(p, list->nodes[i], fp);
532506
if (rc)
533507
return rc;
534508
}
@@ -565,10 +539,10 @@ static int cond_write_node(struct policydb *p, struct cond_node *node,
565539
return rc;
566540
}
567541

568-
rc = cond_write_av_list(p, node->true_list, fp);
542+
rc = cond_write_av_list(p, &node->true_list, fp);
569543
if (rc)
570544
return rc;
571-
rc = cond_write_av_list(p, node->false_list, fp);
545+
rc = cond_write_av_list(p, &node->false_list, fp);
572546
if (rc)
573547
return rc;
574548

security/selinux/ss/conditional.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ struct cond_expr {
3939
* struct is for that list.
4040
*/
4141
struct cond_av_list {
42-
struct avtab_node *node;
43-
struct cond_av_list *next;
42+
struct avtab_node **nodes;
43+
u32 len;
4444
};
4545

4646
/*
@@ -53,8 +53,8 @@ struct cond_av_list {
5353
struct cond_node {
5454
int cur_state;
5555
struct cond_expr *expr;
56-
struct cond_av_list *true_list;
57-
struct cond_av_list *false_list;
56+
struct cond_av_list true_list;
57+
struct cond_av_list false_list;
5858
};
5959

6060
int cond_policydb_init(struct policydb *p);

0 commit comments

Comments
 (0)