All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <keescook@chromium.org>
To: Casey Schaufler <casey@schaufler-ca.com>
Cc: paul@paul-moore.com, linux-security-module@vger.kernel.org,
	jmorris@namei.org, john.johansen@canonical.com,
	penguin-kernel@i-love.sakura.ne.jp,
	stephen.smalley.work@gmail.com, linux-kernel@vger.kernel.org,
	linux-api@vger.kernel.org, mic@digikod.net
Subject: Re: [PATCH v9 09/11] AppArmor: Add selfattr hooks
Date: Fri, 21 Apr 2023 12:54:24 -0700	[thread overview]
Message-ID: <6442e9f1.050a0220.3353e.77fb@mx.google.com> (raw)
In-Reply-To: <20230421174259.2458-10-casey@schaufler-ca.com>

On Fri, Apr 21, 2023 at 10:42:57AM -0700, Casey Schaufler wrote:
> 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>
> Cc: John Johansen <john.johansen@canonical.com>
> ---
>  security/apparmor/include/procattr.h |  2 +-
>  security/apparmor/lsm.c              | 96 ++++++++++++++++++++++++++--
>  security/apparmor/procattr.c         | 11 +++-
>  3 files changed, 99 insertions(+), 10 deletions(-)
> 
> diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
> index 31689437e0e1..03dbfdb2f2c0 100644
> --- a/security/apparmor/include/procattr.h
> +++ b/security/apparmor/include/procattr.h
> @@ -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 */
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index ce6ccb7e06ec..bdaa8bac0404 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -630,6 +630,45 @@ static int apparmor_sb_pivotroot(const struct path *old_path,
>  	return error;
>  }
>  
> +static int apparmor_getselfattr(unsigned int __user attr,
> +				struct lsm_ctx __user *lx, size_t *size,
> +				u32 __user flags)
> +{
> +	int error = -ENOENT;
> +	struct aa_task_ctx *ctx = task_ctx(current);
> +	struct aa_label *label = NULL;
> +	size_t total_len;
> +	char *value;
> +
> +	if (attr == LSM_ATTR_CURRENT)
> +		label = aa_get_newest_label(cred_label(current_cred()));
> +	else if (attr == LSM_ATTR_PREV && ctx->previous)
> +		label = aa_get_newest_label(ctx->previous);
> +	else if (attr == LSM_ATTR_EXEC && ctx->onexec)
> +		label = aa_get_newest_label(ctx->onexec);
> +	else
> +		error = -EOPNOTSUPP;

Is "-EOPNOTSUPP" correct for LSM_ATTR_PREV when !ctx->previous? That
seems like it should be -EINVAL? I think this would be better served as
a switch statement.

> +
> +	if (label) {
> +		error = aa_getprocattr(label, &value, false);
> +		if (error > 0) {
> +			total_len = ALIGN(error + sizeof(*ctx), 8);
> +			if (total_len > *size)
> +				error = -E2BIG;
> +			else
> +				lsm_fill_user_ctx(lx, value, error,
> +						  LSM_ID_APPARMOR, 0);
> +		}
> +	}
> +
> +	aa_put_label(label);
> +
> +	*size = total_len;
> +	if (error > 0)
> +		return 1;
> +	return error;
> +}
> +
>  static int apparmor_getprocattr(struct task_struct *task, const char *name,
>  				char **value)
>  {
> @@ -649,7 +688,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);
> @@ -657,8 +696,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;
> @@ -689,7 +727,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);
> @@ -704,7 +742,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)
> @@ -724,13 +762,57 @@ static int apparmor_setprocattr(const char *name, void *value,
>  
>  fail:
>  	aad(&sa)->label = begin_current_label_crit_section();
> -	aad(&sa)->info = name;
> +	if (attr == LSM_ATTR_CURRENT)
> +		aad(&sa)->info = "current";
> +	else if (attr == LSM_ATTR_EXEC)
> +		aad(&sa)->info = "exec";
> +	else
> +		aad(&sa)->info = "invalid";
>  	aad(&sa)->error = error = -EINVAL;
>  	aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL);
>  	end_current_label_crit_section(aad(&sa)->label);
>  	goto out;
>  }
>  
> +static int apparmor_setselfattr(unsigned int __user attr,
> +				struct lsm_ctx __user *ctx, size_t __user size,
> +				u32 __user flags)
> +{
> +	struct lsm_ctx *lctx;
> +	void *context;
> +	int rc;
> +
> +	if (attr != LSM_ATTR_CURRENT && attr != LSM_ATTR_EXEC)
> +		return -EOPNOTSUPP;
> +
> +	context = kmalloc(size, GFP_KERNEL);
> +	if (context == NULL)
> +		return -ENOMEM;
> +
> +	lctx = (struct lsm_ctx *)context;
> +	if (copy_from_user(context, ctx, size))
> +		rc = -EFAULT;
> +	else if (lctx->ctx_len > size)
> +		rc = -EINVAL;
> +	else
> +		rc = do_setattr(attr, lctx + 1, lctx->ctx_len);
> +
> +	kfree(context);
> +	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)
> @@ -1253,6 +1335,8 @@ static struct security_hook_list apparmor_hooks[] __lsm_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),
>  
> diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
> index 197d41f9c32b..196f319aa3b2 100644
> --- a/security/apparmor/procattr.c
> +++ b/security/apparmor/procattr.c
> @@ -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,10 +58,14 @@ 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);
> +
> +	if (newline)
> +		return len;
>  	return len + 1;
>  }

This is returning the count including trailing %NUL, yes? Why is this
not always just "return len"? i.e.:

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

	aa_put_ns(current_ns);
	return len;


>  
> -- 
> 2.39.2
> 

-- 
Kees Cook

  reply	other threads:[~2023-04-21 19:54 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20230421174259.2458-1-casey.ref@schaufler-ca.com>
2023-04-21 17:42 ` [PATCH v9 00/11] LSM: Three basic syscalls Casey Schaufler
2023-04-21 17:42   ` [PATCH v9 01/11] LSM: Identify modules by more than name Casey Schaufler
2023-04-21 19:14     ` Kees Cook
2023-04-21 17:42   ` [PATCH v9 02/11] LSM: Maintain a table of LSM attribute data Casey Schaufler
2023-04-21 19:20     ` Kees Cook
2023-04-27 15:31       ` Casey Schaufler
2023-04-23  8:04     ` kernel test robot
2023-04-21 17:42   ` [PATCH v9 03/11] proc: Use lsmids instead of lsm names for attrs Casey Schaufler
2023-04-21 19:21     ` Kees Cook
2023-04-21 17:42   ` [PATCH v9 04/11] LSM: syscalls for current process attributes Casey Schaufler
2023-04-21 19:36     ` Kees Cook
2023-04-26  1:12       ` Casey Schaufler
2023-04-22 13:12     ` kernel test robot
2023-04-22 16:59     ` kernel test robot
2023-04-21 17:42   ` [PATCH v9 05/11] LSM: Create lsm_list_modules system call Casey Schaufler
2023-04-21 19:38     ` Kees Cook
2023-04-21 17:42   ` [PATCH v9 06/11] LSM: wireup Linux Security Module syscalls Casey Schaufler
2023-04-21 19:38     ` Kees Cook
2023-04-21 17:42   ` [PATCH v9 07/11] LSM: Helpers for attribute names and filling an lsm_ctx Casey Schaufler
2023-04-21 19:46     ` Kees Cook
2023-04-21 17:42   ` [PATCH v9 08/11] Smack: implement setselfattr and getselfattr hooks Casey Schaufler
2023-04-21 19:49     ` Kees Cook
2023-04-21 17:42   ` [PATCH v9 09/11] AppArmor: Add selfattr hooks Casey Schaufler
2023-04-21 19:54     ` Kees Cook [this message]
2023-04-22  1:23     ` kernel test robot
2023-04-22 14:55     ` kernel test robot
2023-04-21 17:42   ` [PATCH v9 10/11] SELinux: " Casey Schaufler
2023-04-21 19:57     ` Kees Cook
2023-04-21 17:42   ` [PATCH v9 11/11] LSM: selftests for Linux Security Module syscalls Casey Schaufler
2023-04-21 20:01     ` Kees Cook
2023-04-27 16:00       ` Casey Schaufler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6442e9f1.050a0220.3353e.77fb@mx.google.com \
    --to=keescook@chromium.org \
    --cc=casey@schaufler-ca.com \
    --cc=jmorris@namei.org \
    --cc=john.johansen@canonical.com \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=mic@digikod.net \
    --cc=paul@paul-moore.com \
    --cc=penguin-kernel@i-love.sakura.ne.jp \
    --cc=stephen.smalley.work@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.