AppArmor: Add selfattr hooks

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>
This commit is contained in:
Casey Schaufler 2023-09-12 13:56:54 -07:00 committed by Paul Moore
parent 38b323e588
commit 223981db9b
3 changed files with 92 additions and 11 deletions

View File

@ -11,7 +11,7 @@
#ifndef __AA_PROCATTR_H #ifndef __AA_PROCATTR_H
#define __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); int aa_setprocattr_changehat(char *args, size_t size, int flags);
#endif /* __AA_PROCATTR_H */ #endif /* __AA_PROCATTR_H */

View File

@ -776,6 +776,55 @@ static int apparmor_sb_pivotroot(const struct path *old_path,
return error; 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, static int apparmor_getprocattr(struct task_struct *task, const char *name,
char **value) char **value)
{ {
@ -795,7 +844,7 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name,
error = -EINVAL; error = -EINVAL;
if (label) if (label)
error = aa_getprocattr(label, value); error = aa_getprocattr(label, value, true);
aa_put_label(label); aa_put_label(label);
put_cred(cred); put_cred(cred);
@ -803,8 +852,7 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name,
return error; return error;
} }
static int apparmor_setprocattr(const char *name, void *value, static int do_setattr(u64 attr, void *value, size_t size)
size_t size)
{ {
char *command, *largs = NULL, *args = value; char *command, *largs = NULL, *args = value;
size_t arg_size; size_t arg_size;
@ -835,7 +883,7 @@ static int apparmor_setprocattr(const char *name, void *value,
goto out; goto out;
arg_size = size - (args - (largs ? largs : (char *) value)); arg_size = size - (args - (largs ? largs : (char *) value));
if (strcmp(name, "current") == 0) { if (attr == LSM_ATTR_CURRENT) {
if (strcmp(command, "changehat") == 0) { if (strcmp(command, "changehat") == 0) {
error = aa_setprocattr_changehat(args, arg_size, error = aa_setprocattr_changehat(args, arg_size,
AA_CHANGE_NOFLAGS); AA_CHANGE_NOFLAGS);
@ -850,7 +898,7 @@ static int apparmor_setprocattr(const char *name, void *value,
error = aa_change_profile(args, AA_CHANGE_STACK); error = aa_change_profile(args, AA_CHANGE_STACK);
} else } else
goto fail; goto fail;
} else if (strcmp(name, "exec") == 0) { } else if (attr == LSM_ATTR_EXEC) {
if (strcmp(command, "exec") == 0) if (strcmp(command, "exec") == 0)
error = aa_change_profile(args, AA_CHANGE_ONEXEC); error = aa_change_profile(args, AA_CHANGE_ONEXEC);
else if (strcmp(command, "stack") == 0) else if (strcmp(command, "stack") == 0)
@ -870,13 +918,42 @@ out:
fail: fail:
ad.subj_label = begin_current_label_crit_section(); 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; ad.error = error = -EINVAL;
aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL); aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL);
end_current_label_crit_section(ad.subj_label); end_current_label_crit_section(ad.subj_label);
goto out; 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 * apparmor_bprm_committing_creds - do task cleanup on committing new creds
* @bprm: binprm for the exec (NOT NULL) * @bprm: binprm for the exec (NOT NULL)
@ -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_lock, apparmor_file_lock),
LSM_HOOK_INIT(file_truncate, apparmor_file_truncate), 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(getprocattr, apparmor_getprocattr),
LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),

View File

@ -20,6 +20,7 @@
* aa_getprocattr - Return the label information for @label * aa_getprocattr - Return the label information for @label
* @label: the label to print label info about (NOT NULL) * @label: the label to print label info about (NOT NULL)
* @string: Returns - string containing the label info (NOT NULL) * @string: Returns - string containing the label info (NOT NULL)
* @newline: indicates that a newline should be added
* *
* Requires: label != NULL && string != NULL * Requires: label != NULL && string != NULL
* *
@ -27,7 +28,7 @@
* *
* Returns: size of string placed in @string else error code on failure * 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 *ns = labels_ns(label);
struct aa_ns *current_ns = aa_get_current_ns(); struct aa_ns *current_ns = aa_get_current_ns();
@ -57,11 +58,12 @@ int aa_getprocattr(struct aa_label *label, char **string)
return len; return len;
} }
(*string)[len] = '\n'; if (newline)
(*string)[len + 1] = 0; (*string)[len++] = '\n';
(*string)[len] = 0;
aa_put_ns(current_ns); aa_put_ns(current_ns);
return len + 1; return len;
} }
/** /**