2013-09-23 02:30:11

by Miles Lane

[permalink] [raw]
Subject: Linus GIT - kernel BUG at include/linux/scatterlist.h:115! CPU: 1 PID: 1203 Comm: apparmor_parser Not tainted 3.12.0-rc1+

[ 27.190017] kernel BUG at include/linux/scatterlist.h:115!
[ 27.190017] invalid opcode: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
[ 27.190017] Modules linked in: mxm_wmi iwldvm mac80211 iwlwifi
cfg80211 snd_hda_intel(+) snd_hda_codec snd_hwdep snd_pcm_oss
snd_mixer_oss hwmon snd_pcm ttm snd_seq_dummy snd_page_alloc
snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_timer
i915(+) snd i2c_algo_bit drm_kms_helper wmi ac drm soundcore evdev
mac_hid i2c_core battery acpi_cpufreq ehci_pci(+) ehci_hcd asus_laptop
rfkill intel_agp intel_gtt agpgart processor sr_mod cdrom atl1c
uhci_hcd thermal
[ 27.190017] CPU: 1 PID: 1203 Comm: apparmor_parser Not tainted 3.12.0-rc1+ #8
[ 27.190017] Hardware name: ASUSTeK Computer Inc. UL50VT
/UL50VT , BIOS 217 03/01/2010
[ 27.190017] task: ffff8800bd99ea80 ti: ffff8800baf5a000 task.ti:
ffff8800baf5a000
[ 27.190017] RIP: 0010:[<ffffffff811f9e71>] [<ffffffff811f9e71>]
sg_set_buf+0x20/0x7e
[ 27.190017] RSP: 0018:ffff8800baf5bcf8 EFLAGS: 00010246
[ 27.190017] RAX: 0000000000000000 RBX: ffff8800baf5bd70 RCX: 0000000000000024
[ 27.190017] RDX: 0000000000000410 RSI: ffffc900108ca010 RDI: 00004100108ca010
[ 27.190017] RBP: ffff8800baf5bd18 R08: ffff880138eec290 R09: 0000000000000000
[ 27.190017] R10: ffff880138ee2148 R11: 0000000000000e12 R12: ffffc900108ca010
[ 27.190017] R13: 0000000000008649 R14: ffffc900108ca010 R15: ffff880138ee0000
[ 27.190017] FS: 00007f96aaf6c740(0000) GS:ffff88013f300000(0000)
knlGS:0000000000000000
[ 27.190017] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 27.190017] CR2: 00007f96aaf5d00f CR3: 00000000b9e7a000 CR4: 00000000000407e0
[ 27.190017] Stack:
[ 27.190017] ffff8800b9d55520 ffff8800baf5bd70 0000000000008649
ffffc900108ca010
[ 27.190017] ffff8800baf5bdb8 ffffffff811f9f50 ffffffff811f3eef
0000000538ee8000
[ 27.190017] ffff880138c42000 ffff880000000000 0000000087654321
ffffea0002ebd6c0
[ 27.190017] Call Trace:
[ 27.190017] [<ffffffff811f9f50>] aa_calc_profile_hash+0x75/0x11d
[ 27.190017] [<ffffffff811f3eef>] ? __aa_kvmalloc+0x39/0x51
[ 27.190017] [<ffffffff811f7e34>] aa_unpack+0x929/0x969
[ 27.190017] [<ffffffff811f6a21>] aa_replace_profiles+0x38/0x57c
[ 27.190017] [<ffffffff811f249b>] profile_replace+0x35/0x4c
[ 27.190017] [<ffffffff81121477>] vfs_write+0xad/0x113
[ 27.190017] [<ffffffff81121add>] SyS_write+0x44/0x7a
[ 27.190017] [<ffffffff8145f3e2>] system_call_fastpath+0x16/0x1b
[ 27.190017] Code: 66 89 45 fc e8 6a fc ff ff c9 c3 55 48 89 e5 41
56 41 55 41 89 d5 41 54 49 89 f4 53 48 89 fb 48 89 f7 e8 1b 9e e3 ff
84 c0 75 02 <0f> 0b 4c 89 e7 45 89 e6 e8 96 9e e3 ff 48 8b 53 08 41 81
e6 ff
[ 27.190017] RIP [<ffffffff811f9e71>] sg_set_buf+0x20/0x7e
[ 27.190017] RSP <ffff8800baf5bcf8>


2013-09-23 04:57:54

by John Johansen

[permalink] [raw]
Subject: Re: Linus GIT - kernel BUG at include/linux/scatterlist.h:115! CPU: 1 PID: 1203 Comm: apparmor_parser Not tainted 3.12.0-rc1+

On 09/22/2013 07:30 PM, Miles Lane wrote:

yep, thanks for the report. I have a patch for this one, attached
below but is also being sent up to the security tree.

---

apparmor: Use shash crypto API interface for profile hashes

Use the shash interface, rather than the hash interface, when hashing
AppArmor profiles. The shash interface does not use scatterlists and it
is a better fit for what AppArmor needs.

This fixes a kernel paging BUG when aa_calc_profile_hash() is passed a
buffer from vmalloc(). The hash interface requires callers to handle
vmalloc() buffers differently than what AppArmor was doing. Due to
vmalloc() memory not being physically contiguous, each individual page
behind the buffer must be assigned to a scatterlist with sg_set_page()
and then the scatterlist passed to crypto_hash_update().

The shash interface does not have that limitation and allows vmalloc()
and kmalloc() buffers to be handled in the same manner.

https://launchpad.net/bugs/1216294/

Signed-off-by: Tyler Hicks <[email protected]>
Acked-by: John Johansen <[email protected]>
---

I've tested this patch by comparing aafs/policy/profiles/*/sha1 between a
patched i386 VM (i386 is where the BUG is easily reproduced) and an unpatched
amd64 VM. Then I did `service apparmor restart` to trigger a profile
replacement and compared the sha1 files in aafs again. I put all of that into a
loop and let it run for a while.

Tyler

security/apparmor/crypto.c | 34 ++++++++++++++++------------------
1 file changed, 16 insertions(+), 18 deletions(-)

diff --git a/security/apparmor/crypto.c b/security/apparmor/crypto.c
index d6222ba..532471d 100644
--- a/security/apparmor/crypto.c
+++ b/security/apparmor/crypto.c
@@ -15,14 +15,14 @@
* it should be.
*/

-#include <linux/crypto.h>
+#include <crypto/hash.h>

#include "include/apparmor.h"
#include "include/crypto.h"

static unsigned int apparmor_hash_size;

-static struct crypto_hash *apparmor_tfm;
+static struct crypto_shash *apparmor_tfm;

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,
size_t len)
{
- struct scatterlist sg[2];
- struct hash_desc desc = {
- .tfm = apparmor_tfm,
- .flags = 0
- };
+ struct {
+ struct shash_desc shash;
+ char ctx[crypto_shash_descsize(apparmor_tfm)];
+ } desc;
int error = -ENOMEM;
u32 le32_version = cpu_to_le32(version);

if (!apparmor_tfm)
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);
if (!profile->hash)
goto fail;

- error = crypto_hash_init(&desc);
+ desc.shash.tfm = apparmor_tfm;
+ desc.shash.flags = 0;
+
+ error = crypto_shash_init(&desc.shash);
if (error)
goto fail;
- error = crypto_hash_update(&desc, &sg[0], 4);
+ error = crypto_shash_update(&desc.shash, (u8 *) &le32_version, 4);
if (error)
goto fail;
- error = crypto_hash_update(&desc, &sg[1], len);
+ error = crypto_shash_update(&desc.shash, (u8 *) start, len);
if (error)
goto fail;
- error = crypto_hash_final(&desc, profile->hash);
+ error = crypto_shash_final(&desc.shash, profile->hash);
if (error)
goto fail;

@@ -75,19 +73,19 @@ fail:

static int __init init_profile_hash(void)
{
- struct crypto_hash *tfm;
+ struct crypto_shash *tfm;

if (!apparmor_initialized)
return 0;

- tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
+ tfm = crypto_alloc_shash("sha1", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
int error = PTR_ERR(tfm);
AA_ERROR("failed to setup profile sha1 hashing: %d\n", error);
return error;
}
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");

--
1.8.3.2