From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752693AbdAZCFY (ORCPT ); Wed, 25 Jan 2017 21:05:24 -0500 Received: from shelob.surriel.com ([96.67.55.147]:42401 "EHLO shelob.surriel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752536AbdAZCFW (ORCPT ); Wed, 25 Jan 2017 21:05:22 -0500 From: riel@redhat.com To: linux-kernel@vger.kernel.org Cc: mingo@kernel.org, luto@kernel.org, yu-cheng.yu@intel.com, dave.hansen@linux.intel.com, bp@suse.de Subject: [PATCH 1/2] x86/fpu: move copyout_from_xsaves bounds check before the copy Date: Wed, 25 Jan 2017 20:57:58 -0500 Message-Id: <20170126015759.25871-2-riel@redhat.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170126015759.25871-1-riel@redhat.com> References: <20170126015759.25871-1-riel@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Rik van Riel Userspace may have programs, especially debuggers, that do not know how large the full XSAVE area space is. They pass in a size argument, and expect to not get more data than that. Unfortunately, the current copyout_from_xsaves does the bounds check after the copy out to userspace. This could theoretically result in the kernel scribbling over userspace memory outside of the buffer, before bailing out of the copy. In practice, this is not likely to be an issue, since debuggers are likely to specify the size they know about, and that size is likely to exactly match the XSAVE fields they know about. However, we could be a little more careful and do the bounds check before committing ourselves with a copy to userspace. Signed-off-by: Rik van Riel --- arch/x86/kernel/fpu/xstate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index c24ac1efb12d..c1508d56ecfb 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -992,13 +992,13 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf, offset = xstate_offsets[i]; size = xstate_sizes[i]; + if (offset + size > count) + break; + ret = xstate_copyout(offset, size, kbuf, ubuf, src, 0, count); if (ret) return ret; - - if (offset + size >= count) - break; } } -- 2.9.3