Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp4158243pxk; Tue, 8 Sep 2020 12:09:51 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyHdv6IGW6JNkuAnf8YscD5gTkqvPFamyRkv8cTFdZpu+1t8kGEto8MLRFgal/VzoCazWf1 X-Received: by 2002:a50:fc87:: with SMTP id f7mr497081edq.162.1599592191718; Tue, 08 Sep 2020 12:09:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1599592191; cv=none; d=google.com; s=arc-20160816; b=nWzUG1Q16pfbCZWtCTnJXOiPmuI88645TOxnyJCY0Df7cIn4UonC2M4buB9mX+FwQj BDn0LY2FFpSWS4AuNGd2+q4kSkVVESFT9iEoBNKdIN6yo9BwlVIGOP2CUj9Yt+Vi02DH Kt23hqtuCi64dGJZjIXlv7dLryS8qMoG0J0mXknIgaK/RTlezftbf4/JHnEZP/mQ1rN8 2yLuJGLNuwG8iYyi3Rkq6Dn1N6dY2BxcjTg2041DOsuqPTFyKowtyZdKe65b51eycv96 TZAawBrmJXqxD/o07F6b2WHv4cZRF8CFIin3XVrvBaa8/7NQ3LqjKYKV0JwJGKXOqw4J YLCg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=MHzvQhWpKwRt399QiaH/nJmWEsPEqzHbIt+ZazvDKh4=; b=Z1xkfl7h4EPNDwyoKNTB5r5KI0ea1vnVV1HhWsgMB31RpBrlGuHB5vSq/fRtPc8/QR InPAlOgZ+nnZBiCX/sp1/7X/0GvXtgKHCsQWCxeb21d1UhZDqqofRyng2a0ooAvRWX9I 8+Nxm+5onNIR4O6e9ha2mvOl+CYGQe8sCxgcInpndxrj2LUgGRuQCAWAWwF1x4cBLyKW LvBnZIhjMABmBXkOCXJnGW2K6sgSTxXJGG4i+FtBU+FljB/CxqIGTdKYjtkamtflOlGP 8mGWl1oMdg6HkB7lY0YPw5UuMXlWJ3ODr+wxPvZVB20H9EoRR7xlKPbdw5uBsHqQsNbO tj8g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=rhMvfx5K; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id p16si12091696edm.382.2020.09.08.12.09.29; Tue, 08 Sep 2020 12:09:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=rhMvfx5K; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731757AbgIHTFZ (ORCPT + 99 others); Tue, 8 Sep 2020 15:05:25 -0400 Received: from mail.kernel.org ([198.145.29.99]:53658 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731263AbgIHQHV (ORCPT ); Tue, 8 Sep 2020 12:07:21 -0400 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (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 2747723E20; Tue, 8 Sep 2020 15:46:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599580016; bh=/Ow/lijeSaiywMPPJbECOmMdH5AK3m0GXUZw93uyVAA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rhMvfx5KL+Zw8Dem/1G2uDkp6uFllLp8ibGR9S6ykAxywwgpoKAz7iVGbU+XyyY3Y 5d3tHB5f/vfS5KIMVhqtHMr1Wb8JlacWhMebiYguS65gPkxRqPp9e73lSGxNU+LilY uOmREJD+OHJHnEPMP0GAzZjXn/OX52SsN2r9dMJA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Muchun Song , Andrew Morton , Mike Kravetz , Andi Kleen , Linus Torvalds Subject: [PATCH 5.4 126/129] mm/hugetlb: fix a race between hugetlb sysctl handlers Date: Tue, 8 Sep 2020 17:26:07 +0200 Message-Id: <20200908152236.156999518@linuxfoundation.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200908152229.689878733@linuxfoundation.org> References: <20200908152229.689878733@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Muchun Song commit 17743798d81238ab13050e8e2833699b54e15467 upstream. There is a race between the assignment of `table->data` and write value to the pointer of `table->data` in the __do_proc_doulongvec_minmax() on the other thread. CPU0: CPU1: proc_sys_write hugetlb_sysctl_handler proc_sys_call_handler hugetlb_sysctl_handler_common hugetlb_sysctl_handler table->data = &tmp; hugetlb_sysctl_handler_common table->data = &tmp; proc_doulongvec_minmax do_proc_doulongvec_minmax sysctl_head_finish __do_proc_doulongvec_minmax unuse_table i = table->data; *i = val; // corrupt CPU1's stack Fix this by duplicating the `table`, and only update the duplicate of it. And introduce a helper of proc_hugetlb_doulongvec_minmax() to simplify the code. The following oops was seen: BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor instruction fetch in kernel mode #PF: error_code(0x0010) - not-present page Code: Bad RIP value. ... Call Trace: ? set_max_huge_pages+0x3da/0x4f0 ? alloc_pool_huge_page+0x150/0x150 ? proc_doulongvec_minmax+0x46/0x60 ? hugetlb_sysctl_handler_common+0x1c7/0x200 ? nr_hugepages_store+0x20/0x20 ? copy_fd_bitmaps+0x170/0x170 ? hugetlb_sysctl_handler+0x1e/0x20 ? proc_sys_call_handler+0x2f1/0x300 ? unregister_sysctl_table+0xb0/0xb0 ? __fd_install+0x78/0x100 ? proc_sys_write+0x14/0x20 ? __vfs_write+0x4d/0x90 ? vfs_write+0xef/0x240 ? ksys_write+0xc0/0x160 ? __ia32_sys_read+0x50/0x50 ? __close_fd+0x129/0x150 ? __x64_sys_write+0x43/0x50 ? do_syscall_64+0x6c/0x200 ? entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: e5ff215941d5 ("hugetlb: multiple hstates for multiple page sizes") Signed-off-by: Muchun Song Signed-off-by: Andrew Morton Reviewed-by: Mike Kravetz Cc: Andi Kleen Link: http://lkml.kernel.org/r/20200828031146.43035-1-songmuchun@bytedance.com Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/hugetlb.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -3082,6 +3082,22 @@ static unsigned int cpuset_mems_nr(unsig } #ifdef CONFIG_SYSCTL +static int proc_hugetlb_doulongvec_minmax(struct ctl_table *table, int write, + void *buffer, size_t *length, + loff_t *ppos, unsigned long *out) +{ + struct ctl_table dup_table; + + /* + * In order to avoid races with __do_proc_doulongvec_minmax(), we + * can duplicate the @table and alter the duplicate of it. + */ + dup_table = *table; + dup_table.data = out; + + return proc_doulongvec_minmax(&dup_table, write, buffer, length, ppos); +} + static int hugetlb_sysctl_handler_common(bool obey_mempolicy, struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) @@ -3093,9 +3109,8 @@ static int hugetlb_sysctl_handler_common if (!hugepages_supported()) return -EOPNOTSUPP; - table->data = &tmp; - table->maxlen = sizeof(unsigned long); - ret = proc_doulongvec_minmax(table, write, buffer, length, ppos); + ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos, + &tmp); if (ret) goto out; @@ -3139,9 +3154,8 @@ int hugetlb_overcommit_handler(struct ct if (write && hstate_is_gigantic(h)) return -EINVAL; - table->data = &tmp; - table->maxlen = sizeof(unsigned long); - ret = proc_doulongvec_minmax(table, write, buffer, length, ppos); + ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos, + &tmp); if (ret) goto out;