2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 10:07:12 +00:00
apparmor/parser/parser_merge.c
Tyler Hicks 3ce3adf3fe parser: Clean up file entry processing
Removes an unnecessary variable, simplifies and unifies some of the loop
logic, and removes commented out code.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
2013-09-11 11:59:00 -07:00

140 lines
3.2 KiB
C

/*
* 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 <libintl.h>
#define _(s) gettext(s)
#include "parser.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;
//PERROR("strcmp %s %s\n", (*e1)->name, (*e2)->name);
if ((*e1)->namespace) {
if ((*e2)->namespace)
res = strcmp((*e1)->namespace, (*e2)->namespace);
else
return 1;
} else if ((*e2)->namespace) {
return -1;
}
if (res)
return res;
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 = (*e2)->subset - (*e1)->subset;
if (res)
return res;
if ((*e1)->deny != (*e2)->deny)
return (*e1)->deny < (*e2)->deny ? -1 : 1;
/* rules with ptrace and change_profile can only merge with
* rules with exact same perm */
if (((*e1)->mode & (AA_CHANGE_PROFILE | AA_PTRACE_PERMS)) !=
((*e2)->mode & (AA_CHANGE_PROFILE | AA_PTRACE_PERMS)))
return 1;
return strcmp((*e1)->name, (*e2)->name);
}
static int process_file_entries(struct codomain *cod)
{
struct cod_entry *cur, *next;
struct cod_entry **table;
int n, count = 0;
for (cur = cod->entries; cur; cur = cur->next)
count++;
if (count < 2)
return 1;
table = malloc(sizeof(struct cod_entry *) * (count + 1));
if (!table) {
PERROR(_("Couldn't merge entries. Out of Memory\n"));
return 0;
}
for (cur = cod->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];
cod->entries = table[0];
free(table);
/* walk the sorted table merging similar entries */
for (cur = cod->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->mode, next->mode)) {
PERROR(_("profile %s: has merged rule %s with conflicting x modifiers\n"),
cod->name, cur->name);
return 0;
}
cur->mode |= next->mode;
cur->audit |= next->audit;
cur->next = next->next;
next->next = NULL;
free_cod_entries(next);
}
return 1;
}
int codomain_merge_rules(struct codomain *cod)
{
if (!process_file_entries(cod))
goto fail;
/* XXX return error from this */
merge_hat_rules(cod);
return 1;
fail:
return 0;
}