Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp2366625imm; Mon, 28 May 2018 06:50:20 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrdy/ei5QrloZHahpCqTl6IA6+Ngl6Fyf3wiBB9g2timz9aeFLEkZk/Jdye5udf2Zw1hmlE X-Received: by 2002:a65:5c89:: with SMTP id a9-v6mr8770897pgt.51.1527515420747; Mon, 28 May 2018 06:50:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527515420; cv=none; d=google.com; s=arc-20160816; b=hhca09Tjyud+4tpfsvd9ay4ZYVS5s89wDzJ0FK8H8Hk+tNMBM8fPqFf9A87FQON8v8 oqcFSZPFSHSqMWGr74DXL2R/g27ZRp0L8M/cpOFkqzgsXDFw5NL/50Dqr3qVcn90w5iG PxFf7vWefiOYvCUl+frjuAVIiSdsC+BLovDtYIslj8GLZ4fW8IWXt8FE1arfsa7rQvL1 9hVuKrRtDTcRxuRLmVOMJdrGBM042UFX1RQ2s/uZ2Gql73/w+5QyP8mkvPwfTZNvP6k4 3OAx7FyxkV2BGv/b7Ft6GlQGz5yDu7a7IFMskxonv1lhp67ADTlnQVDKOfjUrhqnhUFf PqHg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=TBpCVbEH3iW9xhgofz38+2ORulUHhisOpDSxGQtMuK4=; b=pt/4i0mLGu281UKP+X2ZKxBWY5eWrXd9bwoWUnFoGXXIPVooQJdBZitX09JQc1XzCX nlMeUrA0i41hLL3bnsQuUkA2/GhOigdz1UWYhJhxdcYk0SA6TsBcuG2hu9qY0/+k8o3d dt80aP4L+rumr/1YPf0TsnGr8nPYA7eTMbxersI+a6pXUJl9qWup7DjXWk/lZ4zdbSPc U3wtPnHGtBhNI3ttuhPcPN/LvXrTsQWnMDKL6ihzzrxhdtS3pxowOWeVvlZuVK6D9BH5 rL1kONBL1AZdyTu6kviua7ZcH+L28x/WUoq/H6Epyf+voMsbelTOZ+Vw+zma/FG940Ys B12Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=xkaaS5/P; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a23-v6si29085355pfi.353.2018.05.28.06.50.05; Mon, 28 May 2018 06:50:20 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=xkaaS5/P; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932404AbeE1KmS (ORCPT + 99 others); Mon, 28 May 2018 06:42:18 -0400 Received: from mail.kernel.org ([198.145.29.99]:33560 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S937418AbeE1KmN (ORCPT ); Mon, 28 May 2018 06:42:13 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 028202086D; Mon, 28 May 2018 10:42:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1527504132; bh=4GFqK1t1LQblCIkJKvaAOPFZZ8aLS2/xTqnFed7pxRI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=xkaaS5/PDWqSqf44PnHDx5ZcEQu1Y28no8xNvIFGwM+6Xx6p/6Yj7vByw9JkS/Yaf 2qbaPFI0F9ZTLceB2Za3NMOAE80wOfaKdgSmTRaV+jaknmyrZgEKJtw+3BxERq3IUp tp7647jRGtHziQkn8oC5l0owL44sXJIBA+DKeKuw= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Andrey Ryabinin , Paul Menzel , Alexander Potapenko , Dmitry Vyukov , Matthew Wilcox , Andrew Morton , Linus Torvalds Subject: [PATCH 4.14 025/496] mm/kasan: dont vfree() nonexistent vm_area Date: Mon, 28 May 2018 11:56:50 +0200 Message-Id: <20180528100320.650216776@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180528100319.498712256@linuxfoundation.org> References: <20180528100319.498712256@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Andrey Ryabinin commit 0f901dcbc31f88ae41a2aaa365f7802b5d520a28 upstream. KASAN uses different routines to map shadow for hot added memory and memory obtained in boot process. Attempt to offline memory onlined by normal boot process leads to this: Trying to vfree() nonexistent vm area (000000005d3b34b9) WARNING: CPU: 2 PID: 13215 at mm/vmalloc.c:1525 __vunmap+0x147/0x190 Call Trace: kasan_mem_notifier+0xad/0xb9 notifier_call_chain+0x166/0x260 __blocking_notifier_call_chain+0xdb/0x140 __offline_pages+0x96a/0xb10 memory_subsys_offline+0x76/0xc0 device_offline+0xb8/0x120 store_mem_state+0xfa/0x120 kernfs_fop_write+0x1d5/0x320 __vfs_write+0xd4/0x530 vfs_write+0x105/0x340 SyS_write+0xb0/0x140 Obviously we can't call vfree() to free memory that wasn't allocated via vmalloc(). Use find_vm_area() to see if we can call vfree(). Unfortunately it's a bit tricky to properly unmap and free shadow allocated during boot, so we'll have to keep it. If memory will come online again that shadow will be reused. Matthew asked: how can you call vfree() on something that isn't a vmalloc address? vfree() is able to free any address returned by __vmalloc_node_range(). And __vmalloc_node_range() gives you any address you ask. It doesn't have to be an address in [VMALLOC_START, VMALLOC_END] range. That's also how the module_alloc()/module_memfree() works on architectures that have designated area for modules. [aryabinin@virtuozzo.com: improve comments] Link: http://lkml.kernel.org/r/dabee6ab-3a7a-51cd-3b86-5468718e0390@virtuozzo.com [akpm@linux-foundation.org: fix typos, reflow comment] Link: http://lkml.kernel.org/r/20180201163349.8700-1-aryabinin@virtuozzo.com Fixes: fa69b5989bb0 ("mm/kasan: add support for memory hotplug") Signed-off-by: Andrey Ryabinin Reported-by: Paul Menzel Cc: Alexander Potapenko Cc: Dmitry Vyukov Cc: Matthew Wilcox Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/kasan/kasan.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) --- a/mm/kasan/kasan.c +++ b/mm/kasan/kasan.c @@ -737,6 +737,40 @@ void __asan_unpoison_stack_memory(const EXPORT_SYMBOL(__asan_unpoison_stack_memory); #ifdef CONFIG_MEMORY_HOTPLUG +static bool shadow_mapped(unsigned long addr) +{ + pgd_t *pgd = pgd_offset_k(addr); + p4d_t *p4d; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + if (pgd_none(*pgd)) + return false; + p4d = p4d_offset(pgd, addr); + if (p4d_none(*p4d)) + return false; + pud = pud_offset(p4d, addr); + if (pud_none(*pud)) + return false; + + /* + * We can't use pud_large() or pud_huge(), the first one is + * arch-specific, the last one depends on HUGETLB_PAGE. So let's abuse + * pud_bad(), if pud is bad then it's bad because it's huge. + */ + if (pud_bad(*pud)) + return true; + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd)) + return false; + + if (pmd_bad(*pmd)) + return true; + pte = pte_offset_kernel(pmd, addr); + return !pte_none(*pte); +} + static int __meminit kasan_mem_notifier(struct notifier_block *nb, unsigned long action, void *data) { @@ -758,6 +792,14 @@ static int __meminit kasan_mem_notifier( case MEM_GOING_ONLINE: { void *ret; + /* + * If shadow is mapped already than it must have been mapped + * during the boot. This could happen if we onlining previously + * offlined memory. + */ + if (shadow_mapped(shadow_start)) + return NOTIFY_OK; + ret = __vmalloc_node_range(shadow_size, PAGE_SIZE, shadow_start, shadow_end, GFP_KERNEL, PAGE_KERNEL, VM_NO_GUARD, @@ -769,8 +811,25 @@ static int __meminit kasan_mem_notifier( kmemleak_ignore(ret); return NOTIFY_OK; } - case MEM_OFFLINE: - vfree((void *)shadow_start); + case MEM_OFFLINE: { + struct vm_struct *vm; + + /* + * shadow_start was either mapped during boot by kasan_init() + * or during memory online by __vmalloc_node_range(). + * In the latter case we can use vfree() to free shadow. + * Non-NULL result of the find_vm_area() will tell us if + * that was the second case. + * + * Currently it's not possible to free shadow mapped + * during boot by kasan_init(). It's because the code + * to do that hasn't been written yet. So we'll just + * leak the memory. + */ + vm = find_vm_area((void *)shadow_start); + if (vm) + vfree((void *)shadow_start); + } } return NOTIFY_OK;