Skip to content

Commit

Permalink
apparmor: add gerneric permissions struct and support fns
Browse files Browse the repository at this point in the history
Signed-off-by: John Johansen <[email protected]>
  • Loading branch information
John Johansen committed Jun 11, 2017
1 parent b5b2557 commit aa9aeea
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 17 deletions.
30 changes: 15 additions & 15 deletions security/apparmor/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down
4 changes: 2 additions & 2 deletions security/apparmor/include/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
34 changes: 34 additions & 0 deletions security/apparmor/include/perms.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
102 changes: 102 additions & 0 deletions security/apparmor/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit aa9aeea

Please sign in to comment.