On 08/17/2017 10:05 AM, Petr Mladek wrote: > On Mon 2017-08-14 16:02:43, Joe Lawrence wrote: >> [ ... snip ... ] >> diff --git a/samples/livepatch/livepatch-shadow-fix1.c b/samples/livepatch/livepatch-shadow-fix1.c >> new file mode 100644 >> index 000000000000..5acc838463d1 >> --- /dev/null >> +++ b/samples/livepatch/livepatch-shadow-fix1.c >> +void livepatch_fix1_dummy_free(struct dummy *d) >> +{ >> + void **shadow_leak; >> + >> + /* >> + * Patch: fetch the saved SV_LEAK shadow variable, detach and >> + * free it. Note: handle cases where this shadow variable does >> + * not exist (ie, dummy structures allocated before this livepatch >> + * was loaded.) >> + */ >> + shadow_leak = klp_shadow_get(d, SV_LEAK); >> + if (shadow_leak) { >> + klp_shadow_detach(d, SV_LEAK); >> + kfree(*shadow_leak); > > This should get removed. The buffer used for the shadow variable > is freed by kfree_rcu() called from klp_shadow_detach(). > > Same problem is also in the other livepatch. > >> + pr_info("%s: dummy @ %p, prevented leak @ %p\n", >> + __func__, d, *shadow_leak); > > This might access shadow_leak after it was (double) freed. > >> + } else { >> + pr_info("%s: dummy @ %p leaked!\n", __func__, d); >> + } >> + >> + kfree(d); >> +} Hi Petr, I think you're half correct. The kfree is the crux of the memory leak patch, so it needs to stay. However, the shadow variable is holding a copy of the pointer to the memory leak area, so you're right that it can't be safely dereferenced after the shadow variable is detached*. The code should to be rearranged like: void livepatch_fix1_dummy_free(struct dummy *d) { void **p_shadow_leak, *shadow_leak; p_shadow_leak = klp_shadow_get(d, SV_LEAK); if (p_shadow_leak) { shadow_leak = *p_shadow_leak; << deref before detach klp_shadow_detach(d, SV_LEAK); kfree(shadow_leak); ... * Aside: I usually develop with slub_debug=FZPU set to catch silly use-after-frees like this. However, since the shadow variable is released via kfree_rcu(), I think there was a window before the grace period where this one worked out okay... once I added a synchronize_rcu() call in between the klp_shadow_detch() and kfree() calls, I did see the poison pattern. This is my first time using kfree_rcu(), so it was interesting to dig into. Thanks, -- Joe -- To unsubscribe from this list: send the line "unsubscribe live-patching" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html