* [PATCH] assoc_array: don't call compare_object() on a node
@ 2016-02-22 16:13 Jerome Marchand
2016-02-22 16:37 ` David Howells
2016-02-23 10:28 ` [PATCH V2] " Jerome Marchand
0 siblings, 2 replies; 4+ messages in thread
From: Jerome Marchand @ 2016-02-22 16:13 UTC (permalink / raw)
To: David Howells; +Cc: linux-kernel
In assoc_array_insert_into_terminal_node(), we call the
compare_object() method on all empty slots, even when they're not
leaves, passing a pointer to an unexpected structure to
compare_object(). Currently it causes an out-of-bound read access in
keyring_compare_object detected by KASan. The issue is easily
reproduced with keyutils testsuite.
Only call compare_object() when the slot is a leave.
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
lib/assoc_array.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/assoc_array.c b/lib/assoc_array.c
index 03dd576..59fd7c0 100644
--- a/lib/assoc_array.c
+++ b/lib/assoc_array.c
@@ -524,7 +524,9 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit,
free_slot = i;
continue;
}
- if (ops->compare_object(assoc_array_ptr_to_leaf(ptr), index_key)) {
+ if (assoc_array_ptr_is_leaf(ptr) &&
+ ops->compare_object(assoc_array_ptr_to_leaf(ptr),
+ index_key)) {
pr_devel("replace in slot %d\n", i);
edit->leaf_p = &node->slots[i];
edit->dead_leaf = node->slots[i];
--
2.5.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] assoc_array: don't call compare_object() on a node
2016-02-22 16:13 [PATCH] assoc_array: don't call compare_object() on a node Jerome Marchand
@ 2016-02-22 16:37 ` David Howells
2016-02-22 16:57 ` Jerome Marchand
2016-02-23 10:28 ` [PATCH V2] " Jerome Marchand
1 sibling, 1 reply; 4+ messages in thread
From: David Howells @ 2016-02-22 16:37 UTC (permalink / raw)
To: Jerome Marchand; +Cc: dhowells, keyrings, linux-kernel
Jerome Marchand <jmarchan@redhat.com> wrote:
> In assoc_array_insert_into_terminal_node(), we call the
> compare_object() method on all empty slots,
Ummm... That shouldn't happen - the:
if (!ptr) {
free_slot = i;
continue;
}
preceding the line you modified should cause the comparison to be skipped on a
slot if it's empty.
> even when they're not leaves, passing a pointer to an unexpected structure
> to compare_object().
Do you instead mean a metadata pointer rather than an empty slot?
> Currently it causes an out-of-bound read access in keyring_compare_object
> detected by KASan. The issue is easily reproduced with keyutils testsuite.
I don't see it. Did you modify the testsuite, or is it a matter of running it
often enough?
Also, can you include the oops output you get in the patch description,
please?
That said, I can see that there is probably an issue that your patch fixes -
but it's not quite the one you describe (see above).
David
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] assoc_array: don't call compare_object() on a node
2016-02-22 16:37 ` David Howells
@ 2016-02-22 16:57 ` Jerome Marchand
0 siblings, 0 replies; 4+ messages in thread
From: Jerome Marchand @ 2016-02-22 16:57 UTC (permalink / raw)
To: David Howells; +Cc: keyrings, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1582 bytes --]
On 02/22/2016 05:37 PM, David Howells wrote:
> Jerome Marchand <jmarchan@redhat.com> wrote:
>
>> In assoc_array_insert_into_terminal_node(), we call the
>> compare_object() method on all empty slots,
Sorry, this is a typo. It should be "on all non-empty slots".
>
> Ummm... That shouldn't happen - the:
>
> if (!ptr) {
> free_slot = i;
> continue;
> }
>
> preceding the line you modified should cause the comparison to be skipped on a
> slot if it's empty.
>
>> even when they're not leaves, passing a pointer to an unexpected structure
>> to compare_object().
>
> Do you instead mean a metadata pointer rather than an empty slot?
Yes. In the cases I debugged, it was a node, but I guess we could
encounter a shortcut here too.
>
>> Currently it causes an out-of-bound read access in keyring_compare_object
>> detected by KASan. The issue is easily reproduced with keyutils testsuite.
>
> I don't see it. Did you modify the testsuite, or is it a matter of running it
> often enough?
Do you have KASan enabled? In my experience, the reproduction is
systematic on some test (e.g. keyctl/unlink/all). AFAIK, the testsuite
isn't modify (it's from Red Hat test infrastructure).
>
> Also, can you include the oops output you get in the patch description,
> please?
Sure.
>
> That said, I can see that there is probably an issue that your patch fixes -
> but it's not quite the one you describe (see above).
Does the description sounds correct if you add the missing negation?
Jerome
>
> David
>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH V2] assoc_array: don't call compare_object() on a node
2016-02-22 16:13 [PATCH] assoc_array: don't call compare_object() on a node Jerome Marchand
2016-02-22 16:37 ` David Howells
@ 2016-02-23 10:28 ` Jerome Marchand
1 sibling, 0 replies; 4+ messages in thread
From: Jerome Marchand @ 2016-02-23 10:28 UTC (permalink / raw)
To: David Howells; +Cc: linux-kernel, keyrings
Changes since V1: fixed the description and added KASan warning.
In assoc_array_insert_into_terminal_node(), we call the
compare_object() method on all non-empty slots, even when they're
not leaves, passing a pointer to an unexpected structure to
compare_object(). Currently it causes an out-of-bound read access
in keyring_compare_object detected by KASan (see below). The issue
is easily reproduced with keyutils testsuite.
Only call compare_object() when the slot is a leave.
KASan warning:
==================================================================
BUG: KASAN: slab-out-of-bounds in keyring_compare_object+0x213/0x240 at addr ffff880060a6f838
Read of size 8 by task keyctl/1655
=============================================================================
BUG kmalloc-192 (Not tainted): kasan: bad access detected
-----------------------------------------------------------------------------
Disabling lock debugging due to kernel taint
INFO: Allocated in assoc_array_insert+0xfd0/0x3a60 age=69 cpu=1 pid=1647
___slab_alloc+0x563/0x5c0
__slab_alloc+0x51/0x90
kmem_cache_alloc_trace+0x263/0x300
assoc_array_insert+0xfd0/0x3a60
__key_link_begin+0xfc/0x270
key_create_or_update+0x459/0xaf0
SyS_add_key+0x1ba/0x350
entry_SYSCALL_64_fastpath+0x12/0x76
INFO: Slab 0xffffea0001829b80 objects=16 used=8 fp=0xffff880060a6f550 flags=0x3fff8000004080
INFO: Object 0xffff880060a6f740 @offset=5952 fp=0xffff880060a6e5d1
Bytes b4 ffff880060a6f730: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f740: d1 e5 a6 60 00 88 ff ff 0e 00 00 00 00 00 00 00 ...`............
Object ffff880060a6f750: 02 cf 8e 60 00 88 ff ff 02 c0 8e 60 00 88 ff ff ...`.......`....
Object ffff880060a6f760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f790: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f7a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f7b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f7c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f7d0: 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f7e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Object ffff880060a6f7f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
CPU: 0 PID: 1655 Comm: keyctl Tainted: G B 4.5.0-rc4-kasan+ #291
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
0000000000000000 000000001b2800b4 ffff880060a179e0 ffffffff81b60491
ffff88006c802900 ffff880060a6f740 ffff880060a17a10 ffffffff815e2969
ffff88006c802900 ffffea0001829b80 ffff880060a6f740 ffff880060a6e650
Call Trace:
[<ffffffff81b60491>] dump_stack+0x85/0xc4
[<ffffffff815e2969>] print_trailer+0xf9/0x150
[<ffffffff815e9454>] object_err+0x34/0x40
[<ffffffff815ebe50>] kasan_report_error+0x230/0x550
[<ffffffff819949be>] ? keyring_get_key_chunk+0x13e/0x210
[<ffffffff815ec62d>] __asan_report_load_n_noabort+0x5d/0x70
[<ffffffff81994cc3>] ? keyring_compare_object+0x213/0x240
[<ffffffff81994cc3>] keyring_compare_object+0x213/0x240
[<ffffffff81bc238c>] assoc_array_insert+0x86c/0x3a60
[<ffffffff81bc1b20>] ? assoc_array_cancel_edit+0x70/0x70
[<ffffffff8199797d>] ? __key_link_begin+0x20d/0x270
[<ffffffff8199786c>] __key_link_begin+0xfc/0x270
[<ffffffff81993389>] key_create_or_update+0x459/0xaf0
[<ffffffff8128ce0d>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff81992f30>] ? key_type_lookup+0xc0/0xc0
[<ffffffff8199e19d>] ? lookup_user_key+0x13d/0xcd0
[<ffffffff81534763>] ? memdup_user+0x53/0x80
[<ffffffff819983ea>] SyS_add_key+0x1ba/0x350
[<ffffffff81998230>] ? key_get_type_from_user.constprop.6+0xa0/0xa0
[<ffffffff828bcf4e>] ? retint_user+0x18/0x23
[<ffffffff8128cc7e>] ? trace_hardirqs_on_caller+0x3fe/0x580
[<ffffffff81004017>] ? trace_hardirqs_on_thunk+0x17/0x19
[<ffffffff828bc432>] entry_SYSCALL_64_fastpath+0x12/0x76
Memory state around the buggy address:
ffff880060a6f700: fc fc fc fc fc fc fc fc 00 00 00 00 00 00 00 00
ffff880060a6f780: 00 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc
>ffff880060a6f800: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffff880060a6f880: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff880060a6f900: fc fc fc fc fc fc 00 00 00 00 00 00 00 00 00 00
==================================================================
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
lib/assoc_array.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/assoc_array.c b/lib/assoc_array.c
index 03dd576..59fd7c0 100644
--- a/lib/assoc_array.c
+++ b/lib/assoc_array.c
@@ -524,7 +524,9 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit,
free_slot = i;
continue;
}
- if (ops->compare_object(assoc_array_ptr_to_leaf(ptr), index_key)) {
+ if (assoc_array_ptr_is_leaf(ptr) &&
+ ops->compare_object(assoc_array_ptr_to_leaf(ptr),
+ index_key)) {
pr_devel("replace in slot %d\n", i);
edit->leaf_p = &node->slots[i];
edit->dead_leaf = node->slots[i];
--
2.5.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2016-02-23 10:28 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-22 16:13 [PATCH] assoc_array: don't call compare_object() on a node Jerome Marchand
2016-02-22 16:37 ` David Howells
2016-02-22 16:57 ` Jerome Marchand
2016-02-23 10:28 ` [PATCH V2] " Jerome Marchand
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox