Skip to content

Commit

Permalink
Merge branch 'for-security' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/jj/linux-apparmor into next
  • Loading branch information
James Morris committed Mar 15, 2012
2 parents 6041e83 + 2d4cee7 commit b01d3fb
Show file tree
Hide file tree
Showing 13 changed files with 189 additions and 52 deletions.
5 changes: 3 additions & 2 deletions security/apparmor/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ clean-files := capability_names.h rlim_names.h
# to
# [1] = "dac_override",
quiet_cmd_make-caps = GEN $@
cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ;\
cmd_make-caps = echo "static const char const *capability_names[] = {" > $@ ;\
sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \
-e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
echo "};" >> $@
Expand Down Expand Up @@ -43,7 +43,8 @@ cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ;\
# to
# #define AA_FS_RLIMIT_MASK "fsize stack"
quiet_cmd_make-rlim = GEN $@
cmd_make-rlim = echo "static const char *rlim_names[RLIM_NLIMITS] = {" > $@ ;\
cmd_make-rlim = echo "static const char const *rlim_names[RLIM_NLIMITS] = {" \
> $@ ;\
sed $< >> $@ -r -n \
-e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\
echo "};" >> $@ ;\
Expand Down
6 changes: 3 additions & 3 deletions security/apparmor/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include "include/audit.h"
#include "include/policy.h"

const char *op_table[] = {
const char *const op_table[] = {
"null",

"sysctl",
Expand Down Expand Up @@ -73,15 +73,15 @@ const char *op_table[] = {
"profile_remove"
};

const char *audit_mode_names[] = {
const char *const audit_mode_names[] = {
"normal",
"quiet_denied",
"quiet",
"noquiet",
"all"
};

static char *aa_audit_type[] = {
static const char *const aa_audit_type[] = {
"AUDIT",
"ALLOWED",
"DENIED",
Expand Down
5 changes: 2 additions & 3 deletions security/apparmor/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,13 +372,12 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
state = profile->file.start;

/* buffer freed below, name is pointer into buffer */
error = aa_get_name(&bprm->file->f_path, profile->path_flags, &buffer,
&name);
error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer,
&name, &info);
if (error) {
if (profile->flags &
(PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
error = 0;
info = "Exec failed name resolution";
name = bprm->filename;
goto audit;
}
Expand Down
18 changes: 7 additions & 11 deletions security/apparmor/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,22 +278,16 @@ int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
int error;

flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
error = aa_get_name(path, flags, &buffer, &name);
error = aa_path_name(path, flags, &buffer, &name, &info);
if (error) {
if (error == -ENOENT && is_deleted(path->dentry)) {
/* Access to open files that are deleted are
* give a pass (implicit delegation)
*/
error = 0;
info = NULL;
perms.allow = request;
} else if (error == -ENOENT)
info = "Failed name lookup - deleted entry";
else if (error == -ESTALE)
info = "Failed name lookup - disconnected path";
else if (error == -ENAMETOOLONG)
info = "Failed name lookup - name too long";
else
info = "Failed name lookup";
}
} else {
aa_str_perms(profile->file.dfa, profile->file.start, name, cond,
&perms);
Expand Down Expand Up @@ -364,12 +358,14 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
lperms = nullperms;

/* buffer freed below, lname is pointer in buffer */
error = aa_get_name(&link, profile->path_flags, &buffer, &lname);
error = aa_path_name(&link, profile->path_flags, &buffer, &lname,
&info);
if (error)
goto audit;

/* buffer2 freed below, tname is pointer in buffer2 */
error = aa_get_name(&target, profile->path_flags, &buffer2, &tname);
error = aa_path_name(&target, profile->path_flags, &buffer2, &tname,
&info);
if (error)
goto audit;

Expand Down
15 changes: 14 additions & 1 deletion security/apparmor/include/apparmor.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@

#include "match.h"

/*
* Class of mediation types in the AppArmor policy db
*/
#define AA_CLASS_ENTRY 0
#define AA_CLASS_UNKNOWN 1
#define AA_CLASS_FILE 2
#define AA_CLASS_CAP 3
#define AA_CLASS_NET 4
#define AA_CLASS_RLIMITS 5
#define AA_CLASS_DOMAIN 6

#define AA_CLASS_LAST AA_CLASS_DOMAIN

/* Control parameters settable through module/boot flags */
extern enum audit_mode aa_g_audit;
extern bool aa_g_audit_header;
Expand Down Expand Up @@ -81,7 +94,7 @@ static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
unsigned int start)
{
/* the null transition only needs the string's null terminator byte */
return aa_dfa_match_len(dfa, start, "", 1);
return aa_dfa_next(dfa, start, 0);
}

static inline bool mediated_filesystem(struct inode *inode)
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 @@ -25,7 +25,7 @@

struct aa_profile;

extern const char *audit_mode_names[];
extern const char *const audit_mode_names[];
#define AUDIT_MAX_INDEX 5

enum audit_mode {
Expand All @@ -47,7 +47,7 @@ enum audit_type {
AUDIT_APPARMOR_AUTO
};

extern const char *op_table[];
extern const char *const op_table[];
enum aa_ops {
OP_NULL,

Expand Down
3 changes: 3 additions & 0 deletions security/apparmor/include/match.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
const char *str, int len);
unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
const char *str);
unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
const char c);

void aa_dfa_free_kref(struct kref *kref);

/**
Expand Down
3 changes: 2 additions & 1 deletion security/apparmor/include/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum path_flags {
PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
};

int aa_get_name(struct path *path, int flags, char **buffer, const char **name);
int aa_path_name(struct path *path, int flags, char **buffer,
const char **name, const char **info);

#endif /* __AA_PATH_H */
15 changes: 14 additions & 1 deletion security/apparmor/include/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "file.h"
#include "resource.h"

extern const char *profile_mode_names[];
extern const char *const profile_mode_names[];
#define APPARMOR_NAMES_MAX_INDEX 3

#define COMPLAIN_MODE(_profile) \
Expand Down Expand Up @@ -129,6 +129,17 @@ struct aa_namespace {
struct list_head sub_ns;
};

/* struct aa_policydb - match engine for a policy
* dfa: dfa pattern match
* start: set of start states for the different classes of data
*/
struct aa_policydb {
/* Generic policy DFA specific rule types will be subsections of it */
struct aa_dfa *dfa;
unsigned int start[AA_CLASS_LAST + 1];

};

/* struct aa_profile - basic confinement data
* @base - base components of the profile (name, refcount, lists, lock ...)
* @parent: parent of profile
Expand All @@ -143,6 +154,7 @@ struct aa_namespace {
* @flags: flags controlling profile behavior
* @path_flags: flags controlling path generation behavior
* @size: the memory consumed by this profiles rules
* @policy: general match rules governing policy
* @file: The set of rules governing basic file access and domain transitions
* @caps: capabilities for the profile
* @rlimits: rlimits for the profile
Expand Down Expand Up @@ -179,6 +191,7 @@ struct aa_profile {
u32 path_flags;
int size;

struct aa_policydb policy;
struct aa_file_rules file;
struct aa_caps caps;
struct aa_rlimit rlimits;
Expand Down
80 changes: 77 additions & 3 deletions security/apparmor/match.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,12 +335,12 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
}

/**
* aa_dfa_next_state - traverse @dfa to find state @str stops at
* aa_dfa_match - traverse @dfa to find state @str stops at
* @dfa: the dfa to match @str against (NOT NULL)
* @start: the state of the dfa to start matching in
* @str: the null terminated string of bytes to match against the dfa (NOT NULL)
*
* aa_dfa_next_state will match @str against the dfa and return the state it
* aa_dfa_match will match @str against the dfa and return the state it
* finished matching in. The final state can be used to look up the accepting
* label, or as the start state of a continuing match.
*
Expand All @@ -349,5 +349,79 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
const char *str)
{
return aa_dfa_match_len(dfa, start, str, strlen(str));
u16 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
u16 *next = NEXT_TABLE(dfa);
u16 *check = CHECK_TABLE(dfa);
unsigned int state = start, pos;

if (state == 0)
return 0;

/* current state is <state>, matching character *str */
if (dfa->tables[YYTD_ID_EC]) {
/* Equivalence class table defined */
u8 *equiv = EQUIV_TABLE(dfa);
/* default is direct to next state */
while (*str) {
pos = base[state] + equiv[(u8) *str++];
if (check[pos] == state)
state = next[pos];
else
state = def[state];
}
} else {
/* default is direct to next state */
while (*str) {
pos = base[state] + (u8) *str++;
if (check[pos] == state)
state = next[pos];
else
state = def[state];
}
}

return state;
}

/**
* aa_dfa_next - step one character to the next state in the dfa
* @dfa: the dfa to tranverse (NOT NULL)
* @state: the state to start in
* @c: the input character to transition on
*
* aa_dfa_match will step through the dfa by one input character @c
*
* Returns: state reach after input @c
*/
unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
const char c)
{
u16 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
u16 *next = NEXT_TABLE(dfa);
u16 *check = CHECK_TABLE(dfa);
unsigned int pos;

/* current state is <state>, matching character *str */
if (dfa->tables[YYTD_ID_EC]) {
/* Equivalence class table defined */
u8 *equiv = EQUIV_TABLE(dfa);
/* default is direct to next state */

pos = base[state] + equiv[(u8) c];
if (check[pos] == state)
state = next[pos];
else
state = def[state];
} else {
/* default is direct to next state */
pos = base[state] + (u8) c;
if (check[pos] == state)
state = next[pos];
else
state = def[state];
}

return state;
}
Loading

0 comments on commit b01d3fb

Please sign in to comment.