On Fri 2017-08-18 09:46:08, Joe Lawrence wrote: > 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*. Ah, I see. The extra kftree does not free the shadow->data but it frees the data that the shadow variable points to. > 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 I would rename shadow_leak -> leak. It will make it more clear that it is the original leak pointer. Well, we could actually free the data before we detach/destroy the shadow variable. But then it might deserve a comment to avoid confusion that I had. I mean: shadow_leak = klp_shadow_get(d, SV_LEAK); if (shadow_leak) { pr_info("%s: dummy @ %p, prevented leak @ %p\n", __func__, d, *shadow_leak); /* Free the previously leaked data */ kfree(*shadow_leak); /* Free the shadow variable */ klp_shadow_detach(d, SV_LEAK); > 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. Sounds like a good practice. > 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. Yup. Best Regards, Petr -- 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