apparmor: add gerneric permissions struct and support fns
Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
b5b2557c0a
commit
aa9aeea8d4
4 changed files with 153 additions and 17 deletions
|
@ -56,15 +56,15 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
|
|||
struct common_audit_data *sa = va;
|
||||
kuid_t fsuid = current_fsuid();
|
||||
|
||||
if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) {
|
||||
if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
|
||||
audit_log_format(ab, " requested_mask=");
|
||||
audit_file_mask(ab, aad(sa)->fs.request);
|
||||
audit_file_mask(ab, aad(sa)->request);
|
||||
}
|
||||
if (aad(sa)->fs.denied & AA_AUDIT_FILE_MASK) {
|
||||
if (aad(sa)->denied & AA_AUDIT_FILE_MASK) {
|
||||
audit_log_format(ab, " denied_mask=");
|
||||
audit_file_mask(ab, aad(sa)->fs.denied);
|
||||
audit_file_mask(ab, aad(sa)->denied);
|
||||
}
|
||||
if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) {
|
||||
if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
|
||||
audit_log_format(ab, " fsuid=%d",
|
||||
from_kuid(&init_user_ns, fsuid));
|
||||
audit_log_format(ab, " ouid=%d",
|
||||
|
@ -100,7 +100,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
|
|||
DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op);
|
||||
|
||||
sa.u.tsk = NULL;
|
||||
aad(&sa)->fs.request = request;
|
||||
aad(&sa)->request = request;
|
||||
aad(&sa)->name = name;
|
||||
aad(&sa)->fs.target = target;
|
||||
aad(&sa)->fs.ouid = ouid;
|
||||
|
@ -115,30 +115,30 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
|
|||
mask = 0xffff;
|
||||
|
||||
/* mask off perms that are not being force audited */
|
||||
aad(&sa)->fs.request &= mask;
|
||||
aad(&sa)->request &= mask;
|
||||
|
||||
if (likely(!aad(&sa)->fs.request))
|
||||
if (likely(!aad(&sa)->request))
|
||||
return 0;
|
||||
type = AUDIT_APPARMOR_AUDIT;
|
||||
} else {
|
||||
/* only report permissions that were denied */
|
||||
aad(&sa)->fs.request = aad(&sa)->fs.request & ~perms->allow;
|
||||
AA_BUG(!aad(&sa)->fs.request);
|
||||
aad(&sa)->request = aad(&sa)->request & ~perms->allow;
|
||||
AA_BUG(!aad(&sa)->request);
|
||||
|
||||
if (aad(&sa)->fs.request & perms->kill)
|
||||
if (aad(&sa)->request & perms->kill)
|
||||
type = AUDIT_APPARMOR_KILL;
|
||||
|
||||
/* quiet known rejects, assumes quiet and kill do not overlap */
|
||||
if ((aad(&sa)->fs.request & perms->quiet) &&
|
||||
if ((aad(&sa)->request & perms->quiet) &&
|
||||
AUDIT_MODE(profile) != AUDIT_NOQUIET &&
|
||||
AUDIT_MODE(profile) != AUDIT_ALL)
|
||||
aad(&sa)->fs.request &= ~perms->quiet;
|
||||
aad(&sa)->request &= ~perms->quiet;
|
||||
|
||||
if (!aad(&sa)->fs.request)
|
||||
if (!aad(&sa)->request)
|
||||
return COMPLAIN_MODE(profile) ? 0 : aad(&sa)->error;
|
||||
}
|
||||
|
||||
aad(&sa)->fs.denied = aad(&sa)->fs.request & ~perms->allow;
|
||||
aad(&sa)->denied = aad(&sa)->request & ~perms->allow;
|
||||
return aa_audit(type, profile, &sa, file_audit_cb);
|
||||
}
|
||||
|
||||
|
|
|
@ -107,14 +107,14 @@ struct apparmor_audit_data {
|
|||
void *profile;
|
||||
const char *name;
|
||||
const char *info;
|
||||
u32 request;
|
||||
u32 denied;
|
||||
union {
|
||||
/* these entries require a custom callback fn */
|
||||
struct {
|
||||
struct aa_profile *peer;
|
||||
struct {
|
||||
const char *target;
|
||||
u32 request;
|
||||
u32 denied;
|
||||
kuid_t ouid;
|
||||
} fs;
|
||||
};
|
||||
|
|
|
@ -66,6 +66,40 @@
|
|||
extern const char aa_file_perm_chrs[];
|
||||
extern const char *aa_file_perm_names[];
|
||||
|
||||
struct aa_perms {
|
||||
u32 allow;
|
||||
u32 audit; /* set only when allow is set */
|
||||
|
||||
u32 deny; /* explicit deny, or conflict if allow also set */
|
||||
u32 quiet; /* set only when ~allow | deny */
|
||||
u32 kill; /* set only when ~allow | deny */
|
||||
u32 stop; /* set only when ~allow | deny */
|
||||
|
||||
u32 complain; /* accumulates only used when ~allow & ~deny */
|
||||
u32 cond; /* set only when ~allow and ~deny */
|
||||
|
||||
u32 hide; /* set only when ~allow | deny */
|
||||
u32 prompt; /* accumulates only used when ~allow & ~deny */
|
||||
|
||||
/* Reserved:
|
||||
* u32 subtree; / * set only when allow is set * /
|
||||
*/
|
||||
u16 xindex;
|
||||
};
|
||||
|
||||
#define ALL_PERMS_MASK 0xffffffff
|
||||
|
||||
extern struct aa_perms allperms;
|
||||
|
||||
struct aa_profile;
|
||||
|
||||
void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
|
||||
void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
|
||||
void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
|
||||
u32 chrsmask, const char **names, u32 namesmask);
|
||||
void aa_apply_modes_to_perms(struct aa_profile *profile,
|
||||
struct aa_perms *perms);
|
||||
void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
|
||||
struct aa_perms *perms);
|
||||
|
||||
#endif /* __AA_PERM_H */
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#include "include/perms.h"
|
||||
#include "include/policy.h"
|
||||
|
||||
struct aa_perms allperms = { .allow = ALL_PERMS_MASK,
|
||||
.quiet = ALL_PERMS_MASK,
|
||||
.hide = ALL_PERMS_MASK };
|
||||
|
||||
/**
|
||||
* aa_split_fqname - split a fqname into a profile and namespace name
|
||||
* @fqname: a full qualified name in namespace profile format (NOT NULL)
|
||||
|
@ -188,6 +192,104 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
|
|||
*str = '\0';
|
||||
}
|
||||
|
||||
void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
|
||||
{
|
||||
const char *fmt = "%s";
|
||||
unsigned int i, perm = 1;
|
||||
bool prev = false;
|
||||
|
||||
for (i = 0; i < 32; perm <<= 1, i++) {
|
||||
if (mask & perm) {
|
||||
audit_log_format(ab, fmt, names[i]);
|
||||
if (!prev) {
|
||||
prev = true;
|
||||
fmt = " %s";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
|
||||
u32 chrsmask, const char **names, u32 namesmask)
|
||||
{
|
||||
char str[33];
|
||||
|
||||
audit_log_format(ab, "\"");
|
||||
if ((mask & chrsmask) && chrs) {
|
||||
aa_perm_mask_to_str(str, chrs, mask & chrsmask);
|
||||
mask &= ~chrsmask;
|
||||
audit_log_format(ab, "%s", str);
|
||||
if (mask & namesmask)
|
||||
audit_log_format(ab, " ");
|
||||
}
|
||||
if ((mask & namesmask) && names)
|
||||
aa_audit_perm_names(ab, names, mask & namesmask);
|
||||
audit_log_format(ab, "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_apply_modes_to_perms - apply namespace and profile flags to perms
|
||||
* @profile: that perms where computed from
|
||||
* @perms: perms to apply mode modifiers to
|
||||
*
|
||||
* TODO: split into profile and ns based flags for when accumulating perms
|
||||
*/
|
||||
void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms)
|
||||
{
|
||||
switch (AUDIT_MODE(profile)) {
|
||||
case AUDIT_ALL:
|
||||
perms->audit = ALL_PERMS_MASK;
|
||||
/* fall through */
|
||||
case AUDIT_NOQUIET:
|
||||
perms->quiet = 0;
|
||||
break;
|
||||
case AUDIT_QUIET:
|
||||
perms->audit = 0;
|
||||
/* fall through */
|
||||
case AUDIT_QUIET_DENIED:
|
||||
perms->quiet = ALL_PERMS_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (KILL_MODE(profile))
|
||||
perms->kill = ALL_PERMS_MASK;
|
||||
else if (COMPLAIN_MODE(profile))
|
||||
perms->complain = ALL_PERMS_MASK;
|
||||
/*
|
||||
* TODO:
|
||||
* else if (PROMPT_MODE(profile))
|
||||
* perms->prompt = ALL_PERMS_MASK;
|
||||
*/
|
||||
}
|
||||
|
||||
static u32 map_other(u32 x)
|
||||
{
|
||||
return ((x & 0x3) << 8) | /* SETATTR/GETATTR */
|
||||
((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */
|
||||
((x & 0x60) << 19); /* SETOPT/GETOPT */
|
||||
}
|
||||
|
||||
void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
|
||||
struct aa_perms *perms)
|
||||
{
|
||||
perms->deny = 0;
|
||||
perms->kill = perms->stop = 0;
|
||||
perms->complain = perms->cond = 0;
|
||||
perms->hide = 0;
|
||||
perms->prompt = 0;
|
||||
perms->allow = dfa_user_allow(dfa, state);
|
||||
perms->audit = dfa_user_audit(dfa, state);
|
||||
perms->quiet = dfa_user_quiet(dfa, state);
|
||||
|
||||
/* for v5 perm mapping in the policydb, the other set is used
|
||||
* to extend the general perm set
|
||||
*/
|
||||
perms->allow |= map_other(dfa_other_allow(dfa, state));
|
||||
perms->audit |= map_other(dfa_other_audit(dfa, state));
|
||||
perms->quiet |= map_other(dfa_other_quiet(dfa, state));
|
||||
// perms->xindex = dfa_user_xindex(dfa, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_init - initialize a policy structure
|
||||
* @policy: policy to initialize (NOT NULL)
|
||||
|
|
Loading…
Reference in a new issue