Commit 223981db authored by Casey Schaufler's avatar Casey Schaufler Committed by Paul Moore
Browse files

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: default avatarCasey Schaufler <casey@schaufler-ca.com>
Acked-by: default avatarJohn Johansen <john.johansen@canonical.com>
[PM: forward ported beyond v6.6 due merge window changes]
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent 38b323e5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 */
+85 −6
Original line number Diff line number Diff line
@@ -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)
{
@@ -795,7 +844,7 @@ 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);
@@ -803,8 +852,7 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name,
	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;
@@ -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);
@@ -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)
@@ -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)
@@ -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),

+6 −4
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
 * 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
 *
@@ -27,7 +28,7 @@
 *
 * 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();
@@ -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;
}

/**