Skip to content

Commit

Permalink
Merge tag 'aa-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/…
Browse files Browse the repository at this point in the history
…jj/linux-apparmor into ra-next
  • Loading branch information
James Morris committed May 12, 2013
2 parents f722406 + 2654bfb commit bd71164
Show file tree
Hide file tree
Showing 19 changed files with 286 additions and 248 deletions.
2 changes: 1 addition & 1 deletion security/apparmor/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static const char *const aa_audit_type[] = {
"HINT",
"STATUS",
"ERROR",
"KILLED"
"KILLED",
"AUTO"
};

Expand Down
44 changes: 28 additions & 16 deletions security/apparmor/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,23 @@ void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
aa_get_profile(new->onexec);
}

/**
* aa_get_task_profile - Get another task's profile
* @task: task to query (NOT NULL)
*
* Returns: counted reference to @task's profile
*/
struct aa_profile *aa_get_task_profile(struct task_struct *task)
{
struct aa_profile *p;

rcu_read_lock();
p = aa_get_profile(__aa_task_profile(task));
rcu_read_unlock();

return p;
}

/**
* aa_replace_current_profile - replace the current tasks profiles
* @profile: new profile (NOT NULL)
Expand All @@ -76,7 +93,7 @@ void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
*/
int aa_replace_current_profile(struct aa_profile *profile)
{
struct aa_task_cxt *cxt = current_cred()->security;
struct aa_task_cxt *cxt = current_cxt();
struct cred *new;
BUG_ON(!profile);

Expand All @@ -87,17 +104,13 @@ int aa_replace_current_profile(struct aa_profile *profile)
if (!new)
return -ENOMEM;

cxt = new->security;
if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
cxt = cred_cxt(new);
if (unconfined(profile) || (cxt->profile->ns != profile->ns))
/* if switching to unconfined or a different profile namespace
* clear out context state
*/
aa_put_profile(cxt->previous);
aa_put_profile(cxt->onexec);
cxt->previous = NULL;
cxt->onexec = NULL;
cxt->token = 0;
}
aa_clear_task_cxt_trans(cxt);

/* be careful switching cxt->profile, when racing replacement it
* is possible that cxt->profile->replacedby is the reference keeping
* @profile valid, so make sure to get its reference before dropping
Expand All @@ -123,7 +136,7 @@ int aa_set_current_onexec(struct aa_profile *profile)
if (!new)
return -ENOMEM;

cxt = new->security;
cxt = cred_cxt(new);
aa_get_profile(profile);
aa_put_profile(cxt->onexec);
cxt->onexec = profile;
Expand All @@ -150,7 +163,7 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token)
return -ENOMEM;
BUG_ON(!profile);

cxt = new->security;
cxt = cred_cxt(new);
if (!cxt->previous) {
/* transfer refcount */
cxt->previous = cxt->profile;
Expand Down Expand Up @@ -187,7 +200,7 @@ int aa_restore_previous_profile(u64 token)
if (!new)
return -ENOMEM;

cxt = new->security;
cxt = cred_cxt(new);
if (cxt->token != token) {
abort_creds(new);
return -EACCES;
Expand All @@ -205,11 +218,10 @@ int aa_restore_previous_profile(u64 token)
aa_get_profile(cxt->profile);
aa_put_profile(cxt->previous);
}
/* clear exec && prev information when restoring to previous context */
/* ref has been transfered so avoid putting ref in clear_task_cxt */
cxt->previous = NULL;
cxt->token = 0;
aa_put_profile(cxt->onexec);
cxt->onexec = NULL;
/* clear exec && prev information when restoring to previous context */
aa_clear_task_cxt_trans(cxt);

commit_creds(new);
return 0;
Expand Down
26 changes: 9 additions & 17 deletions security/apparmor/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,14 @@ static int may_change_ptraced_domain(struct task_struct *task,
struct aa_profile *to_profile)
{
struct task_struct *tracer;
const struct cred *cred = NULL;
struct aa_profile *tracerp = NULL;
int error = 0;

rcu_read_lock();
tracer = ptrace_parent(task);
if (tracer) {
if (tracer)
/* released below */
cred = get_task_cred(tracer);
tracerp = aa_cred_profile(cred);
}
tracerp = aa_get_task_profile(tracer);

/* not ptraced */
if (!tracer || unconfined(tracerp))
Expand All @@ -82,8 +79,7 @@ static int may_change_ptraced_domain(struct task_struct *task,

out:
rcu_read_unlock();
if (cred)
put_cred(cred);
aa_put_profile(tracerp);

return error;
}
Expand Down Expand Up @@ -360,7 +356,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
if (bprm->cred_prepared)
return 0;

cxt = bprm->cred->security;
cxt = cred_cxt(bprm->cred);
BUG_ON(!cxt);

profile = aa_get_profile(aa_newest_version(cxt->profile));
Expand Down Expand Up @@ -443,6 +439,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
} else {
error = -ENOENT;
info = "profile not found";
/* remove MAY_EXEC to audit as failure */
perms.allow &= ~MAY_EXEC;
}
}
} else if (COMPLAIN_MODE(profile)) {
Expand Down Expand Up @@ -514,11 +512,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
cxt->profile = new_profile;

/* clear out all temporary/transitional state from the context */
aa_put_profile(cxt->previous);
aa_put_profile(cxt->onexec);
cxt->previous = NULL;
cxt->onexec = NULL;
cxt->token = 0;
aa_clear_task_cxt_trans(cxt);

audit:
error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
Expand Down Expand Up @@ -557,7 +551,7 @@ int apparmor_bprm_secureexec(struct linux_binprm *bprm)
void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
{
struct aa_profile *profile = __aa_current_profile();
struct aa_task_cxt *new_cxt = bprm->cred->security;
struct aa_task_cxt *new_cxt = cred_cxt(bprm->cred);

/* bail out if unconfined or not changing profile */
if ((new_cxt->profile == profile) ||
Expand Down Expand Up @@ -634,7 +628,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)

/* released below */
cred = get_current_cred();
cxt = cred->security;
cxt = cred_cxt(cred);
profile = aa_cred_profile(cred);
previous_profile = cxt->previous;

Expand Down Expand Up @@ -750,7 +744,6 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
bool permtest)
{
const struct cred *cred;
struct aa_task_cxt *cxt;
struct aa_profile *profile, *target = NULL;
struct aa_namespace *ns = NULL;
struct file_perms perms = {};
Expand All @@ -770,7 +763,6 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
}

cred = get_current_cred();
cxt = cred->security;
profile = aa_cred_profile(cred);

/*
Expand Down
12 changes: 11 additions & 1 deletion security/apparmor/include/apparmor.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef __APPARMOR_H
#define __APPARMOR_H

#include <linux/slab.h>
#include <linux/fs.h>

#include "match.h"
Expand Down Expand Up @@ -64,9 +65,18 @@ extern int apparmor_initialized __initdata;
/* fn's in lib */
char *aa_split_fqname(char *args, char **ns_name);
void aa_info_message(const char *str);
void *kvmalloc(size_t size);
void *__aa_kvmalloc(size_t size, gfp_t flags);
void kvfree(void *buffer);

static inline void *kvmalloc(size_t size)
{
return __aa_kvmalloc(size, 0);
}

static inline void *kvzalloc(size_t size)
{
return __aa_kvmalloc(size, __GFP_ZERO);
}

/**
* aa_strneq - compare null terminated @str to a non null terminated substring
Expand Down
61 changes: 43 additions & 18 deletions security/apparmor/include/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

#include "policy.h"

#define cred_cxt(X) (X)->security
#define current_cxt() cred_cxt(current_cred())

/* struct aa_file_cxt - the AppArmor context the file was opened in
* @perms: the permission the file was opened with
*
Expand Down Expand Up @@ -80,23 +83,8 @@ int aa_replace_current_profile(struct aa_profile *profile);
int aa_set_current_onexec(struct aa_profile *profile);
int aa_set_current_hat(struct aa_profile *profile, u64 token);
int aa_restore_previous_profile(u64 cookie);
struct aa_profile *aa_get_task_profile(struct task_struct *task);

/**
* __aa_task_is_confined - determine if @task has any confinement
* @task: task to check confinement of (NOT NULL)
*
* If @task != current needs to be called in RCU safe critical section
*/
static inline bool __aa_task_is_confined(struct task_struct *task)
{
struct aa_task_cxt *cxt = __task_cred(task)->security;

BUG_ON(!cxt || !cxt->profile);
if (unconfined(aa_newest_version(cxt->profile)))
return 0;

return 1;
}

/**
* aa_cred_profile - obtain cred's profiles
Expand All @@ -108,11 +96,35 @@ static inline bool __aa_task_is_confined(struct task_struct *task)
*/
static inline struct aa_profile *aa_cred_profile(const struct cred *cred)
{
struct aa_task_cxt *cxt = cred->security;
struct aa_task_cxt *cxt = cred_cxt(cred);
BUG_ON(!cxt || !cxt->profile);
return aa_newest_version(cxt->profile);
}

/**
* __aa_task_profile - retrieve another task's profile
* @task: task to query (NOT NULL)
*
* Returns: @task's profile without incrementing its ref count
*
* If @task != current needs to be called in RCU safe critical section
*/
static inline struct aa_profile *__aa_task_profile(struct task_struct *task)
{
return aa_cred_profile(__task_cred(task));
}

/**
* __aa_task_is_confined - determine if @task has any confinement
* @task: task to check confinement of (NOT NULL)
*
* If @task != current needs to be called in RCU safe critical section
*/
static inline bool __aa_task_is_confined(struct task_struct *task)
{
return !unconfined(__aa_task_profile(task));
}

/**
* __aa_current_profile - find the current tasks confining profile
*
Expand All @@ -136,7 +148,7 @@ static inline struct aa_profile *__aa_current_profile(void)
*/
static inline struct aa_profile *aa_current_profile(void)
{
const struct aa_task_cxt *cxt = current_cred()->security;
const struct aa_task_cxt *cxt = current_cxt();
struct aa_profile *profile;
BUG_ON(!cxt || !cxt->profile);

Expand All @@ -151,4 +163,17 @@ static inline struct aa_profile *aa_current_profile(void)
return profile;
}

/**
* aa_clear_task_cxt_trans - clear transition tracking info from the cxt
* @cxt: task context to clear (NOT NULL)
*/
static inline void aa_clear_task_cxt_trans(struct aa_task_cxt *cxt)
{
aa_put_profile(cxt->previous);
aa_put_profile(cxt->onexec);
cxt->previous = NULL;
cxt->onexec = NULL;
cxt->token = 0;
}

#endif /* __AA_CONTEXT_H */
14 changes: 7 additions & 7 deletions security/apparmor/include/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,6 @@ static inline void aa_free_file_rules(struct aa_file_rules *rules)
aa_free_domain_entries(&rules->trans);
}

#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))

/* from namei.c */
#define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x))

/**
* aa_map_file_perms - map file flags to AppArmor permissions
* @file: open file to map flags to AppArmor permissions
Expand All @@ -199,8 +194,13 @@ static inline void aa_free_file_rules(struct aa_file_rules *rules)
*/
static inline u32 aa_map_file_to_perms(struct file *file)
{
int flags = MAP_OPEN_FLAGS(file->f_flags);
u32 perms = ACC_FMODE(file->f_mode);
int flags = file->f_flags;
u32 perms = 0;

if (file->f_mode & FMODE_WRITE)
perms |= MAY_WRITE;
if (file->f_mode & FMODE_READ)
perms |= MAY_READ;

if ((flags & O_APPEND) && (perms & MAY_WRITE))
perms = (perms & ~MAY_WRITE) | MAY_APPEND;
Expand Down
Loading

0 comments on commit bd71164

Please sign in to comment.