apparmor: pass cred through to audit info.

The cred is needed to properly audit some messages, and will be needed
in the future for uid conditional mediation. So pass it through to
where the apparmor_audit_data struct gets defined.

Reviewed-by: Georgia Garcia <georgia.garcia@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2022-09-19 20:48:48 -07:00
parent d20f5a1a6e
commit 90c436a64a
20 changed files with 388 additions and 211 deletions

View File

@ -423,7 +423,7 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
/* high level check about policy management - fine grained in /* high level check about policy management - fine grained in
* below after unpack * below after unpack
*/ */
error = aa_may_manage_policy(label, ns, mask); error = aa_may_manage_policy(current_cred(), label, ns, mask);
if (error) if (error)
goto end_section; goto end_section;
@ -486,7 +486,8 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
/* high level check about policy management - fine grained in /* high level check about policy management - fine grained in
* below after unpack * below after unpack
*/ */
error = aa_may_manage_policy(label, ns, AA_MAY_REMOVE_POLICY); error = aa_may_manage_policy(current_cred(), label, ns,
AA_MAY_REMOVE_POLICY);
if (error) if (error)
goto out; goto out;
@ -1800,7 +1801,8 @@ static int ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
int error; int error;
label = begin_current_label_crit_section(); label = begin_current_label_crit_section();
error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY); error = aa_may_manage_policy(current_cred(), label, NULL,
AA_MAY_LOAD_POLICY);
end_current_label_crit_section(label); end_current_label_crit_section(label);
if (error) if (error)
return error; return error;
@ -1849,7 +1851,8 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
int error; int error;
label = begin_current_label_crit_section(); label = begin_current_label_crit_section();
error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY); error = aa_may_manage_policy(current_cred(), label, NULL,
AA_MAY_LOAD_POLICY);
end_current_label_crit_section(label); end_current_label_crit_section(label);
if (error) if (error)
return error; return error;

View File

@ -140,6 +140,7 @@ static int profile_capable(struct aa_profile *profile, int cap,
/** /**
* aa_capable - test permission to use capability * aa_capable - test permission to use capability
* @subj_cread: cred we are testing capability against
* @label: label being tested for capability (NOT NULL) * @label: label being tested for capability (NOT NULL)
* @cap: capability to be tested * @cap: capability to be tested
* @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
@ -148,12 +149,14 @@ static int profile_capable(struct aa_profile *profile, int cap,
* *
* Returns: 0 on success, or else an error code. * Returns: 0 on success, or else an error code.
*/ */
int aa_capable(struct aa_label *label, int cap, unsigned int opts) int aa_capable(const struct cred *subj_cred, struct aa_label *label,
int cap, unsigned int opts)
{ {
struct aa_profile *profile; struct aa_profile *profile;
int error = 0; int error = 0;
DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE); DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE);
ad.subj_cred = subj_cred;
ad.common.u.cap = cap; ad.common.u.cap = cap;
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
profile_capable(profile, cap, opts, &ad)); profile_capable(profile, cap, opts, &ad));

View File

@ -31,6 +31,7 @@
/** /**
* may_change_ptraced_domain - check if can change profile on ptraced task * may_change_ptraced_domain - check if can change profile on ptraced task
* @cred: cred of task changing domain
* @to_label: profile to change to (NOT NULL) * @to_label: profile to change to (NOT NULL)
* @info: message if there is an error * @info: message if there is an error
* *
@ -39,28 +40,34 @@
* *
* Returns: %0 or error if change not allowed * Returns: %0 or error if change not allowed
*/ */
static int may_change_ptraced_domain(struct aa_label *to_label, static int may_change_ptraced_domain(const struct cred *to_cred,
struct aa_label *to_label,
const char **info) const char **info)
{ {
struct task_struct *tracer; struct task_struct *tracer;
struct aa_label *tracerl = NULL; struct aa_label *tracerl = NULL;
const struct cred *tracer_cred = NULL;
int error = 0; int error = 0;
rcu_read_lock(); rcu_read_lock();
tracer = ptrace_parent(current); tracer = ptrace_parent(current);
if (tracer) if (tracer) {
/* released below */ /* released below */
tracerl = aa_get_task_label(tracer); tracerl = aa_get_task_label(tracer);
tracer_cred = get_task_cred(tracer);
}
/* not ptraced */ /* not ptraced */
if (!tracer || unconfined(tracerl)) if (!tracer || unconfined(tracerl))
goto out; goto out;
error = aa_may_ptrace(tracerl, to_label, PTRACE_MODE_ATTACH); error = aa_may_ptrace(tracer_cred, tracerl, to_cred, to_label,
PTRACE_MODE_ATTACH);
out: out:
rcu_read_unlock(); rcu_read_unlock();
aa_put_label(tracerl); aa_put_label(tracerl);
put_cred(tracer_cred);
if (error) if (error)
*info = "ptrace prevents transition"; *info = "ptrace prevents transition";
@ -621,7 +628,8 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
return new; return new;
} }
static struct aa_label *profile_transition(struct aa_profile *profile, static struct aa_label *profile_transition(const struct cred *subj_cred,
struct aa_profile *profile,
const struct linux_binprm *bprm, const struct linux_binprm *bprm,
char *buffer, struct path_cond *cond, char *buffer, struct path_cond *cond,
bool *secure_exec) bool *secure_exec)
@ -711,7 +719,8 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
} }
audit: audit:
aa_audit_file(profile, &perms, OP_EXEC, MAY_EXEC, name, target, new, aa_audit_file(subj_cred, profile, &perms, OP_EXEC, MAY_EXEC, name,
target, new,
cond->uid, info, error); cond->uid, info, error);
if (!new || nonewprivs) { if (!new || nonewprivs) {
aa_put_label(new); aa_put_label(new);
@ -721,7 +730,8 @@ audit:
return new; return new;
} }
static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec, static int profile_onexec(const struct cred *subj_cred,
struct aa_profile *profile, struct aa_label *onexec,
bool stack, const struct linux_binprm *bprm, bool stack, const struct linux_binprm *bprm,
char *buffer, struct path_cond *cond, char *buffer, struct path_cond *cond,
bool *secure_exec) bool *secure_exec)
@ -789,13 +799,15 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec,
} }
audit: audit:
return aa_audit_file(profile, &perms, OP_EXEC, AA_MAY_ONEXEC, xname, return aa_audit_file(subj_cred, profile, &perms, OP_EXEC,
AA_MAY_ONEXEC, xname,
NULL, onexec, cond->uid, info, error); NULL, onexec, cond->uid, info, error);
} }
/* ensure none ns domain transitions are correctly applied with onexec */ /* ensure none ns domain transitions are correctly applied with onexec */
static struct aa_label *handle_onexec(struct aa_label *label, static struct aa_label *handle_onexec(const struct cred *subj_cred,
struct aa_label *label,
struct aa_label *onexec, bool stack, struct aa_label *onexec, bool stack,
const struct linux_binprm *bprm, const struct linux_binprm *bprm,
char *buffer, struct path_cond *cond, char *buffer, struct path_cond *cond,
@ -812,26 +824,28 @@ static struct aa_label *handle_onexec(struct aa_label *label,
if (!stack) { if (!stack) {
error = fn_for_each_in_ns(label, profile, error = fn_for_each_in_ns(label, profile,
profile_onexec(profile, onexec, stack, profile_onexec(subj_cred, profile, onexec, stack,
bprm, buffer, cond, unsafe)); bprm, buffer, cond, unsafe));
if (error) if (error)
return ERR_PTR(error); return ERR_PTR(error);
new = fn_label_build_in_ns(label, profile, GFP_KERNEL, new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
aa_get_newest_label(onexec), aa_get_newest_label(onexec),
profile_transition(profile, bprm, buffer, profile_transition(subj_cred, profile, bprm,
buffer,
cond, unsafe)); cond, unsafe));
} else { } else {
/* TODO: determine how much we want to loosen this */ /* TODO: determine how much we want to loosen this */
error = fn_for_each_in_ns(label, profile, error = fn_for_each_in_ns(label, profile,
profile_onexec(profile, onexec, stack, bprm, profile_onexec(subj_cred, profile, onexec, stack, bprm,
buffer, cond, unsafe)); buffer, cond, unsafe));
if (error) if (error)
return ERR_PTR(error); return ERR_PTR(error);
new = fn_label_build_in_ns(label, profile, GFP_KERNEL, new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
aa_label_merge(&profile->label, onexec, aa_label_merge(&profile->label, onexec,
GFP_KERNEL), GFP_KERNEL),
profile_transition(profile, bprm, buffer, profile_transition(subj_cred, profile, bprm,
buffer,
cond, unsafe)); cond, unsafe));
} }
@ -840,7 +854,8 @@ static struct aa_label *handle_onexec(struct aa_label *label,
/* TODO: get rid of GLOBAL_ROOT_UID */ /* TODO: get rid of GLOBAL_ROOT_UID */
error = fn_for_each_in_ns(label, profile, error = fn_for_each_in_ns(label, profile,
aa_audit_file(profile, &nullperms, OP_CHANGE_ONEXEC, aa_audit_file(subj_cred, profile, &nullperms,
OP_CHANGE_ONEXEC,
AA_MAY_ONEXEC, bprm->filename, NULL, AA_MAY_ONEXEC, bprm->filename, NULL,
onexec, GLOBAL_ROOT_UID, onexec, GLOBAL_ROOT_UID,
"failed to build target label", -ENOMEM)); "failed to build target label", -ENOMEM));
@ -859,6 +874,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
{ {
struct aa_task_ctx *ctx; struct aa_task_ctx *ctx;
struct aa_label *label, *new = NULL; struct aa_label *label, *new = NULL;
const struct cred *subj_cred;
struct aa_profile *profile; struct aa_profile *profile;
char *buffer = NULL; char *buffer = NULL;
const char *info = NULL; const char *info = NULL;
@ -871,6 +887,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
file_inode(bprm->file)->i_mode file_inode(bprm->file)->i_mode
}; };
subj_cred = current_cred();
ctx = task_ctx(current); ctx = task_ctx(current);
AA_BUG(!cred_label(bprm->cred)); AA_BUG(!cred_label(bprm->cred));
AA_BUG(!ctx); AA_BUG(!ctx);
@ -897,11 +914,12 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
/* Test for onexec first as onexec override other x transitions. */ /* Test for onexec first as onexec override other x transitions. */
if (ctx->onexec) if (ctx->onexec)
new = handle_onexec(label, ctx->onexec, ctx->token, new = handle_onexec(subj_cred, label, ctx->onexec, ctx->token,
bprm, buffer, &cond, &unsafe); bprm, buffer, &cond, &unsafe);
else else
new = fn_label_build(label, profile, GFP_KERNEL, new = fn_label_build(label, profile, GFP_KERNEL,
profile_transition(profile, bprm, buffer, profile_transition(subj_cred, profile, bprm,
buffer,
&cond, &unsafe)); &cond, &unsafe));
AA_BUG(!new); AA_BUG(!new);
@ -936,7 +954,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
if (bprm->unsafe & (LSM_UNSAFE_PTRACE)) { if (bprm->unsafe & (LSM_UNSAFE_PTRACE)) {
/* TODO: test needs to be profile of label to new */ /* TODO: test needs to be profile of label to new */
error = may_change_ptraced_domain(new, &info); error = may_change_ptraced_domain(bprm->cred, new, &info);
if (error) if (error)
goto audit; goto audit;
} }
@ -973,7 +991,8 @@ done:
audit: audit:
error = fn_for_each(label, profile, error = fn_for_each(label, profile,
aa_audit_file(profile, &nullperms, OP_EXEC, MAY_EXEC, aa_audit_file(current_cred(), profile, &nullperms,
OP_EXEC, MAY_EXEC,
bprm->filename, NULL, new, bprm->filename, NULL, new,
vfsuid_into_kuid(vfsuid), info, error)); vfsuid_into_kuid(vfsuid), info, error));
aa_put_label(new); aa_put_label(new);
@ -989,7 +1008,8 @@ audit:
* *
* Returns: label for hat transition OR ERR_PTR. Does NOT return NULL * Returns: label for hat transition OR ERR_PTR. Does NOT return NULL
*/ */
static struct aa_label *build_change_hat(struct aa_profile *profile, static struct aa_label *build_change_hat(const struct cred *subj_cred,
struct aa_profile *profile,
const char *name, bool sibling) const char *name, bool sibling)
{ {
struct aa_profile *root, *hat = NULL; struct aa_profile *root, *hat = NULL;
@ -1021,7 +1041,8 @@ static struct aa_label *build_change_hat(struct aa_profile *profile,
aa_put_profile(root); aa_put_profile(root);
audit: audit:
aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, AA_MAY_CHANGEHAT, aa_audit_file(subj_cred, profile, &nullperms, OP_CHANGE_HAT,
AA_MAY_CHANGEHAT,
name, hat ? hat->base.hname : NULL, name, hat ? hat->base.hname : NULL,
hat ? &hat->label : NULL, GLOBAL_ROOT_UID, info, hat ? &hat->label : NULL, GLOBAL_ROOT_UID, info,
error); error);
@ -1037,7 +1058,8 @@ audit:
* *
* Returns: label for hat transition or ERR_PTR. Does not return NULL * Returns: label for hat transition or ERR_PTR. Does not return NULL
*/ */
static struct aa_label *change_hat(struct aa_label *label, const char *hats[], static struct aa_label *change_hat(const struct cred *subj_cred,
struct aa_label *label, const char *hats[],
int count, int flags) int count, int flags)
{ {
struct aa_profile *profile, *root, *hat = NULL; struct aa_profile *profile, *root, *hat = NULL;
@ -1113,7 +1135,8 @@ fail:
*/ */
/* TODO: get rid of GLOBAL_ROOT_UID */ /* TODO: get rid of GLOBAL_ROOT_UID */
if (count > 1 || COMPLAIN_MODE(profile)) { if (count > 1 || COMPLAIN_MODE(profile)) {
aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, aa_audit_file(subj_cred, profile, &nullperms,
OP_CHANGE_HAT,
AA_MAY_CHANGEHAT, name, NULL, NULL, AA_MAY_CHANGEHAT, name, NULL, NULL,
GLOBAL_ROOT_UID, info, error); GLOBAL_ROOT_UID, info, error);
} }
@ -1122,7 +1145,8 @@ fail:
build: build:
new = fn_label_build_in_ns(label, profile, GFP_KERNEL, new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
build_change_hat(profile, name, sibling), build_change_hat(subj_cred, profile, name,
sibling),
aa_get_label(&profile->label)); aa_get_label(&profile->label));
if (!new) { if (!new) {
info = "label build failed"; info = "label build failed";
@ -1152,7 +1176,7 @@ build:
*/ */
int aa_change_hat(const char *hats[], int count, u64 token, int flags) int aa_change_hat(const char *hats[], int count, u64 token, int flags)
{ {
const struct cred *cred; const struct cred *subj_cred;
struct aa_task_ctx *ctx = task_ctx(current); struct aa_task_ctx *ctx = task_ctx(current);
struct aa_label *label, *previous, *new = NULL, *target = NULL; struct aa_label *label, *previous, *new = NULL, *target = NULL;
struct aa_profile *profile; struct aa_profile *profile;
@ -1161,8 +1185,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
int error = 0; int error = 0;
/* released below */ /* released below */
cred = get_current_cred(); subj_cred = get_current_cred();
label = aa_get_newest_cred_label(cred); label = aa_get_newest_cred_label(subj_cred);
previous = aa_get_newest_label(ctx->previous); previous = aa_get_newest_label(ctx->previous);
/* /*
@ -1182,7 +1206,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
} }
if (count) { if (count) {
new = change_hat(label, hats, count, flags); new = change_hat(subj_cred, label, hats, count, flags);
AA_BUG(!new); AA_BUG(!new);
if (IS_ERR(new)) { if (IS_ERR(new)) {
error = PTR_ERR(new); error = PTR_ERR(new);
@ -1191,7 +1215,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
goto out; goto out;
} }
error = may_change_ptraced_domain(new, &info); /* target cred is the same as current except new label */
error = may_change_ptraced_domain(subj_cred, new, &info);
if (error) if (error)
goto fail; goto fail;
@ -1244,7 +1269,7 @@ out:
aa_put_label(new); aa_put_label(new);
aa_put_label(previous); aa_put_label(previous);
aa_put_label(label); aa_put_label(label);
put_cred(cred); put_cred(subj_cred);
return error; return error;
@ -1254,7 +1279,7 @@ kill:
fail: fail:
fn_for_each_in_ns(label, profile, fn_for_each_in_ns(label, profile,
aa_audit_file(profile, &perms, OP_CHANGE_HAT, aa_audit_file(subj_cred, profile, &perms, OP_CHANGE_HAT,
AA_MAY_CHANGEHAT, NULL, NULL, target, AA_MAY_CHANGEHAT, NULL, NULL, target,
GLOBAL_ROOT_UID, info, error)); GLOBAL_ROOT_UID, info, error));
@ -1263,6 +1288,7 @@ fail:
static int change_profile_perms_wrapper(const char *op, const char *name, static int change_profile_perms_wrapper(const char *op, const char *name,
const struct cred *subj_cred,
struct aa_profile *profile, struct aa_profile *profile,
struct aa_label *target, bool stack, struct aa_label *target, bool stack,
u32 request, struct aa_perms *perms) u32 request, struct aa_perms *perms)
@ -1277,7 +1303,8 @@ static int change_profile_perms_wrapper(const char *op, const char *name,
rules->file.start[AA_CLASS_FILE], rules->file.start[AA_CLASS_FILE],
perms); perms);
if (error) if (error)
error = aa_audit_file(profile, perms, op, request, name, error = aa_audit_file(subj_cred, profile, perms, op, request,
name,
NULL, target, GLOBAL_ROOT_UID, info, NULL, target, GLOBAL_ROOT_UID, info,
error); error);
@ -1306,6 +1333,7 @@ int aa_change_profile(const char *fqname, int flags)
const char *auditname = fqname; /* retain leading & if stack */ const char *auditname = fqname; /* retain leading & if stack */
bool stack = flags & AA_CHANGE_STACK; bool stack = flags & AA_CHANGE_STACK;
struct aa_task_ctx *ctx = task_ctx(current); struct aa_task_ctx *ctx = task_ctx(current);
const struct cred *subj_cred = get_current_cred();
int error = 0; int error = 0;
char *op; char *op;
u32 request; u32 request;
@ -1383,6 +1411,7 @@ int aa_change_profile(const char *fqname, int flags)
*/ */
error = fn_for_each_in_ns(label, profile, error = fn_for_each_in_ns(label, profile,
change_profile_perms_wrapper(op, auditname, change_profile_perms_wrapper(op, auditname,
subj_cred,
profile, target, stack, profile, target, stack,
request, &perms)); request, &perms));
if (error) if (error)
@ -1393,7 +1422,7 @@ int aa_change_profile(const char *fqname, int flags)
check: check:
/* check if tracing task is allowed to trace target domain */ /* check if tracing task is allowed to trace target domain */
error = may_change_ptraced_domain(target, &info); error = may_change_ptraced_domain(subj_cred, target, &info);
if (error && !fn_for_each_in_ns(label, profile, if (error && !fn_for_each_in_ns(label, profile,
COMPLAIN_MODE(profile))) COMPLAIN_MODE(profile)))
goto audit; goto audit;
@ -1453,7 +1482,8 @@ check:
audit: audit:
error = fn_for_each_in_ns(label, profile, error = fn_for_each_in_ns(label, profile,
aa_audit_file(profile, &perms, op, request, auditname, aa_audit_file(subj_cred,
profile, &perms, op, request, auditname,
NULL, new ? new : target, NULL, new ? new : target,
GLOBAL_ROOT_UID, info, error)); GLOBAL_ROOT_UID, info, error));
@ -1461,6 +1491,7 @@ out:
aa_put_label(new); aa_put_label(new);
aa_put_label(target); aa_put_label(target);
aa_put_label(label); aa_put_label(label);
put_cred(subj_cred);
return error; return error;
} }

View File

@ -45,7 +45,7 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
{ {
struct common_audit_data *sa = va; struct common_audit_data *sa = va;
struct apparmor_audit_data *ad = aad(sa); struct apparmor_audit_data *ad = aad(sa);
kuid_t fsuid = current_fsuid(); kuid_t fsuid = ad->subj_cred ? ad->subj_cred->fsuid : current_fsuid();
char str[10]; char str[10];
if (ad->request & AA_AUDIT_FILE_MASK) { if (ad->request & AA_AUDIT_FILE_MASK) {
@ -77,6 +77,7 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
/** /**
* aa_audit_file - handle the auditing of file operations * aa_audit_file - handle the auditing of file operations
* @subj_cred: cred of the subject
* @profile: the profile being enforced (NOT NULL) * @profile: the profile being enforced (NOT NULL)
* @perms: the permissions computed for the request (NOT NULL) * @perms: the permissions computed for the request (NOT NULL)
* @op: operation being mediated * @op: operation being mediated
@ -90,7 +91,8 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
* *
* Returns: %0 or error on failure * Returns: %0 or error on failure
*/ */
int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, int aa_audit_file(const struct cred *subj_cred,
struct aa_profile *profile, struct aa_perms *perms,
const char *op, u32 request, const char *name, const char *op, u32 request, const char *name,
const char *target, struct aa_label *tlabel, const char *target, struct aa_label *tlabel,
kuid_t ouid, const char *info, int error) kuid_t ouid, const char *info, int error)
@ -98,6 +100,7 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms,
int type = AUDIT_APPARMOR_AUTO; int type = AUDIT_APPARMOR_AUTO;
DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op); DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op);
ad.subj_cred = subj_cred;
ad.request = request; ad.request = request;
ad.name = name; ad.name = name;
ad.fs.target = target; ad.fs.target = target;
@ -141,7 +144,21 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms,
return aa_audit(type, profile, &ad, file_audit_cb); return aa_audit(type, profile, &ad, file_audit_cb);
} }
static int path_name(const char *op, struct aa_label *label, /**
* is_deleted - test if a file has been completely unlinked
* @dentry: dentry of file to test for deletion (NOT NULL)
*
* Returns: true if deleted else false
*/
static inline bool is_deleted(struct dentry *dentry)
{
if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0)
return true;
return false;
}
static int path_name(const char *op, const struct cred *subj_cred,
struct aa_label *label,
const struct path *path, int flags, char *buffer, const struct path *path, int flags, char *buffer,
const char **name, struct path_cond *cond, u32 request) const char **name, struct path_cond *cond, u32 request)
{ {
@ -153,7 +170,8 @@ static int path_name(const char *op, struct aa_label *label,
labels_profile(label)->disconnected); labels_profile(label)->disconnected);
if (error) { if (error) {
fn_for_each_confined(label, profile, fn_for_each_confined(label, profile,
aa_audit_file(profile, &nullperms, op, request, *name, aa_audit_file(subj_cred,
profile, &nullperms, op, request, *name,
NULL, NULL, cond->uid, info, error)); NULL, NULL, cond->uid, info, error));
return error; return error;
} }
@ -207,9 +225,9 @@ aa_state_t aa_str_perms(struct aa_policydb *file_rules, aa_state_t start,
return state; return state;
} }
static int __aa_path_perm(const char *op, struct aa_profile *profile, static int __aa_path_perm(const char *op, const struct cred *subj_cred,
const char *name, u32 request, struct aa_profile *profile, const char *name,
struct path_cond *cond, int flags, u32 request, struct path_cond *cond, int flags,
struct aa_perms *perms) struct aa_perms *perms)
{ {
struct aa_ruleset *rules = list_first_entry(&profile->rules, struct aa_ruleset *rules = list_first_entry(&profile->rules,
@ -222,12 +240,14 @@ static int __aa_path_perm(const char *op, struct aa_profile *profile,
name, cond, perms); name, cond, perms);
if (request & ~perms->allow) if (request & ~perms->allow)
e = -EACCES; e = -EACCES;
return aa_audit_file(profile, perms, op, request, name, NULL, NULL, return aa_audit_file(subj_cred,
profile, perms, op, request, name, NULL, NULL,
cond->uid, NULL, e); cond->uid, NULL, e);
} }
static int profile_path_perm(const char *op, struct aa_profile *profile, static int profile_path_perm(const char *op, const struct cred *subj_cred,
struct aa_profile *profile,
const struct path *path, char *buffer, u32 request, const struct path *path, char *buffer, u32 request,
struct path_cond *cond, int flags, struct path_cond *cond, int flags,
struct aa_perms *perms) struct aa_perms *perms)
@ -238,18 +258,19 @@ static int profile_path_perm(const char *op, struct aa_profile *profile,
if (profile_unconfined(profile)) if (profile_unconfined(profile))
return 0; return 0;
error = path_name(op, &profile->label, path, error = path_name(op, subj_cred, &profile->label, path,
flags | profile->path_flags, buffer, &name, cond, flags | profile->path_flags, buffer, &name, cond,
request); request);
if (error) if (error)
return error; return error;
return __aa_path_perm(op, profile, name, request, cond, flags, return __aa_path_perm(op, subj_cred, profile, name, request, cond,
perms); flags, perms);
} }
/** /**
* aa_path_perm - do permissions check & audit for @path * aa_path_perm - do permissions check & audit for @path
* @op: operation being checked * @op: operation being checked
* @subj_cred: subject cred
* @label: profile being enforced (NOT NULL) * @label: profile being enforced (NOT NULL)
* @path: path to check permissions of (NOT NULL) * @path: path to check permissions of (NOT NULL)
* @flags: any additional path flags beyond what the profile specifies * @flags: any additional path flags beyond what the profile specifies
@ -258,7 +279,8 @@ static int profile_path_perm(const char *op, struct aa_profile *profile,
* *
* Returns: %0 else error if access denied or other error * Returns: %0 else error if access denied or other error
*/ */
int aa_path_perm(const char *op, struct aa_label *label, int aa_path_perm(const char *op, const struct cred *subj_cred,
struct aa_label *label,
const struct path *path, int flags, u32 request, const struct path *path, int flags, u32 request,
struct path_cond *cond) struct path_cond *cond)
{ {
@ -273,8 +295,8 @@ int aa_path_perm(const char *op, struct aa_label *label,
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
profile_path_perm(op, profile, path, buffer, request, profile_path_perm(op, subj_cred, profile, path, buffer,
cond, flags, &perms)); request, cond, flags, &perms));
aa_put_buffer(buffer); aa_put_buffer(buffer);
@ -301,7 +323,8 @@ static inline bool xindex_is_subset(u32 link, u32 target)
return true; return true;
} }
static int profile_path_link(struct aa_profile *profile, static int profile_path_link(const struct cred *subj_cred,
struct aa_profile *profile,
const struct path *link, char *buffer, const struct path *link, char *buffer,
const struct path *target, char *buffer2, const struct path *target, char *buffer2,
struct path_cond *cond) struct path_cond *cond)
@ -315,13 +338,15 @@ static int profile_path_link(struct aa_profile *profile,
aa_state_t state; aa_state_t state;
int error; int error;
error = path_name(OP_LINK, &profile->label, link, profile->path_flags, error = path_name(OP_LINK, subj_cred, &profile->label, link,
profile->path_flags,
buffer, &lname, cond, AA_MAY_LINK); buffer, &lname, cond, AA_MAY_LINK);
if (error) if (error)
goto audit; goto audit;
/* buffer2 freed below, tname is pointer in buffer2 */ /* buffer2 freed below, tname is pointer in buffer2 */
error = path_name(OP_LINK, &profile->label, target, profile->path_flags, error = path_name(OP_LINK, subj_cred, &profile->label, target,
profile->path_flags,
buffer2, &tname, cond, AA_MAY_LINK); buffer2, &tname, cond, AA_MAY_LINK);
if (error) if (error)
goto audit; goto audit;
@ -381,12 +406,14 @@ done_tests:
error = 0; error = 0;
audit: audit:
return aa_audit_file(profile, &lperms, OP_LINK, request, lname, tname, return aa_audit_file(subj_cred,
profile, &lperms, OP_LINK, request, lname, tname,
NULL, cond->uid, info, error); NULL, cond->uid, info, error);
} }
/** /**
* aa_path_link - Handle hard link permission check * aa_path_link - Handle hard link permission check
* @subj_cred: subject cred
* @label: the label being enforced (NOT NULL) * @label: the label being enforced (NOT NULL)
* @old_dentry: the target dentry (NOT NULL) * @old_dentry: the target dentry (NOT NULL)
* @new_dir: directory the new link will be created in (NOT NULL) * @new_dir: directory the new link will be created in (NOT NULL)
@ -403,7 +430,8 @@ audit:
* *
* Returns: %0 if allowed else error * Returns: %0 if allowed else error
*/ */
int aa_path_link(struct aa_label *label, struct dentry *old_dentry, int aa_path_link(const struct cred *subj_cred,
struct aa_label *label, struct dentry *old_dentry,
const struct path *new_dir, struct dentry *new_dentry) const struct path *new_dir, struct dentry *new_dentry)
{ {
struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry }; struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry };
@ -424,8 +452,8 @@ int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
goto out; goto out;
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
profile_path_link(profile, &link, buffer, &target, profile_path_link(subj_cred, profile, &link, buffer,
buffer2, &cond)); &target, buffer2, &cond));
out: out:
aa_put_buffer(buffer); aa_put_buffer(buffer);
aa_put_buffer(buffer2); aa_put_buffer(buffer2);
@ -453,7 +481,8 @@ static void update_file_ctx(struct aa_file_ctx *fctx, struct aa_label *label,
spin_unlock(&fctx->lock); spin_unlock(&fctx->lock);
} }
static int __file_path_perm(const char *op, struct aa_label *label, static int __file_path_perm(const char *op, const struct cred *subj_cred,
struct aa_label *label,
struct aa_label *flabel, struct file *file, struct aa_label *flabel, struct file *file,
u32 request, u32 denied, bool in_atomic) u32 request, u32 denied, bool in_atomic)
{ {
@ -480,7 +509,8 @@ static int __file_path_perm(const char *op, struct aa_label *label,
/* check every profile in task label not in current cache */ /* check every profile in task label not in current cache */
error = fn_for_each_not_in_set(flabel, label, profile, error = fn_for_each_not_in_set(flabel, label, profile,
profile_path_perm(op, profile, &file->f_path, buffer, profile_path_perm(op, subj_cred, profile,
&file->f_path, buffer,
request, &cond, flags, &perms)); request, &cond, flags, &perms));
if (denied && !error) { if (denied && !error) {
/* /*
@ -493,12 +523,14 @@ static int __file_path_perm(const char *op, struct aa_label *label,
*/ */
if (label == flabel) if (label == flabel)
error = fn_for_each(label, profile, error = fn_for_each(label, profile,
profile_path_perm(op, profile, &file->f_path, profile_path_perm(op, subj_cred,
profile, &file->f_path,
buffer, request, &cond, flags, buffer, request, &cond, flags,
&perms)); &perms));
else else
error = fn_for_each_not_in_set(label, flabel, profile, error = fn_for_each_not_in_set(label, flabel, profile,
profile_path_perm(op, profile, &file->f_path, profile_path_perm(op, subj_cred,
profile, &file->f_path,
buffer, request, &cond, flags, buffer, request, &cond, flags,
&perms)); &perms));
} }
@ -510,7 +542,8 @@ static int __file_path_perm(const char *op, struct aa_label *label,
return error; return error;
} }
static int __file_sock_perm(const char *op, struct aa_label *label, static int __file_sock_perm(const char *op, const struct cred *subj_cred,
struct aa_label *label,
struct aa_label *flabel, struct file *file, struct aa_label *flabel, struct file *file,
u32 request, u32 denied) u32 request, u32 denied)
{ {
@ -524,11 +557,12 @@ static int __file_sock_perm(const char *op, struct aa_label *label,
return 0; return 0;
/* TODO: improve to skip profiles cached in flabel */ /* TODO: improve to skip profiles cached in flabel */
error = aa_sock_file_perm(label, op, request, sock); error = aa_sock_file_perm(subj_cred, label, op, request, sock);
if (denied) { if (denied) {
/* TODO: improve to skip profiles checked above */ /* TODO: improve to skip profiles checked above */
/* check every profile in file label to is cached */ /* check every profile in file label to is cached */
last_error(error, aa_sock_file_perm(flabel, op, request, sock)); last_error(error, aa_sock_file_perm(subj_cred, flabel, op,
request, sock));
} }
if (!error) if (!error)
update_file_ctx(file_ctx(file), label, request); update_file_ctx(file_ctx(file), label, request);
@ -539,6 +573,7 @@ static int __file_sock_perm(const char *op, struct aa_label *label,
/** /**
* aa_file_perm - do permission revalidation check & audit for @file * aa_file_perm - do permission revalidation check & audit for @file
* @op: operation being checked * @op: operation being checked
* @subj_cred: subject cred
* @label: label being enforced (NOT NULL) * @label: label being enforced (NOT NULL)
* @file: file to revalidate access permissions on (NOT NULL) * @file: file to revalidate access permissions on (NOT NULL)
* @request: requested permissions * @request: requested permissions
@ -546,7 +581,8 @@ static int __file_sock_perm(const char *op, struct aa_label *label,
* *
* Returns: %0 if access allowed else error * Returns: %0 if access allowed else error
*/ */
int aa_file_perm(const char *op, struct aa_label *label, struct file *file, int aa_file_perm(const char *op, const struct cred *subj_cred,
struct aa_label *label, struct file *file,
u32 request, bool in_atomic) u32 request, bool in_atomic)
{ {
struct aa_file_ctx *fctx; struct aa_file_ctx *fctx;
@ -582,19 +618,19 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
/* TODO: label cross check */ /* TODO: label cross check */
if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry))
error = __file_path_perm(op, label, flabel, file, request, error = __file_path_perm(op, subj_cred, label, flabel, file,
denied, in_atomic); request, denied, in_atomic);
else if (S_ISSOCK(file_inode(file)->i_mode)) else if (S_ISSOCK(file_inode(file)->i_mode))
error = __file_sock_perm(op, label, flabel, file, request, error = __file_sock_perm(op, subj_cred, label, flabel, file,
denied); request, denied);
aa_put_label(flabel); aa_put_label(flabel);
done: done:
return error; return error;
} }
static void revalidate_tty(struct aa_label *label) static void revalidate_tty(const struct cred *subj_cred, struct aa_label *label)
{ {
struct tty_struct *tty; struct tty_struct *tty;
int drop_tty = 0; int drop_tty = 0;
@ -612,8 +648,8 @@ static void revalidate_tty(struct aa_label *label)
struct tty_file_private, list); struct tty_file_private, list);
file = file_priv->file; file = file_priv->file;
if (aa_file_perm(OP_INHERIT, label, file, MAY_READ | MAY_WRITE, if (aa_file_perm(OP_INHERIT, subj_cred, label, file,
IN_ATOMIC)) MAY_READ | MAY_WRITE, IN_ATOMIC))
drop_tty = 1; drop_tty = 1;
} }
spin_unlock(&tty->files_lock); spin_unlock(&tty->files_lock);
@ -623,12 +659,17 @@ static void revalidate_tty(struct aa_label *label)
no_tty(); no_tty();
} }
struct cred_label {
const struct cred *cred;
struct aa_label *label;
};
static int match_file(const void *p, struct file *file, unsigned int fd) static int match_file(const void *p, struct file *file, unsigned int fd)
{ {
struct aa_label *label = (struct aa_label *)p; struct cred_label *cl = (struct cred_label *)p;
if (aa_file_perm(OP_INHERIT, label, file, aa_map_file_to_perms(file), if (aa_file_perm(OP_INHERIT, cl->cred, cl->label, file,
IN_ATOMIC)) aa_map_file_to_perms(file), IN_ATOMIC))
return fd + 1; return fd + 1;
return 0; return 0;
} }
@ -638,13 +679,17 @@ static int match_file(const void *p, struct file *file, unsigned int fd)
void aa_inherit_files(const struct cred *cred, struct files_struct *files) void aa_inherit_files(const struct cred *cred, struct files_struct *files)
{ {
struct aa_label *label = aa_get_newest_cred_label(cred); struct aa_label *label = aa_get_newest_cred_label(cred);
struct cred_label cl = {
.cred = cred,
.label = label,
};
struct file *devnull = NULL; struct file *devnull = NULL;
unsigned int n; unsigned int n;
revalidate_tty(label); revalidate_tty(cred, label);
/* Revalidate access to inherited open files. */ /* Revalidate access to inherited open files. */
n = iterate_fd(files, 0, match_file, label); n = iterate_fd(files, 0, match_file, &cl);
if (!n) /* none found? */ if (!n) /* none found? */
goto out; goto out;
@ -654,7 +699,7 @@ void aa_inherit_files(const struct cred *cred, struct files_struct *files)
/* replace all the matching ones with this */ /* replace all the matching ones with this */
do { do {
replace_fd(n - 1, devnull, 0); replace_fd(n - 1, devnull, 0);
} while ((n = iterate_fd(files, n, match_file, label)) != 0); } while ((n = iterate_fd(files, n, match_file, &cl)) != 0);
if (devnull) if (devnull)
fput(devnull); fput(devnull);
out: out:

View File

@ -109,6 +109,7 @@ struct apparmor_audit_data {
int type; int type;
u16 class; u16 class;
const char *op; const char *op;
const struct cred *subj_cred;
struct aa_label *subj_label; struct aa_label *subj_label;
const char *name; const char *name;
const char *info; const char *info;

View File

@ -36,7 +36,8 @@ struct aa_caps {
extern struct aa_sfs_entry aa_sfs_entry_caps[]; extern struct aa_sfs_entry aa_sfs_entry_caps[];
int aa_capable(struct aa_label *label, int cap, unsigned int opts); int aa_capable(const struct cred *subj_cred, struct aa_label *label,
int cap, unsigned int opts);
static inline void aa_free_cap_rules(struct aa_caps *caps) static inline void aa_free_cap_rules(struct aa_caps *caps)
{ {

View File

@ -71,7 +71,8 @@ struct path_cond {
#define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill) #define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill)
int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, int aa_audit_file(const struct cred *cred,
struct aa_profile *profile, struct aa_perms *perms,
const char *op, u32 request, const char *name, const char *op, u32 request, const char *name,
const char *target, struct aa_label *tlabel, kuid_t ouid, const char *target, struct aa_label *tlabel, kuid_t ouid,
const char *info, int error); const char *info, int error);
@ -82,14 +83,16 @@ aa_state_t aa_str_perms(struct aa_policydb *file_rules, aa_state_t start,
const char *name, struct path_cond *cond, const char *name, struct path_cond *cond,
struct aa_perms *perms); struct aa_perms *perms);
int aa_path_perm(const char *op, struct aa_label *label, int aa_path_perm(const char *op, const struct cred *subj_cred,
const struct path *path, int flags, u32 request, struct aa_label *label, const struct path *path,
struct path_cond *cond); int flags, u32 request, struct path_cond *cond);
int aa_path_link(struct aa_label *label, struct dentry *old_dentry, int aa_path_link(const struct cred *subj_cred, struct aa_label *label,
const struct path *new_dir, struct dentry *new_dentry); struct dentry *old_dentry, const struct path *new_dir,
struct dentry *new_dentry);
int aa_file_perm(const char *op, struct aa_label *label, struct file *file, int aa_file_perm(const char *op, const struct cred *subj_cred,
struct aa_label *label, struct file *file,
u32 request, bool in_atomic); u32 request, bool in_atomic);
void aa_inherit_files(const struct cred *cred, struct files_struct *files); void aa_inherit_files(const struct cred *cred, struct files_struct *files);

View File

@ -13,6 +13,8 @@
#include <linux/sched.h> #include <linux/sched.h>
int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig); int aa_may_signal(const struct cred *subj_cred, struct aa_label *sender,
const struct cred *target_cred, struct aa_label *target,
int sig);
#endif /* __AA_IPC_H */ #endif /* __AA_IPC_H */

View File

@ -25,26 +25,33 @@
#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN) #define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
int aa_remount(struct aa_label *label, const struct path *path, int aa_remount(const struct cred *subj_cred,
struct aa_label *label, const struct path *path,
unsigned long flags, void *data); unsigned long flags, void *data);
int aa_bind_mount(struct aa_label *label, const struct path *path, int aa_bind_mount(const struct cred *subj_cred,
struct aa_label *label, const struct path *path,
const char *old_name, unsigned long flags); const char *old_name, unsigned long flags);
int aa_mount_change_type(struct aa_label *label, const struct path *path, int aa_mount_change_type(const struct cred *subj_cred,
struct aa_label *label, const struct path *path,
unsigned long flags); unsigned long flags);
int aa_move_mount(struct aa_label *label, const struct path *path, int aa_move_mount(const struct cred *subj_cred,
struct aa_label *label, const struct path *path,
const char *old_name); const char *old_name);
int aa_new_mount(struct aa_label *label, const char *dev_name, int aa_new_mount(const struct cred *subj_cred,
struct aa_label *label, const char *dev_name,
const struct path *path, const char *type, unsigned long flags, const struct path *path, const char *type, unsigned long flags,
void *data); void *data);
int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags); int aa_umount(const struct cred *subj_cred,
struct aa_label *label, struct vfsmount *mnt, int flags);
int aa_pivotroot(struct aa_label *label, const struct path *old_path, int aa_pivotroot(const struct cred *subj_cred,
struct aa_label *label, const struct path *old_path,
const struct path *new_path); const struct path *new_path);
#endif /* __AA_MOUNT_H */ #endif /* __AA_MOUNT_H */

View File

@ -97,7 +97,8 @@ void audit_net_cb(struct audit_buffer *ab, void *va);
int aa_profile_af_perm(struct aa_profile *profile, int aa_profile_af_perm(struct aa_profile *profile,
struct apparmor_audit_data *ad, struct apparmor_audit_data *ad,
u32 request, u16 family, int type); u32 request, u16 family, int type);
int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, int aa_af_perm(const struct cred *subj_cred, struct aa_label *label,
const char *op, u32 request, u16 family,
int type, int protocol); int type, int protocol);
static inline int aa_profile_af_sk_perm(struct aa_profile *profile, static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
struct apparmor_audit_data *ad, struct apparmor_audit_data *ad,
@ -109,7 +110,8 @@ static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
} }
int aa_sk_perm(const char *op, u32 request, struct sock *sk); int aa_sk_perm(const char *op, u32 request, struct sock *sk);
int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label,
const char *op, u32 request,
struct socket *sock); struct socket *sock);
int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, int apparmor_secmark_check(struct aa_label *label, char *op, u32 request,

View File

@ -361,9 +361,12 @@ static inline int AUDIT_MODE(struct aa_profile *profile)
return profile->audit; return profile->audit;
} }
bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns); bool aa_policy_view_capable(const struct cred *subj_cred,
bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns); struct aa_label *label, struct aa_ns *ns);
int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, bool aa_policy_admin_capable(const struct cred *subj_cred,
struct aa_label *label, struct aa_ns *ns);
int aa_may_manage_policy(const struct cred *subj_cred,
struct aa_label *label, struct aa_ns *ns,
u32 mask); u32 mask);
bool aa_current_policy_view_capable(struct aa_ns *ns); bool aa_current_policy_view_capable(struct aa_ns *ns);
bool aa_current_policy_admin_capable(struct aa_ns *ns); bool aa_current_policy_admin_capable(struct aa_ns *ns);

View File

@ -33,7 +33,8 @@ struct aa_rlimit {
extern struct aa_sfs_entry aa_sfs_entry_rlimit[]; extern struct aa_sfs_entry aa_sfs_entry_rlimit[];
int aa_map_resource(int resource); int aa_map_resource(int resource);
int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, int aa_task_setrlimit(const struct cred *subj_cred, struct aa_label *label,
struct task_struct *task,
unsigned int resource, struct rlimit *new_rlim); unsigned int resource, struct rlimit *new_rlim);
void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new); void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new);

View File

@ -91,7 +91,8 @@ static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx)
"segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \
"xcpu xfsz vtalrm prof winch io pwr sys emt lost" "xcpu xfsz vtalrm prof winch io pwr sys emt lost"
int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer,
const struct cred *tracee_cred, struct aa_label *tracee,
u32 request); u32 request);

View File

@ -75,7 +75,8 @@ static void audit_signal_cb(struct audit_buffer *ab, void *va)
FLAGS_NONE, GFP_ATOMIC); FLAGS_NONE, GFP_ATOMIC);
} }
static int profile_signal_perm(struct aa_profile *profile, static int profile_signal_perm(const struct cred *cred,
struct aa_profile *profile,
struct aa_label *peer, u32 request, struct aa_label *peer, u32 request,
struct apparmor_audit_data *ad) struct apparmor_audit_data *ad)
{ {
@ -88,6 +89,7 @@ static int profile_signal_perm(struct aa_profile *profile,
!ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL)) !ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL))
return 0; return 0;
ad->subj_cred = cred;
ad->peer = peer; ad->peer = peer;
/* TODO: secondary cache check <profile, profile, perm> */ /* TODO: secondary cache check <profile, profile, perm> */
state = aa_dfa_next(rules->policy.dfa, state = aa_dfa_next(rules->policy.dfa,
@ -98,7 +100,9 @@ static int profile_signal_perm(struct aa_profile *profile,
return aa_check_perms(profile, &perms, request, ad, audit_signal_cb); return aa_check_perms(profile, &perms, request, ad, audit_signal_cb);
} }
int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig) int aa_may_signal(const struct cred *subj_cred, struct aa_label *sender,
const struct cred *target_cred, struct aa_label *target,
int sig)
{ {
struct aa_profile *profile; struct aa_profile *profile;
DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL); DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL);
@ -106,6 +110,8 @@ int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig)
ad.signal = map_signal_num(sig); ad.signal = map_signal_num(sig);
ad.unmappedsig = sig; ad.unmappedsig = sig;
return xcheck_labels(sender, target, profile, return xcheck_labels(sender, target, profile,
profile_signal_perm(profile, target, MAY_WRITE, &ad), profile_signal_perm(subj_cred, profile, target,
profile_signal_perm(profile, sender, MAY_READ, &ad)); MAY_WRITE, &ad),
profile_signal_perm(target_cred, profile, sender,
MAY_READ, &ad));
} }

View File

@ -116,15 +116,17 @@ static int apparmor_ptrace_access_check(struct task_struct *child,
unsigned int mode) unsigned int mode)
{ {
struct aa_label *tracer, *tracee; struct aa_label *tracer, *tracee;
const struct cred *cred;
int error; int error;
cred = get_task_cred(child);
tracee = cred_label(cred); /* ref count on cred */
tracer = __begin_current_label_crit_section(); tracer = __begin_current_label_crit_section();
tracee = aa_get_task_label(child); error = aa_may_ptrace(current_cred(), tracer, cred, tracee,
error = aa_may_ptrace(tracer, tracee,
(mode & PTRACE_MODE_READ) ? AA_PTRACE_READ (mode & PTRACE_MODE_READ) ? AA_PTRACE_READ
: AA_PTRACE_TRACE); : AA_PTRACE_TRACE);
aa_put_label(tracee);
__end_current_label_crit_section(tracer); __end_current_label_crit_section(tracer);
put_cred(cred);
return error; return error;
} }
@ -132,12 +134,15 @@ static int apparmor_ptrace_access_check(struct task_struct *child,
static int apparmor_ptrace_traceme(struct task_struct *parent) static int apparmor_ptrace_traceme(struct task_struct *parent)
{ {
struct aa_label *tracer, *tracee; struct aa_label *tracer, *tracee;
const struct cred *cred;
int error; int error;
tracee = __begin_current_label_crit_section(); tracee = __begin_current_label_crit_section();
tracer = aa_get_task_label(parent); cred = get_task_cred(parent);
error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE); tracer = cred_label(cred); /* ref count on cred */
aa_put_label(tracer); error = aa_may_ptrace(cred, tracer, current_cred(), tracee,
AA_PTRACE_TRACE);
put_cred(cred);
__end_current_label_crit_section(tracee); __end_current_label_crit_section(tracee);
return error; return error;
@ -188,7 +193,7 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
label = aa_get_newest_cred_label(cred); label = aa_get_newest_cred_label(cred);
if (!unconfined(label)) if (!unconfined(label))
error = aa_capable(label, cap, opts); error = aa_capable(cred, label, cap, opts);
aa_put_label(label); aa_put_label(label);
return error; return error;
@ -211,7 +216,8 @@ static int common_perm(const char *op, const struct path *path, u32 mask,
label = __begin_current_label_crit_section(); label = __begin_current_label_crit_section();
if (!unconfined(label)) if (!unconfined(label))
error = aa_path_perm(op, label, path, 0, mask, cond); error = aa_path_perm(op, current_cred(), label, path, 0, mask,
cond);
__end_current_label_crit_section(label); __end_current_label_crit_section(label);
return error; return error;
@ -357,7 +363,8 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_
label = begin_current_label_crit_section(); label = begin_current_label_crit_section();
if (!unconfined(label)) if (!unconfined(label))
error = aa_path_link(label, old_dentry, new_dir, new_dentry); error = aa_path_link(current_cred(), label, old_dentry, new_dir,
new_dentry);
end_current_label_crit_section(label); end_current_label_crit_section(label);
return error; return error;
@ -396,23 +403,27 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d
vfsuid = i_uid_into_vfsuid(idmap, d_backing_inode(old_dentry)); vfsuid = i_uid_into_vfsuid(idmap, d_backing_inode(old_dentry));
cond_exchange.uid = vfsuid_into_kuid(vfsuid); cond_exchange.uid = vfsuid_into_kuid(vfsuid);
error = aa_path_perm(OP_RENAME_SRC, label, &new_path, 0, error = aa_path_perm(OP_RENAME_SRC, current_cred(),
label, &new_path, 0,
MAY_READ | AA_MAY_GETATTR | MAY_WRITE | MAY_READ | AA_MAY_GETATTR | MAY_WRITE |
AA_MAY_SETATTR | AA_MAY_DELETE, AA_MAY_SETATTR | AA_MAY_DELETE,
&cond_exchange); &cond_exchange);
if (!error) if (!error)
error = aa_path_perm(OP_RENAME_DEST, label, &old_path, error = aa_path_perm(OP_RENAME_DEST, current_cred(),
label, &old_path,
0, MAY_WRITE | AA_MAY_SETATTR | 0, MAY_WRITE | AA_MAY_SETATTR |
AA_MAY_CREATE, &cond_exchange); AA_MAY_CREATE, &cond_exchange);
} }
if (!error) if (!error)
error = aa_path_perm(OP_RENAME_SRC, label, &old_path, 0, error = aa_path_perm(OP_RENAME_SRC, current_cred(),
label, &old_path, 0,
MAY_READ | AA_MAY_GETATTR | MAY_WRITE | MAY_READ | AA_MAY_GETATTR | MAY_WRITE |
AA_MAY_SETATTR | AA_MAY_DELETE, AA_MAY_SETATTR | AA_MAY_DELETE,
&cond); &cond);
if (!error) if (!error)
error = aa_path_perm(OP_RENAME_DEST, label, &new_path, error = aa_path_perm(OP_RENAME_DEST, current_cred(),
label, &new_path,
0, MAY_WRITE | AA_MAY_SETATTR | 0, MAY_WRITE | AA_MAY_SETATTR |
AA_MAY_CREATE, &cond); AA_MAY_CREATE, &cond);
@ -467,7 +478,8 @@ static int apparmor_file_open(struct file *file)
vfsuid = i_uid_into_vfsuid(idmap, inode); vfsuid = i_uid_into_vfsuid(idmap, inode);
cond.uid = vfsuid_into_kuid(vfsuid); cond.uid = vfsuid_into_kuid(vfsuid);
error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, error = aa_path_perm(OP_OPEN, file->f_cred,
label, &file->f_path, 0,
aa_map_file_to_perms(file), &cond); aa_map_file_to_perms(file), &cond);
/* todo cache full allowed permissions set and state */ /* todo cache full allowed permissions set and state */
fctx->allow = aa_map_file_to_perms(file); fctx->allow = aa_map_file_to_perms(file);
@ -507,7 +519,7 @@ static int common_file_perm(const char *op, struct file *file, u32 mask,
return -EACCES; return -EACCES;
label = __begin_current_label_crit_section(); label = __begin_current_label_crit_section();
error = aa_file_perm(op, label, file, mask, in_atomic); error = aa_file_perm(op, current_cred(), label, file, mask, in_atomic);
__end_current_label_crit_section(label); __end_current_label_crit_section(label);
return error; return error;
@ -585,17 +597,21 @@ static int apparmor_sb_mount(const char *dev_name, const struct path *path,
label = __begin_current_label_crit_section(); label = __begin_current_label_crit_section();
if (!unconfined(label)) { if (!unconfined(label)) {
if (flags & MS_REMOUNT) if (flags & MS_REMOUNT)
error = aa_remount(label, path, flags, data); error = aa_remount(current_cred(), label, path, flags,
data);
else if (flags & MS_BIND) else if (flags & MS_BIND)
error = aa_bind_mount(label, path, dev_name, flags); error = aa_bind_mount(current_cred(), label, path,
dev_name, flags);
else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
MS_UNBINDABLE)) MS_UNBINDABLE))
error = aa_mount_change_type(label, path, flags); error = aa_mount_change_type(current_cred(), label,
path, flags);
else if (flags & MS_MOVE) else if (flags & MS_MOVE)
error = aa_move_mount(label, path, dev_name); error = aa_move_mount(current_cred(), label, path,
dev_name);
else else
error = aa_new_mount(label, dev_name, path, type, error = aa_new_mount(current_cred(), label, dev_name,
flags, data); path, type, flags, data);
} }
__end_current_label_crit_section(label); __end_current_label_crit_section(label);
@ -609,7 +625,7 @@ static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
label = __begin_current_label_crit_section(); label = __begin_current_label_crit_section();
if (!unconfined(label)) if (!unconfined(label))
error = aa_umount(label, mnt, flags); error = aa_umount(current_cred(), label, mnt, flags);
__end_current_label_crit_section(label); __end_current_label_crit_section(label);
return error; return error;
@ -623,7 +639,7 @@ static int apparmor_sb_pivotroot(const struct path *old_path,
label = aa_get_current_label(); label = aa_get_current_label();
if (!unconfined(label)) if (!unconfined(label))
error = aa_pivotroot(label, old_path, new_path); error = aa_pivotroot(current_cred(), label, old_path, new_path);
aa_put_label(label); aa_put_label(label);
return error; return error;
@ -785,7 +801,8 @@ static int apparmor_task_setrlimit(struct task_struct *task,
int error = 0; int error = 0;
if (!unconfined(label)) if (!unconfined(label))
error = aa_task_setrlimit(label, task, resource, new_rlim); error = aa_task_setrlimit(current_cred(), label, task,
resource, new_rlim);
__end_current_label_crit_section(label); __end_current_label_crit_section(label);
return error; return error;
@ -794,26 +811,27 @@ static int apparmor_task_setrlimit(struct task_struct *task,
static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo *info, static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo *info,
int sig, const struct cred *cred) int sig, const struct cred *cred)
{ {
const struct cred *tc;
struct aa_label *cl, *tl; struct aa_label *cl, *tl;
int error; int error;
tc = get_task_cred(target);
tl = aa_get_newest_cred_label(tc);
if (cred) { if (cred) {
/* /*
* Dealing with USB IO specific behavior * Dealing with USB IO specific behavior
*/ */
cl = aa_get_newest_cred_label(cred); cl = aa_get_newest_cred_label(cred);
tl = aa_get_task_label(target); error = aa_may_signal(cred, cl, tc, tl, sig);
error = aa_may_signal(cl, tl, sig);
aa_put_label(cl); aa_put_label(cl);
aa_put_label(tl);
return error; return error;
} else {
cl = __begin_current_label_crit_section();
error = aa_may_signal(current_cred(), cl, tc, tl, sig);
__end_current_label_crit_section(cl);
} }
cl = __begin_current_label_crit_section();
tl = aa_get_task_label(target);
error = aa_may_signal(cl, tl, sig);
aa_put_label(tl); aa_put_label(tl);
__end_current_label_crit_section(cl); put_cred(tc);
return error; return error;
} }
@ -879,7 +897,8 @@ static int apparmor_socket_create(int family, int type, int protocol, int kern)
if (!(kern || unconfined(label))) if (!(kern || unconfined(label)))
error = af_select(family, error = af_select(family,
create_perm(label, family, type, protocol), create_perm(label, family, type, protocol),
aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, aa_af_perm(current_cred(), label,
OP_CREATE, AA_MAY_CREATE,
family, type, protocol)); family, type, protocol));
end_current_label_crit_section(label); end_current_label_crit_section(label);

View File

@ -113,6 +113,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
/** /**
* audit_mount - handle the auditing of mount operations * audit_mount - handle the auditing of mount operations
* @subj_cred: cred of the subject
* @profile: the profile being enforced (NOT NULL) * @profile: the profile being enforced (NOT NULL)
* @op: operation being mediated (NOT NULL) * @op: operation being mediated (NOT NULL)
* @name: name of object being mediated (MAYBE NULL) * @name: name of object being mediated (MAYBE NULL)
@ -128,7 +129,8 @@ static void audit_cb(struct audit_buffer *ab, void *va)
* *
* Returns: %0 or error on failure * Returns: %0 or error on failure
*/ */
static int audit_mount(struct aa_profile *profile, const char *op, static int audit_mount(const struct cred *subj_cred,
struct aa_profile *profile, const char *op,
const char *name, const char *src_name, const char *name, const char *src_name,
const char *type, const char *trans, const char *type, const char *trans,
unsigned long flags, const void *data, u32 request, unsigned long flags, const void *data, u32 request,
@ -166,6 +168,7 @@ static int audit_mount(struct aa_profile *profile, const char *op,
return error; return error;
} }
ad.subj_cred = subj_cred;
ad.name = name; ad.name = name;
ad.mnt.src_name = src_name; ad.mnt.src_name = src_name;
ad.mnt.type = type; ad.mnt.type = type;
@ -284,6 +287,7 @@ static int path_flags(struct aa_profile *profile, const struct path *path)
/** /**
* match_mnt_path_str - handle path matching for mount * match_mnt_path_str - handle path matching for mount
* @subj_cred: cred of confined subject
* @profile: the confining profile * @profile: the confining profile
* @mntpath: for the mntpnt (NOT NULL) * @mntpath: for the mntpnt (NOT NULL)
* @buffer: buffer to be used to lookup mntpath * @buffer: buffer to be used to lookup mntpath
@ -296,7 +300,8 @@ static int path_flags(struct aa_profile *profile, const struct path *path)
* *
* Returns: 0 on success else error * Returns: 0 on success else error
*/ */
static int match_mnt_path_str(struct aa_profile *profile, static int match_mnt_path_str(const struct cred *subj_cred,
struct aa_profile *profile,
const struct path *mntpath, char *buffer, const struct path *mntpath, char *buffer,
const char *devname, const char *type, const char *devname, const char *type,
unsigned long flags, void *data, bool binary, unsigned long flags, void *data, bool binary,
@ -337,12 +342,14 @@ static int match_mnt_path_str(struct aa_profile *profile,
error = 0; error = 0;
audit: audit:
return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL, return audit_mount(subj_cred, profile, OP_MOUNT, mntpnt, devname,
type, NULL,
flags, data, AA_MAY_MOUNT, &perms, info, error); flags, data, AA_MAY_MOUNT, &perms, info, error);
} }
/** /**
* match_mnt - handle path matching for mount * match_mnt - handle path matching for mount
* @subj_cred: cred of the subject
* @profile: the confining profile * @profile: the confining profile
* @path: for the mntpnt (NOT NULL) * @path: for the mntpnt (NOT NULL)
* @buffer: buffer to be used to lookup mntpath * @buffer: buffer to be used to lookup mntpath
@ -355,7 +362,8 @@ audit:
* *
* Returns: 0 on success else error * Returns: 0 on success else error
*/ */
static int match_mnt(struct aa_profile *profile, const struct path *path, static int match_mnt(const struct cred *subj_cred,
struct aa_profile *profile, const struct path *path,
char *buffer, const struct path *devpath, char *devbuffer, char *buffer, const struct path *devpath, char *devbuffer,
const char *type, unsigned long flags, void *data, const char *type, unsigned long flags, void *data,
bool binary) bool binary)
@ -379,11 +387,12 @@ static int match_mnt(struct aa_profile *profile, const struct path *path,
devname = ERR_PTR(error); devname = ERR_PTR(error);
} }
return match_mnt_path_str(profile, path, buffer, devname, type, flags, return match_mnt_path_str(subj_cred, profile, path, buffer, devname,
data, binary, info); type, flags, data, binary, info);
} }
int aa_remount(struct aa_label *label, const struct path *path, int aa_remount(const struct cred *subj_cred,
struct aa_label *label, const struct path *path,
unsigned long flags, void *data) unsigned long flags, void *data)
{ {
struct aa_profile *profile; struct aa_profile *profile;
@ -400,14 +409,16 @@ int aa_remount(struct aa_label *label, const struct path *path,
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
match_mnt(profile, path, buffer, NULL, NULL, NULL, match_mnt(subj_cred, profile, path, buffer, NULL,
NULL, NULL,
flags, data, binary)); flags, data, binary));
aa_put_buffer(buffer); aa_put_buffer(buffer);
return error; return error;
} }
int aa_bind_mount(struct aa_label *label, const struct path *path, int aa_bind_mount(const struct cred *subj_cred,
struct aa_label *label, const struct path *path,
const char *dev_name, unsigned long flags) const char *dev_name, unsigned long flags)
{ {
struct aa_profile *profile; struct aa_profile *profile;
@ -434,8 +445,8 @@ int aa_bind_mount(struct aa_label *label, const struct path *path,
goto out; goto out;
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
match_mnt(profile, path, buffer, &old_path, old_buffer, match_mnt(subj_cred, profile, path, buffer, &old_path,
NULL, flags, NULL, false)); old_buffer, NULL, flags, NULL, false));
out: out:
aa_put_buffer(buffer); aa_put_buffer(buffer);
aa_put_buffer(old_buffer); aa_put_buffer(old_buffer);
@ -444,7 +455,8 @@ out:
return error; return error;
} }
int aa_mount_change_type(struct aa_label *label, const struct path *path, int aa_mount_change_type(const struct cred *subj_cred,
struct aa_label *label, const struct path *path,
unsigned long flags) unsigned long flags)
{ {
struct aa_profile *profile; struct aa_profile *profile;
@ -462,14 +474,16 @@ int aa_mount_change_type(struct aa_label *label, const struct path *path,
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
match_mnt(profile, path, buffer, NULL, NULL, NULL, match_mnt(subj_cred, profile, path, buffer, NULL,
NULL, NULL,
flags, NULL, false)); flags, NULL, false));
aa_put_buffer(buffer); aa_put_buffer(buffer);
return error; return error;
} }
int aa_move_mount(struct aa_label *label, const struct path *path, int aa_move_mount(const struct cred *subj_cred,
struct aa_label *label, const struct path *path,
const char *orig_name) const char *orig_name)
{ {
struct aa_profile *profile; struct aa_profile *profile;
@ -493,7 +507,8 @@ int aa_move_mount(struct aa_label *label, const struct path *path,
if (!buffer || !old_buffer) if (!buffer || !old_buffer)
goto out; goto out;
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
match_mnt(profile, path, buffer, &old_path, old_buffer, match_mnt(subj_cred, profile, path, buffer, &old_path,
old_buffer,
NULL, MS_MOVE, NULL, false)); NULL, MS_MOVE, NULL, false));
out: out:
aa_put_buffer(buffer); aa_put_buffer(buffer);
@ -503,9 +518,9 @@ out:
return error; return error;
} }
int aa_new_mount(struct aa_label *label, const char *dev_name, int aa_new_mount(const struct cred *subj_cred, struct aa_label *label,
const struct path *path, const char *type, unsigned long flags, const char *dev_name, const struct path *path,
void *data) const char *type, unsigned long flags, void *data)
{ {
struct aa_profile *profile; struct aa_profile *profile;
char *buffer = NULL, *dev_buffer = NULL; char *buffer = NULL, *dev_buffer = NULL;
@ -550,12 +565,14 @@ int aa_new_mount(struct aa_label *label, const char *dev_name,
goto out; goto out;
} }
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
match_mnt(profile, path, buffer, dev_path, dev_buffer, match_mnt(subj_cred, profile, path, buffer,
dev_path, dev_buffer,
type, flags, data, binary)); type, flags, data, binary));
} else { } else {
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
match_mnt_path_str(profile, path, buffer, dev_name, match_mnt_path_str(subj_cred, profile, path,
type, flags, data, binary, NULL)); buffer, dev_name,
type, flags, data, binary, NULL));
} }
out: out:
@ -567,7 +584,8 @@ out:
return error; return error;
} }
static int profile_umount(struct aa_profile *profile, const struct path *path, static int profile_umount(const struct cred *subj_cred,
struct aa_profile *profile, const struct path *path,
char *buffer) char *buffer)
{ {
struct aa_ruleset *rules = list_first_entry(&profile->rules, struct aa_ruleset *rules = list_first_entry(&profile->rules,
@ -596,11 +614,13 @@ static int profile_umount(struct aa_profile *profile, const struct path *path,
error = -EACCES; error = -EACCES;
audit: audit:
return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL, return audit_mount(subj_cred, profile, OP_UMOUNT, name, NULL, NULL,
NULL, 0, NULL,
AA_MAY_UMOUNT, &perms, info, error); AA_MAY_UMOUNT, &perms, info, error);
} }
int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags) int aa_umount(const struct cred *subj_cred, struct aa_label *label,
struct vfsmount *mnt, int flags)
{ {
struct aa_profile *profile; struct aa_profile *profile;
char *buffer = NULL; char *buffer = NULL;
@ -615,7 +635,7 @@ int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
return -ENOMEM; return -ENOMEM;
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
profile_umount(profile, &path, buffer)); profile_umount(subj_cred, profile, &path, buffer));
aa_put_buffer(buffer); aa_put_buffer(buffer);
return error; return error;
@ -625,7 +645,8 @@ int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
* *
* Returns: label for transition or ERR_PTR. Does not return NULL * Returns: label for transition or ERR_PTR. Does not return NULL
*/ */
static struct aa_label *build_pivotroot(struct aa_profile *profile, static struct aa_label *build_pivotroot(const struct cred *subj_cred,
struct aa_profile *profile,
const struct path *new_path, const struct path *new_path,
char *new_buffer, char *new_buffer,
const struct path *old_path, const struct path *old_path,
@ -670,7 +691,8 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile,
error = 0; error = 0;
audit: audit:
error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name, error = audit_mount(subj_cred, profile, OP_PIVOTROOT, new_name,
old_name,
NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT, NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
&perms, info, error); &perms, info, error);
if (error) if (error)
@ -679,7 +701,8 @@ audit:
return aa_get_newest_label(&profile->label); return aa_get_newest_label(&profile->label);
} }
int aa_pivotroot(struct aa_label *label, const struct path *old_path, int aa_pivotroot(const struct cred *subj_cred, struct aa_label *label,
const struct path *old_path,
const struct path *new_path) const struct path *new_path)
{ {
struct aa_profile *profile; struct aa_profile *profile;
@ -697,7 +720,8 @@ int aa_pivotroot(struct aa_label *label, const struct path *old_path,
if (!old_buffer || !new_buffer) if (!old_buffer || !new_buffer)
goto out; goto out;
target = fn_label_build(label, profile, GFP_KERNEL, target = fn_label_build(label, profile, GFP_KERNEL,
build_pivotroot(profile, new_path, new_buffer, build_pivotroot(subj_cred, profile, new_path,
new_buffer,
old_path, old_buffer)); old_path, old_buffer));
if (!target) { if (!target) {
info = "label build failed"; info = "label build failed";
@ -723,7 +747,8 @@ out:
fail: fail:
/* TODO: add back in auditing of new_name and old_name */ /* TODO: add back in auditing of new_name and old_name */
error = fn_for_each(label, profile, error = fn_for_each(label, profile,
audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */, audit_mount(subj_cred, profile, OP_PIVOTROOT,
NULL /*new_name */,
NULL /* old_name */, NULL /* old_name */,
NULL, NULL, NULL, NULL,
0, NULL, AA_MAY_PIVOTROOT, &nullperms, info, 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,

View File

@ -135,8 +135,8 @@ int aa_profile_af_perm(struct aa_profile *profile,
return aa_check_perms(profile, &perms, request, ad, audit_net_cb); return aa_check_perms(profile, &perms, request, ad, audit_net_cb);
} }
int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, int aa_af_perm(const struct cred *subj_cred, struct aa_label *label,
int type, int protocol) const char *op, u32 request, u16 family, int type, int protocol)
{ {
struct aa_profile *profile; struct aa_profile *profile;
DEFINE_AUDIT_NET(ad, op, NULL, family, type, protocol); DEFINE_AUDIT_NET(ad, op, NULL, family, type, protocol);
@ -146,7 +146,9 @@ int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
type)); type));
} }
static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, static int aa_label_sk_perm(const struct cred *subj_cred,
struct aa_label *label,
const char *op, u32 request,
struct sock *sk) struct sock *sk)
{ {
struct aa_sk_ctx *ctx = SK_CTX(sk); struct aa_sk_ctx *ctx = SK_CTX(sk);
@ -159,6 +161,7 @@ static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
struct aa_profile *profile; struct aa_profile *profile;
DEFINE_AUDIT_SK(ad, op, sk); DEFINE_AUDIT_SK(ad, op, sk);
ad.subj_cred = subj_cred;
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
aa_profile_af_sk_perm(profile, &ad, request, sk)); aa_profile_af_sk_perm(profile, &ad, request, sk));
} }
@ -176,21 +179,21 @@ int aa_sk_perm(const char *op, u32 request, struct sock *sk)
/* TODO: switch to begin_current_label ???? */ /* TODO: switch to begin_current_label ???? */
label = begin_current_label_crit_section(); label = begin_current_label_crit_section();
error = aa_label_sk_perm(label, op, request, sk); error = aa_label_sk_perm(current_cred(), label, op, request, sk);
end_current_label_crit_section(label); end_current_label_crit_section(label);
return error; return error;
} }
int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label,
struct socket *sock) const char *op, u32 request, struct socket *sock)
{ {
AA_BUG(!label); AA_BUG(!label);
AA_BUG(!sock); AA_BUG(!sock);
AA_BUG(!sock->sk); AA_BUG(!sock->sk);
return aa_label_sk_perm(label, op, request, sock->sk); return aa_label_sk_perm(subj_cred, label, op, request, sock->sk);
} }
#ifdef CONFIG_NETWORK_SECMARK #ifdef CONFIG_NETWORK_SECMARK

View File

@ -762,21 +762,23 @@ static int audit_policy(struct aa_label *subj_label, const char *op,
/* don't call out to other LSMs in the stack for apparmor policy admin /* don't call out to other LSMs in the stack for apparmor policy admin
* permissions * permissions
*/ */
static int policy_ns_capable(struct aa_label *label, static int policy_ns_capable(const struct cred *subj_cred,
struct aa_label *label,
struct user_namespace *userns, int cap) struct user_namespace *userns, int cap)
{ {
int err; int err;
/* check for MAC_ADMIN cap in cred */ /* check for MAC_ADMIN cap in cred */
err = cap_capable(current_cred(), userns, cap, CAP_OPT_NONE); err = cap_capable(subj_cred, userns, cap, CAP_OPT_NONE);
if (!err) if (!err)
err = aa_capable(label, cap, CAP_OPT_NONE); err = aa_capable(subj_cred, label, cap, CAP_OPT_NONE);
return err; return err;
} }
/** /**
* aa_policy_view_capable - check if viewing policy in at @ns is allowed * aa_policy_view_capable - check if viewing policy in at @ns is allowed
* @subj_cred: cred of subject
* @label: label that is trying to view policy in ns * @label: label that is trying to view policy in ns
* @ns: namespace being viewed by @label (may be NULL if @label's ns) * @ns: namespace being viewed by @label (may be NULL if @label's ns)
* *
@ -785,9 +787,10 @@ static int policy_ns_capable(struct aa_label *label,
* If @ns is NULL then the namespace being viewed is assumed to be the * If @ns is NULL then the namespace being viewed is assumed to be the
* tasks current namespace. * tasks current namespace.
*/ */
bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns) bool aa_policy_view_capable(const struct cred *subj_cred,
struct aa_label *label, struct aa_ns *ns)
{ {
struct user_namespace *user_ns = current_user_ns(); struct user_namespace *user_ns = subj_cred->user_ns;
struct aa_ns *view_ns = labels_view(label); struct aa_ns *view_ns = labels_view(label);
bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) || bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) ||
in_egroup_p(make_kgid(user_ns, 0)); in_egroup_p(make_kgid(user_ns, 0));
@ -804,15 +807,17 @@ bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns)
return response; return response;
} }
bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns) bool aa_policy_admin_capable(const struct cred *subj_cred,
struct aa_label *label, struct aa_ns *ns)
{ {
struct user_namespace *user_ns = current_user_ns(); struct user_namespace *user_ns = subj_cred->user_ns;
bool capable = policy_ns_capable(label, user_ns, CAP_MAC_ADMIN) == 0; bool capable = policy_ns_capable(subj_cred, label, user_ns,
CAP_MAC_ADMIN) == 0;
AA_DEBUG("cap_mac_admin? %d\n", capable); AA_DEBUG("cap_mac_admin? %d\n", capable);
AA_DEBUG("policy locked? %d\n", aa_g_lock_policy); AA_DEBUG("policy locked? %d\n", aa_g_lock_policy);
return aa_policy_view_capable(label, ns) && capable && return aa_policy_view_capable(subj_cred, label, ns) && capable &&
!aa_g_lock_policy; !aa_g_lock_policy;
} }
@ -822,7 +827,7 @@ bool aa_current_policy_view_capable(struct aa_ns *ns)
bool res; bool res;
label = __begin_current_label_crit_section(); label = __begin_current_label_crit_section();
res = aa_policy_view_capable(label, ns); res = aa_policy_view_capable(current_cred(), label, ns);
__end_current_label_crit_section(label); __end_current_label_crit_section(label);
return res; return res;
@ -834,7 +839,7 @@ bool aa_current_policy_admin_capable(struct aa_ns *ns)
bool res; bool res;
label = __begin_current_label_crit_section(); label = __begin_current_label_crit_section();
res = aa_policy_admin_capable(label, ns); res = aa_policy_admin_capable(current_cred(), label, ns);
__end_current_label_crit_section(label); __end_current_label_crit_section(label);
return res; return res;
@ -842,13 +847,15 @@ bool aa_current_policy_admin_capable(struct aa_ns *ns)
/** /**
* aa_may_manage_policy - can the current task manage policy * aa_may_manage_policy - can the current task manage policy
* @subj_cred; subjects cred
* @label: label to check if it can manage policy * @label: label to check if it can manage policy
* @ns: namespace being managed by @label (may be NULL if @label's ns) * @ns: namespace being managed by @label (may be NULL if @label's ns)
* @mask: contains the policy manipulation operation being done * @mask: contains the policy manipulation operation being done
* *
* Returns: 0 if the task is allowed to manipulate policy else error * Returns: 0 if the task is allowed to manipulate policy else error
*/ */
int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask) int aa_may_manage_policy(const struct cred *subj_cred, struct aa_label *label,
struct aa_ns *ns, u32 mask)
{ {
const char *op; const char *op;
@ -864,7 +871,7 @@ int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask)
return audit_policy(label, op, NULL, NULL, "policy_locked", return audit_policy(label, op, NULL, NULL, "policy_locked",
-EACCES); -EACCES);
if (!aa_policy_admin_capable(label, ns)) if (!aa_policy_admin_capable(subj_cred, label, ns))
return audit_policy(label, op, NULL, NULL, "not policy admin", return audit_policy(label, op, NULL, NULL, "not policy admin",
-EACCES); -EACCES);

View File

@ -43,6 +43,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
/** /**
* audit_resource - audit setting resource limit * audit_resource - audit setting resource limit
* @subj_cred: cred setting the resource
* @profile: profile being enforced (NOT NULL) * @profile: profile being enforced (NOT NULL)
* @resource: rlimit being auditing * @resource: rlimit being auditing
* @value: value being set * @value: value being set
@ -52,13 +53,15 @@ static void audit_cb(struct audit_buffer *ab, void *va)
* *
* Returns: 0 or ad->error else other error code on failure * Returns: 0 or ad->error else other error code on failure
*/ */
static int audit_resource(struct aa_profile *profile, unsigned int resource, static int audit_resource(const struct cred *subj_cred,
struct aa_profile *profile, unsigned int resource,
unsigned long value, struct aa_label *peer, unsigned long value, struct aa_label *peer,
const char *info, int error) const char *info, int error)
{ {
DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_RLIMITS, DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_RLIMITS,
OP_SETRLIMIT); OP_SETRLIMIT);
ad.subj_cred = subj_cred;
ad.rlim.rlim = resource; ad.rlim.rlim = resource;
ad.rlim.max = value; ad.rlim.max = value;
ad.peer = peer; ad.peer = peer;
@ -82,7 +85,8 @@ int aa_map_resource(int resource)
return rlim_map[resource]; return rlim_map[resource];
} }
static int profile_setrlimit(struct aa_profile *profile, unsigned int resource, static int profile_setrlimit(const struct cred *subj_cred,
struct aa_profile *profile, unsigned int resource,
struct rlimit *new_rlim) struct rlimit *new_rlim)
{ {
struct aa_ruleset *rules = list_first_entry(&profile->rules, struct aa_ruleset *rules = list_first_entry(&profile->rules,
@ -92,12 +96,13 @@ static int profile_setrlimit(struct aa_profile *profile, unsigned int resource,
if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max > if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max >
rules->rlimits.limits[resource].rlim_max) rules->rlimits.limits[resource].rlim_max)
e = -EACCES; e = -EACCES;
return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL, return audit_resource(subj_cred, profile, resource, new_rlim->rlim_max,
e); NULL, NULL, e);
} }
/** /**
* aa_task_setrlimit - test permission to set an rlimit * aa_task_setrlimit - test permission to set an rlimit
* @subj_cred: cred setting the limit
* @label: label confining the task (NOT NULL) * @label: label confining the task (NOT NULL)
* @task: task the resource is being set on * @task: task the resource is being set on
* @resource: the resource being set * @resource: the resource being set
@ -107,7 +112,8 @@ static int profile_setrlimit(struct aa_profile *profile, unsigned int resource,
* *
* Returns: 0 or error code if setting resource failed * Returns: 0 or error code if setting resource failed
*/ */
int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, int aa_task_setrlimit(const struct cred *subj_cred, struct aa_label *label,
struct task_struct *task,
unsigned int resource, struct rlimit *new_rlim) unsigned int resource, struct rlimit *new_rlim)
{ {
struct aa_profile *profile; struct aa_profile *profile;
@ -126,14 +132,15 @@ int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
*/ */
if (label != peer && if (label != peer &&
aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0) aa_capable(subj_cred, label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0)
error = fn_for_each(label, profile, error = fn_for_each(label, profile,
audit_resource(profile, resource, audit_resource(subj_cred, profile, resource,
new_rlim->rlim_max, peer, new_rlim->rlim_max, peer,
"cap_sys_resource", -EACCES)); "cap_sys_resource", -EACCES));
else else
error = fn_for_each_confined(label, profile, error = fn_for_each_confined(label, profile,
profile_setrlimit(profile, resource, new_rlim)); profile_setrlimit(subj_cred, profile, resource,
new_rlim));
aa_put_label(peer); aa_put_label(peer);
return error; return error;

View File

@ -223,14 +223,16 @@ static void audit_ptrace_cb(struct audit_buffer *ab, void *va)
/* assumes check for RULE_MEDIATES is already done */ /* assumes check for RULE_MEDIATES is already done */
/* TODO: conditionals */ /* TODO: conditionals */
static int profile_ptrace_perm(struct aa_profile *profile, static int profile_ptrace_perm(const struct cred *cred,
struct aa_label *peer, u32 request, struct aa_profile *profile,
struct apparmor_audit_data *ad) struct aa_label *peer, u32 request,
struct apparmor_audit_data *ad)
{ {
struct aa_ruleset *rules = list_first_entry(&profile->rules, struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list); typeof(*rules), list);
struct aa_perms perms = { }; struct aa_perms perms = { };
ad->subj_cred = cred;
ad->peer = peer; ad->peer = peer;
aa_profile_match_label(profile, rules, peer, AA_CLASS_PTRACE, request, aa_profile_match_label(profile, rules, peer, AA_CLASS_PTRACE, request,
&perms); &perms);
@ -238,7 +240,8 @@ static int profile_ptrace_perm(struct aa_profile *profile,
return aa_check_perms(profile, &perms, request, ad, audit_ptrace_cb); return aa_check_perms(profile, &perms, request, ad, audit_ptrace_cb);
} }
static int profile_tracee_perm(struct aa_profile *tracee, static int profile_tracee_perm(const struct cred *cred,
struct aa_profile *tracee,
struct aa_label *tracer, u32 request, struct aa_label *tracer, u32 request,
struct apparmor_audit_data *ad) struct apparmor_audit_data *ad)
{ {
@ -246,10 +249,11 @@ static int profile_tracee_perm(struct aa_profile *tracee,
!ANY_RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE)) !ANY_RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE))
return 0; return 0;
return profile_ptrace_perm(tracee, tracer, request, ad); return profile_ptrace_perm(cred, tracee, tracer, request, ad);
} }
static int profile_tracer_perm(struct aa_profile *tracer, static int profile_tracer_perm(const struct cred *cred,
struct aa_profile *tracer,
struct aa_label *tracee, u32 request, struct aa_label *tracee, u32 request,
struct apparmor_audit_data *ad) struct apparmor_audit_data *ad)
{ {
@ -257,7 +261,7 @@ static int profile_tracer_perm(struct aa_profile *tracer,
return 0; return 0;
if (ANY_RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE)) if (ANY_RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE))
return profile_ptrace_perm(tracer, tracee, request, ad); return profile_ptrace_perm(cred, tracer, tracee, request, ad);
/* profile uses the old style capability check for ptrace */ /* profile uses the old style capability check for ptrace */
if (&tracer->label == tracee) if (&tracer->label == tracee)
@ -266,8 +270,8 @@ static int profile_tracer_perm(struct aa_profile *tracer,
ad->subj_label = &tracer->label; ad->subj_label = &tracer->label;
ad->peer = tracee; ad->peer = tracee;
ad->request = 0; ad->request = 0;
ad->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, ad->error = aa_capable(cred, &tracer->label, CAP_SYS_PTRACE,
CAP_OPT_NONE); CAP_OPT_NONE);
return aa_audit(AUDIT_APPARMOR_AUTO, tracer, ad, audit_ptrace_cb); return aa_audit(AUDIT_APPARMOR_AUTO, tracer, ad, audit_ptrace_cb);
} }
@ -280,7 +284,8 @@ static int profile_tracer_perm(struct aa_profile *tracer,
* *
* Returns: %0 else error code if permission denied or error * Returns: %0 else error code if permission denied or error
*/ */
int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer,
const struct cred *tracee_cred, struct aa_label *tracee,
u32 request) u32 request)
{ {
struct aa_profile *profile; struct aa_profile *profile;
@ -288,6 +293,8 @@ int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_PTRACE, OP_PTRACE); DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_PTRACE, OP_PTRACE);
return xcheck_labels(tracer, tracee, profile, return xcheck_labels(tracer, tracee, profile,
profile_tracer_perm(profile, tracee, request, &sa), profile_tracer_perm(tracer_cred, profile, tracee,
profile_tracee_perm(profile, tracer, xrequest, &sa)); request, &sa),
profile_tracee_perm(tracee_cred, profile, tracer,
xrequest, &sa));
} }