2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-29 05:17:59 +00:00

exec modes per U:G:O

This commit is contained in:
John Johansen 2007-11-16 09:35:57 +00:00
parent ec639bc82c
commit 638535d650
6 changed files with 109 additions and 57 deletions

View File

@ -32,14 +32,18 @@
#define AA_MAY_LINK (1 << 4) #define AA_MAY_LINK (1 << 4)
#define AA_MAY_LOCK (1 << 5) #define AA_MAY_LOCK (1 << 5)
#define AA_EXEC_MMAP (1 << 6) #define AA_EXEC_MMAP (1 << 6)
#define AA_EXEC_UNSAFE (1 << 7)
#define AA_EXEC_MOD_0 (1 << 8)
#define AA_EXEC_MOD_1 (1 << 9)
#define AA_BASE_PERMS (AA_MAY_EXEC | AA_MAY_WRITE | \ #define AA_BASE_PERMS (AA_MAY_EXEC | AA_MAY_WRITE | \
AA_MAY_READ | AA_MAY_APPEND | \ AA_MAY_READ | AA_MAY_APPEND | \
AA_MAY_LINK | AA_MAY_LOCK | \ AA_MAY_LINK | AA_MAY_LOCK | \
AA_EXEC_MMAP) AA_EXEC_MMAP | AA_EXEC_UNSAFE | \
AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
#define AA_USER_SHIFT 0 #define AA_USER_SHIFT 0
#define AA_GROUP_SHIFT 7 #define AA_GROUP_SHIFT 10
#define AA_OTHER_SHIFT 14 #define AA_OTHER_SHIFT 20
#define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT) #define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT)
#define AA_GROUP_PERMS (AA_BASE_PERMS << AA_GROUP_SHIFT) #define AA_GROUP_PERMS (AA_BASE_PERMS << AA_GROUP_SHIFT)
@ -48,31 +52,34 @@
#define AA_FILE_PERMS (AA_USER_PERMS | AA_GROUP_PERMS | \ #define AA_FILE_PERMS (AA_USER_PERMS | AA_GROUP_PERMS | \
AA_OTHER_PERMS) AA_OTHER_PERMS)
#define AA_CHANGE_PROFILE (1 << 26) #define AA_CHANGE_PROFILE (1 << 30)
#define AA_EXEC_UNSAFE (1 << 27)
#define AA_EXEC_MOD_SHIFT 28
#define AA_EXEC_MOD_0 (1 << 28)
#define AA_EXEC_MOD_1 (1 << 29)
#define AA_EXEC_MOD_2 (1 << 30)
#define AA_ERROR_BIT (1 << 31) #define AA_ERROR_BIT (1 << 31)
#define AA_SHARED_PERMS (AA_CHANGE_PROFILE | AA_ERROR_BIT)
#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | \
AA_EXEC_MOD_1 | \
AA_EXEC_MOD_2)
#define AA_EXEC_UNCONFINED (AA_EXEC_MOD_2) #define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
#define AA_EXEC_TYPE (AA_MAY_EXEC | AA_EXEC_UNSAFE | \
AA_EXEC_MODIFIERS)
#define AA_EXEC_UNCONFINED 0
#define AA_EXEC_INHERIT (AA_EXEC_MOD_0) #define AA_EXEC_INHERIT (AA_EXEC_MOD_0)
#define AA_EXEC_PROFILE (AA_EXEC_MOD_1) #define AA_EXEC_PROFILE (AA_EXEC_MOD_1)
#define AA_EXEC_PROFILE_OR_INHERIT (AA_EXEC_MOD_0 | AA_EXEC_MOD_1) #define AA_EXEC_PROFILE_OR_INHERIT (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
#define AA_VALID_PERMS (AA_FILE_PERMS | AA_CHANGE_PROFILE | \ #define AA_VALID_PERMS (AA_FILE_PERMS | AA_CHANGE_PROFILE)
AA_EXEC_UNSAFE | AA_EXEC_MODIFIERS)
#define AA_EXEC_BITS ((AA_MAY_EXEC << AA_USER_SHIFT) | \ #define AA_EXEC_BITS ((AA_MAY_EXEC << AA_USER_SHIFT) | \
(AA_MAY_EXEC << AA_GROUP_SHIFT) | \ (AA_MAY_EXEC << AA_GROUP_SHIFT) | \
(AA_MAY_EXEC << AA_OTHER_SHIFT)) (AA_MAY_EXEC << AA_OTHER_SHIFT))
#define ALL_AA_EXEC_UNSAFE ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \
(AA_EXEC_UNSAFE << AA_GROUP_SHIFT) | \
(AA_EXEC_UNSAFE << AA_OTHER_SHIFT))
#define AA_USER_EXEC_TYPE (AA_EXEC_TYPE << AA_USER_SHIFT)
#define AA_GROUP_EXEC_TYPE (AA_EXEC_TYPE << AA_GROUP_SHIFT)
#define AA_OTHER_EXEC_TYPE (AA_EXEC_TYPE << AA_OTHER_SHIFT)
#define SHIFT_MODE(MODE, SHIFT) ((((MODE) & AA_BASE_PERMS) << (SHIFT))\ #define SHIFT_MODE(MODE, SHIFT) ((((MODE) & AA_BASE_PERMS) << (SHIFT))\
| ((MODE) & ~AA_FILE_PERMS)) | ((MODE) & ~AA_FILE_PERMS))
#define SHIFT_TO_BASE(MODE, SHIFT) ((((MODE) & AA_FILE_PERMS) >> (SHIFT))\ #define SHIFT_TO_BASE(MODE, SHIFT) ((((MODE) & AA_FILE_PERMS) >> (SHIFT))\
@ -113,4 +120,19 @@ enum pattern_t {
#define HAS_EXEC_UNSAFE(mode) ((mode) & AA_EXEC_UNSAFE) #define HAS_EXEC_UNSAFE(mode) ((mode) & AA_EXEC_UNSAFE)
#define HAS_CHANGE_PROFILE(mode) ((mode) & AA_CHANGE_PROFILE) #define HAS_CHANGE_PROFILE(mode) ((mode) & AA_CHANGE_PROFILE)
static inline int is_merged_x_consistent(int a, int b)
{
if ((a & AA_USER_EXEC_TYPE) && (b & AA_USER_EXEC_TYPE) &&
((a & AA_USER_EXEC_TYPE) != (b & AA_USER_EXEC_TYPE)))
return 0;
if ((a & AA_GROUP_EXEC_TYPE) && (b & AA_GROUP_EXEC_TYPE) &&
((a & AA_GROUP_EXEC_TYPE) != (b & AA_GROUP_EXEC_TYPE)))
return 0;
if ((a & AA_OTHER_EXEC_TYPE) && (b & AA_OTHER_EXEC_TYPE) &&
((a & AA_OTHER_EXEC_TYPE) != (b & AA_OTHER_EXEC_TYPE)))
return 0;
return 1;
}
#endif /* ! _IMMUNIX_H */ #endif /* ! _IMMUNIX_H */

View File

@ -1512,23 +1512,32 @@ uint32_t accept_perms(State *state)
if (!(match= dynamic_cast<MatchFlag *>(*i))) if (!(match= dynamic_cast<MatchFlag *>(*i)))
continue; continue;
if (dynamic_cast<ExactMatchFlag *>(match)) { if (dynamic_cast<ExactMatchFlag *>(match)) {
if (diff_qualifiers(exact_match_perms, match->flag)) if (!is_merged_x_consistent(exact_match_perms,
match->flag))
exact_match_perms |= AA_ERROR_BIT; exact_match_perms |= AA_ERROR_BIT;
exact_match_perms |= match->flag; exact_match_perms |= match->flag;
} else { } else {
if (diff_qualifiers(perms, match->flag)) if (!is_merged_x_consistent(perms, match->flag))
perms |= AA_ERROR_BIT; perms |= AA_ERROR_BIT;
perms |= match->flag; perms |= match->flag;
} }
} }
if (exact_match_perms & AA_EXEC_MODIFIERS) perms |= exact_match_perms &
perms = exact_match_perms | (perms & ~AA_EXEC_MODIFIERS); ~(AA_USER_EXEC_TYPE | AA_GROUP_EXEC_TYPE | AA_OTHER_EXEC_TYPE);
else {
if (exact_match_perms) if (exact_match_perms & AA_USER_EXEC_TYPE)
fprintf(stderr, "exact match perms without exec modifiers!!!\n"); perms = (exact_match_perms & AA_USER_EXEC_TYPE) |
perms |= exact_match_perms; (perms & ~AA_USER_EXEC_TYPE);
}
if (exact_match_perms & AA_GROUP_EXEC_TYPE)
perms = (exact_match_perms & AA_GROUP_EXEC_TYPE) |
(perms & ~AA_GROUP_EXEC_TYPE);
if (exact_match_perms & AA_OTHER_EXEC_TYPE)
perms = (exact_match_perms & AA_OTHER_EXEC_TYPE) |
(perms & ~AA_OTHER_EXEC_TYPE);
if (perms & AA_ERROR_BIT) { if (perms & AA_ERROR_BIT) {
fprintf(stderr, "error bit 0x%x\n", perms); fprintf(stderr, "error bit 0x%x\n", perms);
exit(255); exit(255);
@ -1542,7 +1551,7 @@ fprintf(stderr, "exact match perms without exec modifiers!!!\n");
extern "C" int aare_add_rule(aare_ruleset_t *rules, char *rule, uint32_t perms) extern "C" int aare_add_rule(aare_ruleset_t *rules, char *rule, uint32_t perms)
{ {
static MatchFlag *match_flags[sizeof(perms) * 8 - 4 + 8]; static MatchFlag *match_flags[sizeof(perms) * 8 - 1];
static MatchFlag *exec_match_flags[8 * 3]; static MatchFlag *exec_match_flags[8 * 3];
static ExactMatchFlag *exact_match_flags[8 * 3]; static ExactMatchFlag *exact_match_flags[8 * 3];
Node *tree, *accept; Node *tree, *accept;
@ -1553,8 +1562,6 @@ extern "C" int aare_add_rule(aare_ruleset_t *rules, char *rule, uint32_t perms)
if (regexp_parse(&tree, rule)) if (regexp_parse(&tree, rule))
return 0; return 0;
if ((perms & AA_EXEC_BITS) && !(perms & AA_EXEC_MODIFIERS))
fprintf(stderr, "Rule with exec bits and not exec modifiers\n\t 0x%x %s\n", perms, rule);
/* /*
* Check if we have an expression with or without wildcards. This * Check if we have an expression with or without wildcards. This
* determines how exec modifiers are merged in accept_perms() based * determines how exec modifiers are merged in accept_perms() based
@ -1573,36 +1580,51 @@ extern "C" int aare_add_rule(aare_ruleset_t *rules, char *rule, uint32_t perms)
if (rules->reverse) if (rules->reverse)
flip_tree(tree); flip_tree(tree);
#define ALL_EXEC_TYPE (AA_USER_EXEC_TYPE | AA_GROUP_EXEC_TYPE | \
AA_OTHER_EXEC_TYPE)
#define EXTRACT_X_INDEX(perm, shift) (((perm) >> (shift + 7)) & 0x7)
if (perms & ALL_EXEC_TYPE && (!perms & AA_EXEC_BITS))
fprintf(stderr, "adding X rule without MAY_EXEC: 0x%x %s\n", perms, rule);
accept = NULL; accept = NULL;
for (unsigned int n = 0; perms && n < (sizeof(perms) * 8) - 4; n++) { for (unsigned int n = 0; perms && n < (sizeof(perms) * 8) - 1; n++) {
uint32_t mask = 1 << n; uint32_t mask = 1 << n;
if (perms & mask) { if (perms & mask) {
perms &= ~mask; perms &= ~mask;
Node *flag; Node *flag;
if ((mask & AA_EXEC_BITS) && (perms & AA_EXEC_MODIFIERS)) { if (mask & AA_EXEC_BITS) {
int index = (perms & AA_EXEC_MODIFIERS) >> AA_EXEC_MOD_SHIFT; uint32_t eperm = 0;
if (mask & (AA_MAY_EXEC << AA_GROUP_SHIFT)) uint32_t index = 0;
index += 8; if (mask & (AA_MAY_EXEC << AA_USER_SHIFT)) {
else if (mask & (AA_MAY_EXEC << AA_OTHER_SHIFT)) eperm = mask | perms & AA_USER_EXEC_TYPE;
index += 16; index = EXTRACT_X_INDEX(perms, AA_USER_SHIFT);
} else if (mask & (AA_MAY_EXEC << AA_GROUP_SHIFT)) {
eperm = mask | perms & AA_GROUP_EXEC_TYPE;
index = EXTRACT_X_INDEX(perms, AA_GROUP_SHIFT) + 8;
} else {
eperm = mask | perms & AA_OTHER_EXEC_TYPE;
index = EXTRACT_X_INDEX(perms, AA_OTHER_SHIFT) + 16;
}
if (exact_match) { if (exact_match) {
if (exact_match_flags[index]) if (exact_match_flags[index])
flag = exact_match_flags[index]->dup(); flag = exact_match_flags[index]->dup();
else { else {
exact_match_flags[index] = new ExactMatchFlag(mask | (perms & AA_EXEC_MODIFIERS)); exact_match_flags[index] = new ExactMatchFlag(eperm);
flag = exact_match_flags[index]; flag = exact_match_flags[index];
} }
} else { } else {
if (exec_match_flags[index]) if (exec_match_flags[index])
flag = exec_match_flags[index]->dup(); flag = exec_match_flags[index]->dup();
else { else {
exec_match_flags[index] = new MatchFlag(mask | (perms & AA_EXEC_MODIFIERS)); exec_match_flags[index] = new MatchFlag(eperm);
flag = exec_match_flags[index]; flag = exec_match_flags[index];
} }
} }
} else if (mask & ALL_EXEC_TYPE) {
/* these cases are covered by EXEC_BITS */
continue;
} else { } else {
if (match_flags[n]) if (match_flags[n])
flag = match_flags[n]->dup(); flag = match_flags[n]->dup();

View File

@ -79,16 +79,12 @@ static int process_file_entries(struct codomain *cod)
qsort(table, count, sizeof(struct cod_entry *), file_comp); qsort(table, count, sizeof(struct cod_entry *), file_comp);
table[count] = NULL; table[count] = NULL;
#define X_CONFLICT(a, b) \
(((a) & AA_EXEC_BITS) && ((b) & AA_EXEC_BITS) && \
(((a) & (AA_EXEC_MODIFIERS | AA_EXEC_UNSAFE)) != \
((b) & (AA_EXEC_MODIFIERS | AA_EXEC_UNSAFE))))
/* walk the sorted table merging similar entries */ /* walk the sorted table merging similar entries */
for (cur = table[0], next = table[1], n = 1; next != NULL; n++, next = table[n]) { for (cur = table[0], next = table[1], n = 1; next != NULL; n++, next = table[n]) {
if (file_comp(&cur, &next) == 0) { if (file_comp(&cur, &next) == 0) {
/* check for merged x consistency */ /* check for merged x consistency */
if (X_CONFLICT(cur->mode, next->mode)) { if (!is_merged_x_consistent(cur->mode, next->mode)) {
PERROR(_("profile %s: has merged rule %s with multiple x modifiers\n"), PERROR(_("profile %s: has merged rule %s with multiple x modifiers\n"),
cod->name, cur->name); cod->name, cur->name);
return 0; return 0;

View File

@ -560,7 +560,7 @@ out:
int parse_mode(const char *str_mode) int parse_mode(const char *str_mode)
{ {
const char *next, *pos = str_mode; const char *next, *pos = str_mode;
int tmp, mode = 0; int tmp, exec_mods, mode = 0;
next = strchr(str_mode, ':'); next = strchr(str_mode, ':');
if (!next) { if (!next) {
tmp = parse_sub_mode(str_mode, ""); tmp = parse_sub_mode(str_mode, "");
@ -572,23 +572,32 @@ int parse_mode(const char *str_mode)
return mode; return mode;
} }
/* user:group:other */ /* user:group:other */
if (next > pos) if (next > pos) {
exec_mods = mode & AA_EXEC_MODIFIERS;
mode = SHIFT_MODE(parse_sub_mode(pos, "user"), AA_USER_SHIFT); mode = SHIFT_MODE(parse_sub_mode(pos, "user"), AA_USER_SHIFT);
}
pos = next + 1; pos = next + 1;
next = strchr(pos, ':'); next = strchr(pos, ':');
if (next > pos) { if (next > pos) {
tmp = parse_sub_mode(pos, "group"); tmp = parse_sub_mode(pos, "group");
/* we can allow different mods per labeling, just not when named transitions
are present.
if ((mode & AA_EXEC_BITS) && (tmp & AA_EXEC_BITS) && if ((mode & AA_EXEC_BITS) && (tmp & AA_EXEC_BITS) &&
(mode & AA_EXEC_MODIFIERS) != (tmp & AA_EXEC_MODIFIERS)) (exec_mods != (tmp & AA_EXEC_MODIFIERS)))
yyerror(_("conflicting x modifiers between user and group permissions.")); yyerror(_("conflicting x modifiers between user and group permissions."));
*/
exec_mods = tmp & AA_EXEC_MODIFIERS;
mode |= SHIFT_MODE(tmp, AA_GROUP_SHIFT); mode |= SHIFT_MODE(tmp, AA_GROUP_SHIFT);
} }
pos = next + 1; pos = next + 1;
if (*pos) { if (*pos) {
tmp = parse_sub_mode(pos, "other"); tmp = parse_sub_mode(pos, "other");
/* allow different x mods per ugo
if ((mode & AA_EXEC_BITS) && (tmp & AA_EXEC_BITS) && if ((mode & AA_EXEC_BITS) && (tmp & AA_EXEC_BITS) &&
(mode & AA_EXEC_MODIFIERS) != (tmp & AA_EXEC_MODIFIERS)) (exec_mods != (tmp & AA_EXEC_MODIFIERS)))
yyerror(_("conflicting x modifiers between other and user:group permissions.")); yyerror(_("conflicting x modifiers between other and user:group permissions."));
*/
exec_mods = tmp & AA_EXEC_MODIFIERS;
mode |= SHIFT_MODE(tmp, AA_OTHER_SHIFT); mode |= SHIFT_MODE(tmp, AA_OTHER_SHIFT);
} }
if (mode & ~AA_VALID_PERMS) if (mode & ~AA_VALID_PERMS)

View File

@ -497,14 +497,16 @@ static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry)
/* ix implies m but the apparmor module does not add m bit to /* ix implies m but the apparmor module does not add m bit to
* dfa states like it does for pcre * dfa states like it does for pcre
*/ */
if ((entry->mode & AA_EXEC_MODIFIERS) == AA_EXEC_INHERIT) { if (((entry->mode >> AA_OTHER_SHIFT) & AA_EXEC_MODIFIERS) ==
if (HAS_MAY_EXEC(SHIFT_TO_BASE(entry->mode, AA_OTHER_SHIFT))) AA_EXEC_INHERIT)
entry->mode |= AA_EXEC_MMAP << AA_OTHER_SHIFT; entry->mode |= AA_EXEC_MMAP << AA_OTHER_SHIFT;
if (HAS_MAY_EXEC(SHIFT_TO_BASE(entry->mode, AA_GROUP_SHIFT))) if (((entry->mode >> AA_GROUP_SHIFT) & AA_EXEC_MODIFIERS) ==
entry->mode |= AA_EXEC_MMAP << AA_GROUP_SHIFT; AA_EXEC_INHERIT)
if (HAS_MAY_EXEC(SHIFT_TO_BASE(entry->mode, AA_USER_SHIFT))) entry->mode |= AA_EXEC_MMAP << AA_GROUP_SHIFT;
entry->mode |= AA_EXEC_MMAP << AA_USER_SHIFT; if (((entry->mode >> AA_USER_SHIFT) & AA_EXEC_MODIFIERS) ==
} AA_EXEC_INHERIT)
entry->mode |= AA_EXEC_MMAP << AA_USER_SHIFT;
if (!aare_add_rule(dfarules, tbuf, entry->mode)) if (!aare_add_rule(dfarules, tbuf, entry->mode))
ret = FALSE; ret = FALSE;

View File

@ -518,14 +518,15 @@ rule: id_or_var file_mode TOK_END_OF_RULE
rule: file_mode id_or_var TOK_END_OF_RULE rule: file_mode id_or_var TOK_END_OF_RULE
{ {
$$ = do_file_rule(NULL, $2, $1 & ~AA_EXEC_UNSAFE); $$ = do_file_rule(NULL, $2, $1 & ~ALL_AA_EXEC_UNSAFE);
}; };
rule: TOK_UNSAFE file_mode id_or_var TOK_END_OF_RULE rule: TOK_UNSAFE file_mode id_or_var TOK_END_OF_RULE
{ {
int mode = (($2 & AA_EXEC_BITS) << 7) & ALL_AA_EXEC_UNSAFE;
if (!($2 & AA_EXEC_BITS)) if (!($2 & AA_EXEC_BITS))
yyerror(_("unsafe rule missing exec permissions")); yyerror(_("unsafe rule missing exec permissions"));
$$ = do_file_rule(NULL, $3, $2 | AA_EXEC_UNSAFE); $$ = do_file_rule(NULL, $3, ($2 & ~ALL_AA_EXEC_UNSAFE) | mode);
}; };
rule: id_or_var file_mode id_or_var rule: id_or_var file_mode id_or_var