[PATCH] apparmor: move task specific domain change info out of cred

Stephen Smalley sds at tycho.nsa.gov
Mon Mar 13 17:16:18 UTC 2017


On Mon, 2017-03-13 at 10:05 -0700, John Johansen wrote:
> On 03/13/2017 09:47 AM, Serge E. Hallyn wrote:
> > Quoting John Johansen (john.johansen at canonical.com):
> > > Now that security_task_alloc() hook and "struct task_struct"-
> > > >security
> > > field are revived, move task specific domain change information
> > > for
> > > change_onexec (equiv of setexeccon) and change_hat out of the
> > > cred
> > > into a context off of the task_struct.
> > > 
> > > This cleans up apparmor's use of the cred structure so that it
> > > only
> > > carries the reference to current mediation.
> > > 
> > > Signed-off-by: John Johansen <john.johansen at canonical.com>
> > 
> > Thanks, John, that helps in compelling a review of the previous
> > patch :)
> > 
> > So the task_struct->security pointer is only to store requested
> > transition profiles right?
> > 
> 
> correct, well and support information for the transition like the
> random
> magic token for change_hat.

Is it really a net win for AA?  You save some space in the per-cred
structure (but that was already shared by most tasks, particularly any
that are not using change_onexec/change_hat), but won't you end up
using more space overall since you will now be allocating space for
(onexec, previous, token) for every task, even ones that don't use
those operations?

> 
> 
> > > ---
> > >  security/apparmor/context.c         | 129 +++++++++++++++++-----
> > > --------------
> > >  security/apparmor/domain.c          |  28 ++++----
> > >  security/apparmor/include/context.h |  63 ++++++++----------
> > >  security/apparmor/lsm.c             |  65 ++++++++++--------
> > >  security/apparmor/policy.c          |   5 +-
> > >  5 files changed, 143 insertions(+), 147 deletions(-)
> > > 
> > > diff --git a/security/apparmor/context.c
> > > b/security/apparmor/context.c
> > > index 1fc16b8..8afb304 100644
> > > --- a/security/apparmor/context.c
> > > +++ b/security/apparmor/context.c
> > > @@ -13,11 +13,9 @@
> > >   * License.
> > >   *
> > >   *
> > > - * AppArmor sets confinement on every task, via the the
> > > aa_task_ctx and
> > > - * the aa_task_ctx.profile, both of which are required and are
> > > not allowed
> > > - * to be NULL.  The aa_task_ctx is not reference counted and is
> > > unique
> > > - * to each cred (which is reference count).  The profile pointed
> > > to by
> > > - * the task_ctx is reference counted.
> > > + * AppArmor sets confinement on every task, via the
> > > cred_profile() which
> > > + * is required and is not allowed to be NULL.  The cred_profile
> > > is
> > > + * reference counted.
> > >   *
> > >   * TODO
> > >   * If a task uses change_hat it currently does not return to the
> > > old
> > > @@ -29,25 +27,42 @@
> > >  #include "include/context.h"
> > >  #include "include/policy.h"
> > >  
> > > +
> > > +/**
> > > + * aa_get_task_profile - Get another task's profile
> > > + * @task: task to query  (NOT NULL)
> > > + *
> > > + * Returns: counted reference to @task's profile
> > > + */
> > > +struct aa_profile *aa_get_task_profile(struct task_struct *task)
> > > +{
> > > +	struct aa_profile *p;
> > > +
> > > +	rcu_read_lock();
> > > +	p = aa_get_profile(__aa_task_profile(task));
> > > +	rcu_read_unlock();
> > > +
> > > +	return p;
> > > +}
> > > +
> > >  /**
> > > - * aa_alloc_task_context - allocate a new task_ctx
> > > + * aa_alloc_task_ctx - allocate a new task_ctx
> > >   * @flags: gfp flags for allocation
> > >   *
> > >   * Returns: allocated buffer or NULL on failure
> > >   */
> > > -struct aa_task_ctx *aa_alloc_task_context(gfp_t flags)
> > > +struct aa_task_ctx *aa_alloc_task_ctx(gfp_t flags)
> > >  {
> > >  	return kzalloc(sizeof(struct aa_task_ctx), flags);
> > >  }
> > >  
> > >  /**
> > > - * aa_free_task_context - free a task_ctx
> > > + * aa_free_task_ctx - free a task_ctx
> > >   * @ctx: task_ctx to free (MAYBE NULL)
> > >   */
> > > -void aa_free_task_context(struct aa_task_ctx *ctx)
> > > +void aa_free_task_ctx(struct aa_task_ctx *ctx)
> > >  {
> > >  	if (ctx) {
> > > -		aa_put_profile(ctx->profile);
> > >  		aa_put_profile(ctx->previous);
> > >  		aa_put_profile(ctx->onexec);
> > >  
> > > @@ -56,36 +71,18 @@ void aa_free_task_context(struct aa_task_ctx
> > > *ctx)
> > >  }
> > >  
> > >  /**
> > > - * aa_dup_task_context - duplicate a task context, incrementing
> > > reference counts
> > > + * aa_dup_task_ctx - duplicate a task context, incrementing
> > > reference counts
> > >   * @new: a blank task context      (NOT NULL)
> > >   * @old: the task context to copy  (NOT NULL)
> > >   */
> > > -void aa_dup_task_context(struct aa_task_ctx *new, const struct
> > > aa_task_ctx *old)
> > > +void aa_dup_task_ctx(struct aa_task_ctx *new, const struct
> > > aa_task_ctx *old)
> > >  {
> > >  	*new = *old;
> > > -	aa_get_profile(new->profile);
> > >  	aa_get_profile(new->previous);
> > >  	aa_get_profile(new->onexec);
> > >  }
> > >  
> > >  /**
> > > - * aa_get_task_profile - Get another task's profile
> > > - * @task: task to query  (NOT NULL)
> > > - *
> > > - * Returns: counted reference to @task's profile
> > > - */
> > > -struct aa_profile *aa_get_task_profile(struct task_struct *task)
> > > -{
> > > -	struct aa_profile *p;
> > > -
> > > -	rcu_read_lock();
> > > -	p = aa_get_profile(__aa_task_profile(task));
> > > -	rcu_read_unlock();
> > > -
> > > -	return p;
> > > -}
> > > -
> > > -/**
> > >   * aa_replace_current_profile - replace the current tasks
> > > profiles
> > >   * @profile: new profile  (NOT NULL)
> > >   *
> > > @@ -93,36 +90,37 @@ struct aa_profile *aa_get_task_profile(struct
> > > task_struct *task)
> > >   */
> > >  int aa_replace_current_profile(struct aa_profile *profile)
> > >  {
> > > -	struct aa_task_ctx *ctx = current_ctx();
> > > +	struct aa_profile *old = __aa_current_profile();
> > >  	struct cred *new;
> > > +
> > >  	AA_BUG(!profile);
> > >  
> > > -	if (ctx->profile == profile)
> > > +	if (old == profile)
> > >  		return 0;
> > >  
> > >  	if (current_cred() != current_real_cred())
> > >  		return -EBUSY;
> > >  
> > >  	new  = prepare_creds();
> > > +	old = cred_profile(new);
> > >  	if (!new)
> > >  		return -ENOMEM;
> > >  
> > > -	ctx = cred_ctx(new);
> > > -	if (unconfined(profile) || (ctx->profile->ns != profile-
> > > >ns))
> > > +	if (unconfined(profile) || (old->ns != profile->ns))
> > >  		/* if switching to unconfined or a different
> > > profile namespace
> > >  		 * clear out context state
> > >  		 */
> > > -		aa_clear_task_ctx_trans(ctx);
> > > +		aa_clear_task_ctx(current_task_ctx());
> > >  
> > >  	/*
> > > -	 * be careful switching ctx->profile, when racing
> > > replacement it
> > > -	 * is possible that ctx->profile->proxy->profile is the
> > > reference
> > > +	 * be careful switching cred profile, when racing
> > > replacement it
> > > +	 * is possible that the cred profile's->proxy->profile
> > > is the reference
> > >  	 * keeping @profile valid, so make sure to get its
> > > reference before
> > > -	 * dropping the reference on ctx->profile
> > > +	 * dropping the reference on the cred's profile
> > >  	 */
> > >  	aa_get_profile(profile);
> > > -	aa_put_profile(ctx->profile);
> > > -	ctx->profile = profile;
> > > +	aa_put_profile(old);
> > > +	cred_profile(new) = profile;
> > >  
> > >  	commit_creds(new);
> > >  	return 0;
> > > @@ -137,16 +135,12 @@ int aa_replace_current_profile(struct
> > > aa_profile *profile)
> > >  int aa_set_current_onexec(struct aa_profile *profile)
> > >  {
> > >  	struct aa_task_ctx *ctx;
> > > -	struct cred *new = prepare_creds();
> > > -	if (!new)
> > > -		return -ENOMEM;
> > >  
> > > -	ctx = cred_ctx(new);
> > > +	ctx = current_task_ctx();
> > >  	aa_get_profile(profile);
> > >  	aa_put_profile(ctx->onexec);
> > >  	ctx->onexec = profile;
> > >  
> > > -	commit_creds(new);
> > >  	return 0;
> > >  }
> > >  
> > > @@ -162,25 +156,28 @@ int aa_set_current_onexec(struct aa_profile
> > > *profile)
> > >   */
> > >  int aa_set_current_hat(struct aa_profile *profile, u64 token)
> > >  {
> > > -	struct aa_task_ctx *ctx;
> > > -	struct cred *new = prepare_creds();
> > > +	struct aa_task_ctx *ctx = current_task_ctx();
> > > +	struct cred *new;
> > > +
> > > +	AA_BUG(!profile);
> > > +
> > > +	new = prepare_creds();
> > >  	if (!new)
> > >  		return -ENOMEM;
> > > -	AA_BUG(!profile);
> > >  
> > > -	ctx = cred_ctx(new);
> > >  	if (!ctx->previous) {
> > >  		/* transfer refcount */
> > > -		ctx->previous = ctx->profile;
> > > +		ctx->previous = cred_profile(new);
> > >  		ctx->token = token;
> > >  	} else if (ctx->token == token) {
> > > -		aa_put_profile(ctx->profile);
> > > +		aa_put_profile(cred_profile(new));
> > >  	} else {
> > >  		/* previous_profile && ctx->token != token */
> > >  		abort_creds(new);
> > >  		return -EACCES;
> > >  	}
> > > -	ctx->profile = aa_get_newest_profile(profile);
> > > +
> > > +	cred_profile(new) = aa_get_newest_profile(profile);
> > >  	/* clear exec on switching context */
> > >  	aa_put_profile(ctx->onexec);
> > >  	ctx->onexec = NULL;
> > > @@ -200,28 +197,26 @@ int aa_set_current_hat(struct aa_profile
> > > *profile, u64 token)
> > >   */
> > >  int aa_restore_previous_profile(u64 token)
> > >  {
> > > -	struct aa_task_ctx *ctx;
> > > -	struct cred *new = prepare_creds();
> > > -	if (!new)
> > > -		return -ENOMEM;
> > > +	struct aa_task_ctx *ctx = current_task_ctx();
> > > +	struct cred *new;
> > >  
> > > -	ctx = cred_ctx(new);
> > > -	if (ctx->token != token) {
> > > -		abort_creds(new);
> > > +	if (ctx->token != token)
> > >  		return -EACCES;
> > > -	}
> > >  	/* ignore restores when there is no saved profile */
> > > -	if (!ctx->previous) {
> > > -		abort_creds(new);
> > > +	if (!ctx->previous)
> > >  		return 0;
> > > -	}
> > >  
> > > -	aa_put_profile(ctx->profile);
> > > -	ctx->profile = aa_get_newest_profile(ctx->previous);
> > > -	AA_BUG(!ctx->profile);
> > > +	new = prepare_creds();
> > > +	if (!new)
> > > +		return -ENOMEM;
> > > +
> > > +	aa_put_profile(cred_profile(new));
> > > +	cred_profile(new) = aa_get_newest_profile(ctx-
> > > >previous);
> > > +	AA_BUG(!cred_profile(new));
> > >  	/* clear exec && prev information when restoring to
> > > previous context */
> > > -	aa_clear_task_ctx_trans(ctx);
> > > +	aa_clear_task_ctx(ctx);
> > >  
> > >  	commit_creds(new);
> > > +
> > >  	return 0;
> > >  }
> > > diff --git a/security/apparmor/domain.c
> > > b/security/apparmor/domain.c
> > > index ef4beef..1994c02 100644
> > > --- a/security/apparmor/domain.c
> > > +++ b/security/apparmor/domain.c
> > > @@ -353,10 +353,10 @@ int apparmor_bprm_set_creds(struct
> > > linux_binprm *bprm)
> > >  	if (bprm->cred_prepared)
> > >  		return 0;
> > >  
> > > -	ctx = cred_ctx(bprm->cred);
> > > +	ctx = current_task_ctx();
> > >  	AA_BUG(!ctx);
> > > -
> > > -	profile = aa_get_newest_profile(ctx->profile);
> > > +	AA_BUG(!cred_profile(bprm->cred));
> > > +	profile = aa_get_newest_profile(cred_profile(bprm-
> > > >cred));
> > >  	/*
> > >  	 * get the namespace from the replacement profile as
> > > replacement
> > >  	 * can change the namespace
> > > @@ -499,14 +499,11 @@ int apparmor_bprm_set_creds(struct
> > > linux_binprm *bprm)
> > >  	bprm->per_clear |= PER_CLEAR_ON_SETID;
> > >  
> > >  x_clear:
> > > -	aa_put_profile(ctx->profile);
> > > -	/* transfer new profile reference will be released when
> > > ctx is freed */
> > > -	ctx->profile = new_profile;
> > > +	aa_put_profile(profile);
> > > +	/* transfer new profile reference will be released when
> > > cred is freed */
> > > +	cred_profile(bprm->cred) = new_profile;
> > >  	new_profile = NULL;
> > >  
> > > -	/* clear out all temporary/transitional state from the
> > > context */
> > > -	aa_clear_task_ctx_trans(ctx);
> > > -
> > >  audit:
> > >  	error = aa_audit_file(profile, &perms, OP_EXEC,
> > > MAY_EXEC, name,
> > >  			      new_profile ? new_profile-
> > > >base.hname : NULL,
> > > @@ -544,17 +541,16 @@ int apparmor_bprm_secureexec(struct
> > > linux_binprm *bprm)
> > >  void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
> > >  {
> > >  	struct aa_profile *profile = __aa_current_profile();
> > > -	struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred);
> > > +	struct aa_profile *new = cred_profile(bprm->cred);
> > >  
> > >  	/* bail out if unconfined or not changing profile */
> > > -	if ((new_ctx->profile == profile) ||
> > > -	    (unconfined(new_ctx->profile)))
> > > +	if (new == profile || unconfined(new))
> > >  		return;
> > >  
> > >  	current->pdeath_signal = 0;
> > >  
> > >  	/* reset soft limits and set hard limits for the new
> > > profile */
> > > -	__aa_transition_rlimits(profile, new_ctx->profile);
> > > +	__aa_transition_rlimits(profile, new);
> > >  }
> > >  
> > >  /**
> > > @@ -564,6 +560,10 @@ void apparmor_bprm_committing_creds(struct
> > > linux_binprm *bprm)
> > >  void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
> > >  {
> > >  	/* TODO: cleanup signals - ipc mediation */
> > > +
> > > +	/* clear out all temporary/transitional state from the
> > > context */
> > > +	aa_clear_task_ctx(current_task_ctx());
> > > +
> > >  	return;
> > >  }
> > >  
> > > @@ -621,7 +621,7 @@ int aa_change_hat(const char *hats[], int
> > > count, u64 token, bool permtest)
> > >  
> > >  	/* released below */
> > >  	cred = get_current_cred();
> > > -	ctx = cred_ctx(cred);
> > > +	ctx = current_task_ctx();
> > >  	profile = aa_get_newest_profile(aa_cred_profile(cred));
> > >  	previous_profile = aa_get_newest_profile(ctx->previous);
> > >  
> > > diff --git a/security/apparmor/include/context.h
> > > b/security/apparmor/include/context.h
> > > index 5b18fed..9943969 100644
> > > --- a/security/apparmor/include/context.h
> > > +++ b/security/apparmor/include/context.h
> > > @@ -22,8 +22,9 @@
> > >  #include "policy.h"
> > >  #include "policy_ns.h"
> > >  
> > > -#define cred_ctx(X) ((X)->security)
> > > -#define current_ctx() cred_ctx(current_cred())
> > > +#define task_ctx(X) ((X)->security)
> > > +#define current_task_ctx() (task_ctx(current))
> > > +#define cred_profile(X) ((X)->security)
> > >  
> > >  /* struct aa_file_ctx - the AppArmor context the file was opened
> > > in
> > >   * @perms: the permission the file was opened with
> > > @@ -58,28 +59,23 @@ static inline void
> > > aa_free_file_context(struct aa_file_ctx *ctx)
> > >  }
> > >  
> > >  /**
> > > - * struct aa_task_ctx - primary label for confined tasks
> > > - * @profile: the current profile   (NOT NULL)
> > > - * @exec: profile to transition to on next exec  (MAYBE NULL)
> > > - * @previous: profile the task may return to     (MAYBE NULL)
> > > + * struct aa_task_ctx - information for current task label
> > > change
> > > + * @onexec: profile to transition to on next exec  (MAY BE NULL)
> > > + * @previous: profile the task may return to     (MAY BE NULL)
> > >   * @token: magic value the task must know for returning to
> > > @previous_profile
> > >   *
> > > - * Contains the task's current profile (which could change due
> > > to
> > > - * change_hat).  Plus the hat_magic needed during change_hat.
> > > - *
> > >   * TODO: make so a task can be confined by a stack of contexts
> > >   */
> > >  struct aa_task_ctx {
> > > -	struct aa_profile *profile;
> > >  	struct aa_profile *onexec;
> > >  	struct aa_profile *previous;
> > >  	u64 token;
> > >  };
> > >  
> > > -struct aa_task_ctx *aa_alloc_task_context(gfp_t flags);
> > > -void aa_free_task_context(struct aa_task_ctx *ctx);
> > > -void aa_dup_task_context(struct aa_task_ctx *new,
> > > -			 const struct aa_task_ctx *old);
> > > +struct aa_task_ctx *aa_alloc_task_ctx(gfp_t flags);
> > > +void aa_free_task_ctx(struct aa_task_ctx *ctx);
> > > +void aa_dup_task_ctx(struct aa_task_ctx *new, const struct
> > > aa_task_ctx *old);
> > > +
> > >  int aa_replace_current_profile(struct aa_profile *profile);
> > >  int aa_set_current_onexec(struct aa_profile *profile);
> > >  int aa_set_current_hat(struct aa_profile *profile, u64 token);
> > > @@ -97,10 +93,11 @@ struct aa_profile *aa_get_task_profile(struct
> > > task_struct *task);
> > >   */
> > >  static inline struct aa_profile *aa_cred_profile(const struct
> > > cred *cred)
> > >  {
> > > -	struct aa_task_ctx *ctx = cred_ctx(cred);
> > > +	struct aa_profile *profile = cred_profile(cred);
> > >  
> > > -	AA_BUG(!ctx || !ctx->profile);
> > > -	return ctx->profile;
> > > +	AA_BUG(!profile);
> > > +
> > > +	return profile;
> > >  }
> > >  
> > >  /**
> > > @@ -117,17 +114,6 @@ static inline struct aa_profile
> > > *__aa_task_profile(struct task_struct *task)
> > >  }
> > >  
> > >  /**
> > > - * __aa_task_is_confined - determine if @task has any
> > > confinement
> > > - * @task: task to check confinement of  (NOT NULL)
> > > - *
> > > - * If @task != current needs to be called in RCU safe critical
> > > section
> > > - */
> > > -static inline bool __aa_task_is_confined(struct task_struct
> > > *task)
> > > -{
> > > -	return !unconfined(__aa_task_profile(task));
> > > -}
> > > -
> > > -/**
> > >   * __aa_current_profile - find the current tasks confining
> > > profile
> > >   *
> > >   * Returns: up to date confining profile or the ns unconfined
> > > profile (NOT NULL)
> > > @@ -150,19 +136,17 @@ static inline struct aa_profile
> > > *__aa_current_profile(void)
> > >   */
> > >  static inline struct aa_profile *aa_current_profile(void)
> > >  {
> > > -	const struct aa_task_ctx *ctx = current_ctx();
> > > -	struct aa_profile *profile;
> > > +	struct aa_profile *profile = __aa_current_profile();
> > >  
> > > -	AA_BUG(!ctx || !ctx->profile);
> > > +	AA_BUG(!profile);
> > >  
> > > -	if (profile_is_stale(ctx->profile)) {
> > > -		profile = aa_get_newest_profile(ctx->profile);
> > > +	if (profile_is_stale(profile)) {
> > > +		profile = aa_get_newest_profile(profile);
> > >  		aa_replace_current_profile(profile);
> > >  		aa_put_profile(profile);
> > > -		ctx = current_ctx();
> > >  	}
> > >  
> > > -	return ctx->profile;
> > > +	return profile;
> > >  }
> > >  
> > >  static inline struct aa_ns *aa_get_current_ns(void)
> > > @@ -170,12 +154,17 @@ static inline struct aa_ns
> > > *aa_get_current_ns(void)
> > >  	return aa_get_ns(__aa_current_profile()->ns);
> > >  }
> > >  
> > > +
> > > +
> > > +
> > >  /**
> > > - * aa_clear_task_ctx_trans - clear transition tracking info from
> > > the ctx
> > > + * aa_clear_task_ctx - clear transition tracking info from the
> > > ctx
> > >   * @ctx: task context to clear (NOT NULL)
> > >   */
> > > -static inline void aa_clear_task_ctx_trans(struct aa_task_ctx
> > > *ctx)
> > > +static inline void aa_clear_task_ctx(struct aa_task_ctx *ctx)
> > >  {
> > > +	AA_BUG(!ctx);
> > > +
> > >  	aa_put_profile(ctx->previous);
> > >  	aa_put_profile(ctx->onexec);
> > >  	ctx->previous = NULL;
> > > diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> > > index 1f2000d..ed9bf71 100644
> > > --- a/security/apparmor/lsm.c
> > > +++ b/security/apparmor/lsm.c
> > > @@ -49,12 +49,12 @@ DEFINE_PER_CPU(struct aa_buffers,
> > > aa_buffers);
> > >   */
> > >  
> > >  /*
> > > - * free the associated aa_task_ctx and put its profiles
> > > + * put the associated profiles
> > >   */
> > >  static void apparmor_cred_free(struct cred *cred)
> > >  {
> > > -	aa_free_task_context(cred_ctx(cred));
> > > -	cred_ctx(cred) = NULL;
> > > +	aa_put_profile(cred_profile(cred));
> > > +	cred_profile(cred) = NULL;
> > >  }
> > >  
> > >  /*
> > > @@ -62,30 +62,19 @@ static void apparmor_cred_free(struct cred
> > > *cred)
> > >   */
> > >  static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t
> > > gfp)
> > >  {
> > > -	/* freed by apparmor_cred_free */
> > > -	struct aa_task_ctx *ctx = aa_alloc_task_context(gfp);
> > > -
> > > -	if (!ctx)
> > > -		return -ENOMEM;
> > > -
> > > -	cred_ctx(cred) = ctx;
> > > +	cred_profile(cred) = NULL;
> > >  	return 0;
> > >  }
> > >  
> > >  /*
> > > - * prepare new aa_task_ctx for modification by prepare_cred
> > > block
> > > + * prepare new cred profile for modification by prepare_cred
> > > block
> > >   */
> > >  static int apparmor_cred_prepare(struct cred *new, const struct
> > > cred *old,
> > >  				 gfp_t gfp)
> > >  {
> > > -	/* freed by apparmor_cred_free */
> > > -	struct aa_task_ctx *ctx = aa_alloc_task_context(gfp);
> > > -
> > > -	if (!ctx)
> > > -		return -ENOMEM;
> > > -
> > > -	aa_dup_task_context(ctx, cred_ctx(old));
> > > -	cred_ctx(new) = ctx;
> > > +	struct aa_profile *tmp = cred_profile(new);
> > > +	cred_profile(new) =
> > > aa_get_newest_profile(cred_profile(old));
> > > +	aa_put_profile(tmp);
> > >  	return 0;
> > >  }
> > >  
> > > @@ -94,10 +83,30 @@ static int apparmor_cred_prepare(struct cred
> > > *new, const struct cred *old,
> > >   */
> > >  static void apparmor_cred_transfer(struct cred *new, const
> > > struct cred *old)
> > >  {
> > > -	const struct aa_task_ctx *old_ctx = cred_ctx(old);
> > > -	struct aa_task_ctx *new_ctx = cred_ctx(new);
> > > +	struct aa_profile *tmp = cred_profile(new);
> > > +	cred_profile(new) =
> > > aa_get_newest_profile(cred_profile(old));
> > > +	aa_put_profile(tmp);
> > > +}
> > >  
> > > -	aa_dup_task_context(new_ctx, old_ctx);
> > > +static void apparmor_task_free(struct task_struct *task)
> > > +{
> > > +
> > > +	aa_free_task_ctx(task_ctx(task));
> > > +	task_ctx(task) = NULL;
> > > +}
> > > +
> > > +static int apparmor_task_alloc(struct task_struct *task,
> > > +			       unsigned long clone_flags)
> > > +{
> > > +	struct aa_task_ctx *new = aa_alloc_task_ctx(GFP_KERNEL);
> > > +
> > > +	if (!new)
> > > +		return -ENOMEM;
> > > +
> > > +	aa_dup_task_ctx(new, current_task_ctx());
> > > +	task_ctx(task) = new;
> > > +
> > > +	return 0;
> > >  }
> > >  
> > >  static int apparmor_ptrace_access_check(struct task_struct
> > > *child,
> > > @@ -484,11 +493,11 @@ static int apparmor_getprocattr(struct
> > > task_struct *task, char *name,
> > >  	int error = -ENOENT;
> > >  	/* released below */
> > >  	const struct cred *cred = get_task_cred(task);
> > > -	struct aa_task_ctx *ctx = cred_ctx(cred);
> > > +	struct aa_task_ctx *ctx = current_task_ctx();
> > >  	struct aa_profile *profile = NULL;
> > >  
> > >  	if (strcmp(name, "current") == 0)
> > > -		profile = aa_get_newest_profile(ctx->profile);
> > > +		profile =
> > > aa_get_newest_profile(cred_profile(cred));
> > >  	else if (strcmp(name, "prev") == 0  && ctx->previous)
> > >  		profile = aa_get_newest_profile(ctx->previous);
> > >  	else if (strcmp(name, "exec") == 0 && ctx->onexec)
> > > @@ -629,6 +638,8 @@ static struct security_hook_list
> > > apparmor_hooks[] = {
> > >  	LSM_HOOK_INIT(bprm_committed_creds,
> > > apparmor_bprm_committed_creds),
> > >  	LSM_HOOK_INIT(bprm_secureexec,
> > > apparmor_bprm_secureexec),
> > >  
> > > +	LSM_HOOK_INIT(task_free, apparmor_task_free),
> > > +	LSM_HOOK_INIT(task_alloc, apparmor_task_alloc),
> > >  	LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
> > >  };
> > >  
> > > @@ -871,12 +882,12 @@ static int __init set_init_ctx(void)
> > >  	struct cred *cred = (struct cred *)current->real_cred;
> > >  	struct aa_task_ctx *ctx;
> > >  
> > > -	ctx = aa_alloc_task_context(GFP_KERNEL);
> > > +	ctx = aa_alloc_task_ctx(GFP_KERNEL);
> > >  	if (!ctx)
> > >  		return -ENOMEM;
> > >  
> > > -	ctx->profile = aa_get_profile(root_ns->unconfined);
> > > -	cred_ctx(cred) = ctx;
> > > +	cred_profile(cred) = aa_get_profile(root_ns-
> > > >unconfined);
> > > +	task_ctx(current) = ctx;
> > >  
> > >  	return 0;
> > >  }
> > > diff --git a/security/apparmor/policy.c
> > > b/security/apparmor/policy.c
> > > index f44312a..b9c300b 100644
> > > --- a/security/apparmor/policy.c
> > > +++ b/security/apparmor/policy.c
> > > @@ -827,8 +827,9 @@ static int __lookup_replace(struct aa_ns *ns,
> > > const char *hname,
> > >   * @udata: serialized data stream  (NOT NULL)
> > >   *
> > >   * unpack and replace a profile on the profile list and uses of
> > > that profile
> > > - * by any aa_task_ctx.  If the profile does not exist on the
> > > profile list
> > > - * it is added.
> > > + * by any task creds via invalidating the old version of the
> > > profile, which
> > > + * tasks will notice to update their own cred.  If the profile
> > > does not exist
> > > + * on the profile list it is added.
> > >   *
> > >   * Returns: size of data consumed else error code on failure.
> > >   */
> > > -- 
> > > 2.9.3
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the Linux-security-module-archive mailing list