Commit b822cb18 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull apparmor fixes from James Morris:
 "Bugfixes for the Apparmor code for regressions introduced in the 3.12
  pull request"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  apparmor: fix suspicious RCU usage warning in policy.c/policy.h
  apparmor: Use shash crypto API interface for profile hashes
parents cbb16bec 4cd4fc77
...@@ -15,14 +15,14 @@ ...@@ -15,14 +15,14 @@
* it should be. * it should be.
*/ */
#include <linux/crypto.h> #include <crypto/hash.h>
#include "include/apparmor.h" #include "include/apparmor.h"
#include "include/crypto.h" #include "include/crypto.h"
static unsigned int apparmor_hash_size; static unsigned int apparmor_hash_size;
static struct crypto_hash *apparmor_tfm; static struct crypto_shash *apparmor_tfm;
unsigned int aa_hash_size(void) unsigned int aa_hash_size(void)
{ {
...@@ -32,35 +32,33 @@ unsigned int aa_hash_size(void) ...@@ -32,35 +32,33 @@ unsigned int aa_hash_size(void)
int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
size_t len) size_t len)
{ {
struct scatterlist sg[2]; struct {
struct hash_desc desc = { struct shash_desc shash;
.tfm = apparmor_tfm, char ctx[crypto_shash_descsize(apparmor_tfm)];
.flags = 0 } desc;
};
int error = -ENOMEM; int error = -ENOMEM;
u32 le32_version = cpu_to_le32(version); u32 le32_version = cpu_to_le32(version);
if (!apparmor_tfm) if (!apparmor_tfm)
return 0; return 0;
sg_init_table(sg, 2);
sg_set_buf(&sg[0], &le32_version, 4);
sg_set_buf(&sg[1], (u8 *) start, len);
profile->hash = kzalloc(apparmor_hash_size, GFP_KERNEL); profile->hash = kzalloc(apparmor_hash_size, GFP_KERNEL);
if (!profile->hash) if (!profile->hash)
goto fail; goto fail;
error = crypto_hash_init(&desc); desc.shash.tfm = apparmor_tfm;
desc.shash.flags = 0;
error = crypto_shash_init(&desc.shash);
if (error) if (error)
goto fail; goto fail;
error = crypto_hash_update(&desc, &sg[0], 4); error = crypto_shash_update(&desc.shash, (u8 *) &le32_version, 4);
if (error) if (error)
goto fail; goto fail;
error = crypto_hash_update(&desc, &sg[1], len); error = crypto_shash_update(&desc.shash, (u8 *) start, len);
if (error) if (error)
goto fail; goto fail;
error = crypto_hash_final(&desc, profile->hash); error = crypto_shash_final(&desc.shash, profile->hash);
if (error) if (error)
goto fail; goto fail;
...@@ -75,19 +73,19 @@ int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, ...@@ -75,19 +73,19 @@ int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
static int __init init_profile_hash(void) static int __init init_profile_hash(void)
{ {
struct crypto_hash *tfm; struct crypto_shash *tfm;
if (!apparmor_initialized) if (!apparmor_initialized)
return 0; return 0;
tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); tfm = crypto_alloc_shash("sha1", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) { if (IS_ERR(tfm)) {
int error = PTR_ERR(tfm); int error = PTR_ERR(tfm);
AA_ERROR("failed to setup profile sha1 hashing: %d\n", error); AA_ERROR("failed to setup profile sha1 hashing: %d\n", error);
return error; return error;
} }
apparmor_tfm = tfm; apparmor_tfm = tfm;
apparmor_hash_size = crypto_hash_digestsize(apparmor_tfm); apparmor_hash_size = crypto_shash_digestsize(apparmor_tfm);
aa_info_message("AppArmor sha1 policy hashing enabled"); aa_info_message("AppArmor sha1 policy hashing enabled");
......
...@@ -360,7 +360,9 @@ static inline void aa_put_replacedby(struct aa_replacedby *p) ...@@ -360,7 +360,9 @@ static inline void aa_put_replacedby(struct aa_replacedby *p)
static inline void __aa_update_replacedby(struct aa_profile *orig, static inline void __aa_update_replacedby(struct aa_profile *orig,
struct aa_profile *new) struct aa_profile *new)
{ {
struct aa_profile *tmp = rcu_dereference(orig->replacedby->profile); struct aa_profile *tmp;
tmp = rcu_dereference_protected(orig->replacedby->profile,
mutex_is_locked(&orig->ns->lock));
rcu_assign_pointer(orig->replacedby->profile, aa_get_profile(new)); rcu_assign_pointer(orig->replacedby->profile, aa_get_profile(new));
orig->flags |= PFLAG_INVALID; orig->flags |= PFLAG_INVALID;
aa_put_profile(tmp); aa_put_profile(tmp);
......
...@@ -563,7 +563,8 @@ void __init aa_free_root_ns(void) ...@@ -563,7 +563,8 @@ void __init aa_free_root_ns(void)
static void free_replacedby(struct aa_replacedby *r) static void free_replacedby(struct aa_replacedby *r)
{ {
if (r) { if (r) {
aa_put_profile(rcu_dereference(r->profile)); /* r->profile will not be updated any more as r is dead */
aa_put_profile(rcu_dereference_protected(r->profile, true));
kzfree(r); kzfree(r);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment