Skip to content

Commit

Permalink
AppArmor: Add selfattr hooks
Browse files Browse the repository at this point in the history
Add hooks for setselfattr and getselfattr. These hooks are not very
different from their setprocattr and getprocattr equivalents, and
much of the code is shared.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Acked-by: John Johansen <john.johansen@canonical.com>
[PM: forward ported beyond v6.6 due merge window changes]
Signed-off-by: Paul Moore <paul@paul-moore.com>
  • Loading branch information
cschaufler authored and pcmoore committed Nov 13, 2023
1 parent 38b323e commit 223981d
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 11 deletions.
2 changes: 1 addition & 1 deletion security/apparmor/include/procattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#ifndef __AA_PROCATTR_H
#define __AA_PROCATTR_H

int aa_getprocattr(struct aa_label *label, char **string);
int aa_getprocattr(struct aa_label *label, char **string, bool newline);
int aa_setprocattr_changehat(char *args, size_t size, int flags);

#endif /* __AA_PROCATTR_H */
91 changes: 85 additions & 6 deletions security/apparmor/lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,55 @@ static int apparmor_sb_pivotroot(const struct path *old_path,
return error;
}

static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx,
size_t *size, u32 flags)
{
int error = -ENOENT;
struct aa_task_ctx *ctx = task_ctx(current);
struct aa_label *label = NULL;
size_t total_len = 0;
char *value;

switch (attr) {
case LSM_ATTR_CURRENT:
label = aa_get_newest_label(cred_label(current_cred()));
break;
case LSM_ATTR_PREV:
if (ctx->previous)
label = aa_get_newest_label(ctx->previous);
break;
case LSM_ATTR_EXEC:
if (ctx->onexec)
label = aa_get_newest_label(ctx->onexec);
break;
default:
error = -EOPNOTSUPP;
break;
}

if (label) {
error = aa_getprocattr(label, &value, false);
if (error > 0) {
total_len = ALIGN(struct_size(lx, ctx, error), 8);
if (total_len > *size)
error = -E2BIG;
else if (lx)
error = lsm_fill_user_ctx(lx, value, error,
LSM_ID_APPARMOR, 0);
else
error = 1;
}
kfree(value);
}

aa_put_label(label);

*size = total_len;
if (error < 0)
return error;
return 1;
}

static int apparmor_getprocattr(struct task_struct *task, const char *name,
char **value)
{
Expand All @@ -795,16 +844,15 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name,
error = -EINVAL;

if (label)
error = aa_getprocattr(label, value);
error = aa_getprocattr(label, value, true);

aa_put_label(label);
put_cred(cred);

return error;
}

static int apparmor_setprocattr(const char *name, void *value,
size_t size)
static int do_setattr(u64 attr, void *value, size_t size)
{
char *command, *largs = NULL, *args = value;
size_t arg_size;
Expand Down Expand Up @@ -835,7 +883,7 @@ static int apparmor_setprocattr(const char *name, void *value,
goto out;

arg_size = size - (args - (largs ? largs : (char *) value));
if (strcmp(name, "current") == 0) {
if (attr == LSM_ATTR_CURRENT) {
if (strcmp(command, "changehat") == 0) {
error = aa_setprocattr_changehat(args, arg_size,
AA_CHANGE_NOFLAGS);
Expand All @@ -850,7 +898,7 @@ static int apparmor_setprocattr(const char *name, void *value,
error = aa_change_profile(args, AA_CHANGE_STACK);
} else
goto fail;
} else if (strcmp(name, "exec") == 0) {
} else if (attr == LSM_ATTR_EXEC) {
if (strcmp(command, "exec") == 0)
error = aa_change_profile(args, AA_CHANGE_ONEXEC);
else if (strcmp(command, "stack") == 0)
Expand All @@ -870,13 +918,42 @@ static int apparmor_setprocattr(const char *name, void *value,

fail:
ad.subj_label = begin_current_label_crit_section();
ad.info = name;
if (attr == LSM_ATTR_CURRENT)
ad.info = "current";
else if (attr == LSM_ATTR_EXEC)
ad.info = "exec";
else
ad.info = "invalid";
ad.error = error = -EINVAL;
aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL);
end_current_label_crit_section(ad.subj_label);
goto out;
}

static int apparmor_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
size_t size, u32 flags)
{
int rc;

if (attr != LSM_ATTR_CURRENT && attr != LSM_ATTR_EXEC)
return -EOPNOTSUPP;

rc = do_setattr(attr, ctx->ctx, ctx->ctx_len);
if (rc > 0)
return 0;
return rc;
}

static int apparmor_setprocattr(const char *name, void *value,
size_t size)
{
int attr = lsm_name_to_attr(name);

if (attr)
return do_setattr(attr, value, size);
return -EINVAL;
}

/**
* apparmor_bprm_committing_creds - do task cleanup on committing new creds
* @bprm: binprm for the exec (NOT NULL)
Expand Down Expand Up @@ -1424,6 +1501,8 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = {
LSM_HOOK_INIT(file_lock, apparmor_file_lock),
LSM_HOOK_INIT(file_truncate, apparmor_file_truncate),

LSM_HOOK_INIT(getselfattr, apparmor_getselfattr),
LSM_HOOK_INIT(setselfattr, apparmor_setselfattr),
LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),

Expand Down
10 changes: 6 additions & 4 deletions security/apparmor/procattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@
* aa_getprocattr - Return the label information for @label
* @label: the label to print label info about (NOT NULL)
* @string: Returns - string containing the label info (NOT NULL)
* @newline: indicates that a newline should be added
*
* Requires: label != NULL && string != NULL
*
* Creates a string containing the label information for @label.
*
* Returns: size of string placed in @string else error code on failure
*/
int aa_getprocattr(struct aa_label *label, char **string)
int aa_getprocattr(struct aa_label *label, char **string, bool newline)
{
struct aa_ns *ns = labels_ns(label);
struct aa_ns *current_ns = aa_get_current_ns();
Expand Down Expand Up @@ -57,11 +58,12 @@ int aa_getprocattr(struct aa_label *label, char **string)
return len;
}

(*string)[len] = '\n';
(*string)[len + 1] = 0;
if (newline)
(*string)[len++] = '\n';
(*string)[len] = 0;

aa_put_ns(current_ns);
return len + 1;
return len;
}

/**
Expand Down

0 comments on commit 223981d

Please sign in to comment.