Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753305AbdHRNqM (ORCPT ); Fri, 18 Aug 2017 09:46:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53330 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752612AbdHRNqJ (ORCPT ); Fri, 18 Aug 2017 09:46:09 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 73FF05F795 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=joe.lawrence@redhat.com Subject: Re: [PATCH v4] livepatch: introduce shadow variable API To: Petr Mladek Cc: live-patching@vger.kernel.org, linux-kernel@vger.kernel.org, Josh Poimboeuf , Jessica Yu , Jiri Kosina , Miroslav Benes References: <1502740963-31310-1-git-send-email-joe.lawrence@redhat.com> <1502740963-31310-2-git-send-email-joe.lawrence@redhat.com> <20170817140545.GF601@pathway.suse.cz> From: Joe Lawrence Organization: Red Hat Message-ID: Date: Fri, 18 Aug 2017 09:46:08 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.0 MIME-Version: 1.0 In-Reply-To: <20170817140545.GF601@pathway.suse.cz> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 18 Aug 2017 13:46:09 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2389 Lines: 73 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