File: parser_merge.c

package info (click to toggle)
apparmor 4.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 34,800 kB
  • sloc: ansic: 24,940; python: 24,595; sh: 12,524; cpp: 9,024; yacc: 2,061; makefile: 1,921; lex: 1,215; pascal: 1,145; perl: 1,033; ruby: 365; lisp: 282; exp: 250; java: 212; xml: 159
file content (129 lines) | stat: -rw-r--r-- 3,210 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
 *   NOVELL (All rights reserved)
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of version 2 of the GNU General Public
 *   License published by the Free Software Foundation.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, contact Novell, Inc.
 */

#include <linux/unistd.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#include "parser.h"
#include "profile.h"

static int file_comp(const void *c1, const void *c2)
{
	struct cod_entry **e1, **e2;
	e1 = (struct cod_entry **)c1;
	e2 = (struct cod_entry **)c2;
	int res = 0;

	if ((*e1)->link_name) {
		if ((*e2)->link_name)
			res = strcmp((*e1)->link_name, (*e2)->link_name);
		else
			return 1;
	} else if ((*e2)->link_name) {
		return -1;
	}
	if (res)
		return res;

	if ((*e1)->link_name)
		res = ((int) (*e2)->subset) - ((int) (*e1)->subset);
	if (res)
		return res;

	if ((*e1)->rule_mode != (*e2)->rule_mode)
		return (*e1)->rule_mode < (*e2)->rule_mode ? -1 : 1;

	if ((*e1)->audit != (*e2)->audit)
		return (*e1)->audit < (*e2)->audit ? -1 : 1;

	if ((*e1)->priority != (*e2)->priority)
		return (*e2)->priority - (*e1)->priority;

	return strcmp((*e1)->name, (*e2)->name);
}

static int process_file_entries(Profile *prof)
{
	struct cod_entry *cur, *next;
	struct cod_entry **table;
	int n, count = 0;

	for (cur = prof->entries; cur; cur = cur->next)
		count++;

	if (count < 2)
		return 0;

	table = (struct cod_entry **) malloc(sizeof(struct cod_entry *) * (count + 1));
	if (!table) {
		PERROR(_("Couldn't merge entries. Out of Memory\n"));
		return -ENOMEM;
	}

	for (cur = prof->entries, n = 0; cur; cur = cur->next, n++)
		table[n] = cur;
	qsort(table, count, sizeof(struct cod_entry *), file_comp);
	table[count] = NULL;
	for (n = 0; n < count; n++)
		table[n]->next = table[n + 1];
	prof->entries = table[0];
	free(table);

	count = 0;
	/* walk the sorted table merging similar entries */
	for (cur = prof->entries, next = cur->next; next; next = cur->next) {
		if (file_comp(&cur, &next) != 0) {
			cur = next;
			continue;
		}

		/* check for merged x consistency */
		if (!is_merged_x_consistent(cur->perms, next->perms)) {
			PERROR(_("profile %s: has merged rule %s with conflicting x modifiers\n"),
				prof->name, cur->name);
			return -1;
		}
		cur->perms |= next->perms;
		cur->next = next->next;

		next->next = NULL;
		free_cod_entries(next);
		count++;
	}

	return count;
}

int profile_merge_rules(Profile *prof)
{
	if (!(parseopts.control & CONTROL_RULE_MERGE))
		return 0;

	int res, tmp = process_file_entries(prof);
	if (tmp < 0)
		return -tmp;
	res = prof->merge_rules();
	if (res < 0)
		return -res;
	if (parseopts.dump & DUMP_RULE_MERGE)
	        fprintf(stderr, "RULE MERGE: deleted %d file rules, %d rules\n", tmp, res);
	return 0;
}