From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: ** X-Spam-Status: No, score=2.4 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HTML_MESSAGE,MAILING_LIST_MULTI,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7AD93C28CBC for ; Sun, 3 May 2020 05:54:10 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 2965A207DD for ; Sun, 3 May 2020 05:54:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="agPzahvh" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2965A207DD Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id E4C5B8E0005; Sun, 3 May 2020 01:54:08 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id DFC848E0001; Sun, 3 May 2020 01:54:08 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D12738E0005; Sun, 3 May 2020 01:54:08 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0245.hostedemail.com [216.40.44.245]) by kanga.kvack.org (Postfix) with ESMTP id B88F68E0001 for ; Sun, 3 May 2020 01:54:08 -0400 (EDT) Received: from smtpin13.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id 704504DDF for ; Sun, 3 May 2020 05:54:08 +0000 (UTC) X-FDA: 76774342176.13.trip43_241816832f802 X-HE-Tag: trip43_241816832f802 X-Filterd-Recvd-Size: 7994 Received: from mail-il1-f179.google.com (mail-il1-f179.google.com [209.85.166.179]) by imf49.hostedemail.com (Postfix) with ESMTP for ; Sun, 3 May 2020 05:54:07 +0000 (UTC) Received: by mail-il1-f179.google.com with SMTP id s10so8226621iln.11 for ; Sat, 02 May 2020 22:54:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=+orlJv04VVENsxp3P3NewtywowLB/Z7soBUgDWcU2k0=; b=agPzahvhpJe5wplM99NwHdXOeaUi76VGhk50a+kScR4ZhPuW3FflzDZJszoD0N3dyE zBQZcIUK+qiNjHm6r7eM5hqnkI9uMie+aS/GpT/ax8Uryga5v73C37oeO2ZAN/sS27C4 /5h8lm17NvB5Q4yP07MU9Ehn4IPeLsihd5hJH1ciQKRznDXC2/0c1gNzx3HpTAF7erD6 ytlVsNRdu2zgBuHAv3DdAfqmRJZjdk3dKYedHknLXpJ5lGRIEvJWAE1FKAZVKeTXG1aq 2opmN012Xe9M44OweApXjoNeWoka01oYx96LiClDxYCNOSzM9/DJIgljE1EiNAriJKdy mqHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=+orlJv04VVENsxp3P3NewtywowLB/Z7soBUgDWcU2k0=; b=N2XA0vyw+pUh1wIgKSOlVQ9SmQmsJG67WQx5m7AUKLFoN+kvuqOYSRzA7laYgYyooa Rm2WdQfdL/yWaMTveD9FMSlJd//txHPo+784+8rdwxwLXcojka836ZG+RVZk5eLkrp9P 6I8l0AzCMxIPqvdYLHYYCbP36lbkeJp274666thSSchxVmyyJfM+GYlgizUK2eLZeW/y N2rmVskgJC19jH8EQlmImufWKsTpfHAYLaXAHwiqs8dehQutAtlm5dOhqgpcb+RULFtb FiDSapZdK8WccUpRaPvVrVeT5IrQlQe9/oRapUDeIJ+i7gqak4tqTkoDU9erfHkhK4F7 cWgQ== X-Gm-Message-State: AGi0PuZzk0A9ep4x+QKu3h1mpVgUSgiFOo898hxTisv/N26JWbVUq8Rc KLh/Tm7cbw9D1kW3asSfltsB5xNX6WnLs9gNhPiyU3m9 X-Google-Smtp-Source: APiQypJw4nukqR2NzzyxvcaPa8j2pjuf2nfssviqAFCQclsqneXDvCKMl9G5kTHG2cF/nGgessi3iwOVCFa7n22eA7o= X-Received: by 2002:a92:3c0f:: with SMTP id j15mr10582348ila.201.1588485247185; Sat, 02 May 2020 22:54:07 -0700 (PDT) MIME-Version: 1.0 From: Dongyang Zhan Date: Sun, 3 May 2020 13:53:56 +0800 Message-ID: Subject: Possible null pointer dereference in memory_present() To: linux-mm@kvack.org Content-Type: multipart/alternative; boundary="000000000000e3b69c05a4b80ae0" X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: --000000000000e3b69c05a4b80ae0 Content-Type: text/plain; charset="UTF-8" Hi, I found a potential bug in /mm/sparse.c. So, I hope you can help me to confirm it. In Linux 4.10.17, memory_present() in /mm/sparse.c does not handles the failure of ms = __nr_to_section(section), causing a null pointer dereference bug. If ms = __nr_to_section(section) fails, which makes ms a null pointer. accessing ms->section_mem_map will trigger a bug. void __init memory_present(int nid, unsigned long start, unsigned long end) { unsigned long pfn; start &= PAGE_SECTION_MASK; mminit_validate_memmodel_limits(&start, &end); for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) { unsigned long section = pfn_to_section_nr(pfn); struct mem_section *ms; sparse_index_init(section, nid); // set_section_nid(section, nid); ms = __nr_to_section(section); //does not handle the failure. if (!ms->section_mem_map) //null pointer dereference bug ms->section_mem_map = sparse_encode_early_nid(nid) | SECTION_MARKED_PRESENT; } } Let us see sparse_index_init(section, nid) in /mm/sparse.c static int __meminit sparse_index_init(unsigned long section_nr, int nid) { unsigned long root = SECTION_NR_TO_ROOT(section_nr); struct mem_section *section; if (mem_section[root]) //if mem_section[root] does not exist, the section will be allocated. return -EEXIST; section = sparse_index_alloc(nid); if (!section) return -ENOMEM;// if it fails to allocate the section, mem_section[root] will be a null pointer. mem_section[root] = section; return 0; } If mem_section[root] does not exist, the section will be allocated. And, if it fails to allocate the section, mem_section[root] will be a null pointer. Note that, root is the result of SECTION_NR_TO_ROOT(section_nr), so mem_section[SECTION_NR_TO_ROOT(section_nr)] is null. Then, let us see __nr_to_section() in /include/linux/mmzone.h . static inline struct mem_section *__nr_to_section(unsigned long nr) { if (!mem_section[SECTION_NR_TO_ROOT(nr)]) // The nr is nid in __init memory_present(). So, mem_section[SECTION_NR_TO_ROOT(nr)] is null in the above case. return NULL; return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK]; } Therefore, this function can return a null pointer. Accessing ms->section_mem_map in __init memory_present() will trigger a null pointer dereference bug. --000000000000e3b69c05a4b80ae0 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,
I found a potential bug in /mm/sparse.c.
So, I hope you can help me to =
confirm it.

In =
Linux 4.10.17, memory_present() in /mm/sparse.c does not handles the failur=
e of ms =3D __nr_to_section(section), causing a null pointer dereference bu=
g. If ms =3D __nr_to_section(section) fails, which makes ms a null pointer.=
 accessing ms->section_mem_map will trigger a bug.

void __init memory_present(int nid, unsigned long start, unsigned long end)
{
	unsigned long pfn;

	start &=3D PAGE_SECTION_MASK;
	mminit_validate_memmodel_limits(&start, &end);
	for (pfn =3D start; pfn < end; pfn +=3D PAGES_PER_SECTION) {
		unsigned long section =3D pfn_to_section_nr(pfn);
		struct mem_section *ms;

		sparse_index_init(section, nid); //
		set_section_nid(section, nid);

		ms =3D __nr_to_section(section); //does not handle the failure.
		if (!ms->section_mem_map) //null pointer dereference bug
			ms->section_mem_map =3D sparse_encode_early_nid(nid) |
							SECTION_MARKED_PRESENT;
	}
}
Let us see sparse_index_init(section, nid) in /mm/sparse.c=20
static int __meminit sparse_index_init(unsigned long section_nr, int nid)
{
	unsigned long root =3D SECTION_NR_TO_ROOT(section_nr);
	struct mem_section *section;

	if (mem_section[root]) //if mem_section[root] does not exist, the section =
will be allocated.
		return -EEXIST;

	section =3D sparse_index_alloc(nid);
	if (!section)
		return -ENOMEM;// if it fails to allocate the section, mem_section[root] =
will be a null pointer.

	mem_section[root] =3D section;

	return 0;
}
If mem_section[root] does not exist, the section will be allocated. And, if=
 it fails to allocate the section, mem_section[root] will be a null pointer=
. Note that, root is the result of SECTION_NR_TO_ROOT(section_nr), so mem_s=
ection[SECTION_NR_TO_ROOT(section_nr)] is null.

Then, let us see __nr_to_section() in /include/linux/mmzone.h .
static inline struct mem_section *__nr_to_section(unsigned long nr)
{
	if (!mem_section[SECTION_NR_TO_ROOT(nr)]) // The nr is  nid in __init memo=
ry_present(). So, mem_section[SECTION_NR_TO_ROOT(nr)] is null in the above =
case.
		return NULL;
	return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK=
];
}
Therefore, this function can return a null pointer. Accessing ms->sectio=
n_mem_map in __init memory_present() will trigger a null pointer dereferenc=
e bug.
--000000000000e3b69c05a4b80ae0--