Received: by 2002:a05:6358:53a8:b0:117:f937:c515 with SMTP id z40csp5778123rwe; Tue, 18 Apr 2023 11:19:37 -0700 (PDT) X-Google-Smtp-Source: AKy350ZEQwQUr1nt0rwk3f8gTQncQtDQMDnloAnj2Rv4sixJE6kxU+D9Tz7Ym3/pLAjbhOuA4mOu X-Received: by 2002:a05:6a21:118f:b0:ef:67c4:2719 with SMTP id oj15-20020a056a21118f00b000ef67c42719mr600942pzb.22.1681841977109; Tue, 18 Apr 2023 11:19:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681841977; cv=none; d=google.com; s=arc-20160816; b=j5BlNmpbDCF47miR+WKNjVN6vZbuuFPTTBLC5jsY6UYFwE7XjGbVdsSH8NoRRFExS/ IH7qydzGg5Wm+GAmZVYZGu6r9C9dVp8SyesAxWUNrafJCSaL5IMwN+n/upG73wHcoVAl Vm7u3o3xW1h+vH2Q5IrCtLhZNW37lU0hNhXG6sKigwTNrQiP2B6kKX+GRA2wzzqihboF BkDyQEkOzCwFW6yWMNdzj0KNjXORlcviyGjlX7bINW8NEMEnZEUDN19Smvcw2fZFso2S 8MSTQX388YnSfxAWGw/UhBF3x5B428TunKDrpsrjc+m7g2L2KJ0vwgciL3GlJk9IDWpI b1qQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to :content-language:references:to:from:subject:user-agent:mime-version :date:message-id:sender:hmm_source_type:hmm_attache_num :hmm_source_ip; bh=gqee3DJpWFDB/NcKE8MuuViJ67hCrsWWTzWcuiu1kYI=; b=ThBN0Vht5S3D+Z7an/oLMI7Xun5ZTZfsx6V1CJ+vR+qQbMiQjdIVAyUnVm6ekVoZn+ /xIzB5PNPcM/Vha5do0FXzSoAWrCMS1tliK1lCpM/5162RkCPBkY7Y325lXxlHb6dTYc ZR07n0E3Ut59b7O56QXS8CDJbDEDjyzmPJmbYKJuRCvMOz4InzofetVrEGTQhoRDL/sR eClkoLNxYmcgSlwy4GXbD1lNycJ+q3q44FjEcYmNthiAGaM+F/5qOW3SP1QH7eDGm3yw WUP1BgU5dCxS/4n8eXCelQEVMjVjghF/VSr2twdjK2rbTI3sx1Km7/8ijI1ohmCkjYp1 P4aQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id k7-20020a17090a9d8700b00247447dc4a2si10919316pjp.20.2023.04.18.11.19.23; Tue, 18 Apr 2023 11:19:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229940AbjDRSQy (ORCPT + 99 others); Tue, 18 Apr 2023 14:16:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48014 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229813AbjDRSQw (ORCPT ); Tue, 18 Apr 2023 14:16:52 -0400 Received: from 189.cn (ptr.189.cn [183.61.185.102]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 405DC4ECB; Tue, 18 Apr 2023 11:16:50 -0700 (PDT) HMM_SOURCE_IP: 10.64.8.43:36206.1084606344 HMM_ATTACHE_NUM: 0000 HMM_SOURCE_TYPE: SMTP Received: from clientip-114.242.206.180 (unknown [10.64.8.43]) by 189.cn (HERMES) with SMTP id A4080100567; Wed, 19 Apr 2023 02:16:45 +0800 (CST) Received: from ([114.242.206.180]) by gateway-151646-dep-7b48884fd-tj646 with ESMTP id ce235540f5fb4e348657788457610f7a for maarten.lankhorst@linux.intel.com; Wed, 19 Apr 2023 02:16:48 CST X-Transaction-ID: ce235540f5fb4e348657788457610f7a X-Real-From: 15330273260@189.cn X-Receive-IP: 114.242.206.180 X-MEDUSA-Status: 0 Sender: 15330273260@189.cn Message-ID: <86a8b262-cbf2-b75f-9972-491f557edf74@189.cn> Date: Wed, 19 Apr 2023 02:16:45 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.10.0 Subject: Re: [PATCH v3] drm/fbdev-generic: prohibit potential out-of-bounds access From: Sui Jingfeng <15330273260@189.cn> To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Li Yi , Helge Deller , Lucas De Marchi , linux-kernel@vger.kernel.org, linux-fbdev@vger.kernel.org, dri-devel@lists.freedesktop.org, loongson-kernel@lists.loongnix.cn References: <20230417113219.1354078-1-suijingfeng@loongson.cn> <139c9398-488d-df19-9ae2-2b4b47ef64f4@189.cn> Content-Language: en-US In-Reply-To: <139c9398-488d-df19-9ae2-2b4b47ef64f4@189.cn> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.3 required=5.0 tests=BAYES_00, FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,FROM_LOCAL_DIGITS, FROM_LOCAL_HEX,NICE_REPLY_A,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On 2023/4/19 01:52, Sui Jingfeng wrote: > Hi, > > On 2023/4/18 16:32, Daniel Vetter wrote: >> On Mon, Apr 17, 2023 at 07:32:19PM +0800, Sui Jingfeng wrote: >>> The fbdev test of IGT may write after EOF, which lead to out-of-bound >>> access for the drm drivers using fbdev-generic. For example, on a x86 >>> + aspeed bmc card platform, with a 1680x1050 resolution display, >>> running >>> fbdev test if IGT will cause the linux kernel hang with the following >>> call trace: >>> >>>    Oops: 0000 [#1] PREEMPT SMP PTI >>>    [IGT] fbdev: starting subtest eof >>>    Workqueue: events drm_fb_helper_damage_work [drm_kms_helper] >>>    [IGT] fbdev: starting subtest nullptr >>> >>>    RIP: 0010:memcpy_erms+0xa/0x20 >>>    RSP: 0018:ffffa17d40167d98 EFLAGS: 00010246 >>>    RAX: ffffa17d4eb7fa80 RBX: ffffa17d40e0aa80 RCX: 00000000000014c0 >>>    RDX: 0000000000001a40 RSI: ffffa17d40e0b000 RDI: ffffa17d4eb80000 >>>    RBP: ffffa17d40167e20 R08: 0000000000000000 R09: ffff89522ecff8c0 >>>    R10: ffffa17d4e4c5000 R11: 0000000000000000 R12: ffffa17d4eb7fa80 >>>    R13: 0000000000001a40 R14: 000000000000041a R15: ffffa17d40167e30 >>>    FS:  0000000000000000(0000) GS:ffff895257380000(0000) >>> knlGS:0000000000000000 >>>    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033 >>>    CR2: ffffa17d40e0b000 CR3: 00000001eaeca006 CR4: 00000000001706e0 >>>    Call Trace: >>>     >>>     ? drm_fbdev_generic_helper_fb_dirty+0x207/0x330 [drm_kms_helper] >>>     drm_fb_helper_damage_work+0x8f/0x170 [drm_kms_helper] >>>     process_one_work+0x21f/0x430 >>>     worker_thread+0x4e/0x3c0 >>>     ? __pfx_worker_thread+0x10/0x10 >>>     kthread+0xf4/0x120 >>>     ? __pfx_kthread+0x10/0x10 >>>     ret_from_fork+0x2c/0x50 >>>     >>>    CR2: ffffa17d40e0b000 >>>    ---[ end trace 0000000000000000 ]--- >>> >>> The direct reason is that damage rectange computed by >>> drm_fb_helper_memory_range_to_clip() does not guaranteed to be >>> in-bound. >>> It is already results in workaround code populate to elsewhere. Another >>> reason is that exposing a larger buffer size than the actual needed >>> help >>> to trigger this bug intrinsic in drm_fb_helper_memory_range_to_clip(). >>> >>> Others fbdev emulation solutions write to the GEM buffer directly, they >>> won't reproduce this bug because the .fb_dirty function callback do not >>> being hooked, so no chance is given to >>> drm_fb_helper_memory_range_to_clip() >>> to generate a out-of-bound when drm_fb_helper_sys_write() is called. >>> >>> This patch break the trigger condition of this bug by shrinking the >>> shadow >>> buffer size to sizes->surface_height * buffer->fb->pitches[0]. >>> >>> Fixes: '8fbc9af55de0 ("drm/fbdev-generic: Set screen size to size of >>> GEM >>> buffer")' >>> >>> Signed-off-by: Sui Jingfeng >>> --- >>>   drivers/gpu/drm/drm_fbdev_generic.c | 2 +- >>>   1 file changed, 1 insertion(+), 1 deletion(-) >>> >>> diff --git a/drivers/gpu/drm/drm_fbdev_generic.c >>> b/drivers/gpu/drm/drm_fbdev_generic.c >>> index 8e5148bf40bb..b057cfbba938 100644 >>> --- a/drivers/gpu/drm/drm_fbdev_generic.c >>> +++ b/drivers/gpu/drm/drm_fbdev_generic.c >>> @@ -94,7 +94,7 @@ static int >>> drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper, >>>       fb_helper->buffer = buffer; >>>       fb_helper->fb = buffer->fb; >>>   -    screen_size = buffer->gem->size; >>> +    screen_size = sizes->surface_height * buffer->fb->pitches[0]; >> So I read core some more and stumbled over drm_fb_helper_deferred_io(). >> Which has all the code and comments about this, including limiting. >> >> I think it would be clearer if we fix the issue there, instead of >> passing >> limits around in obscure places that then again get broken? > > No, it is more obscure doing that way... > > > As the size of the shadow screen buffer will be exposed to userspace. > > The size 'helper->fb->height * helper->fb->pitches[0]' is a > exactly(best) fit, > > You are guaranteed to waste at lease one byte by increasing one byte, > > and can not store all pixels by decreasing one byte (In the case where > `helper->fb->pitches[0] = helper->fb->width * 4`). > > It implicitly tell the userspace do not go beyond that boundary. > > although userspace program can still choose to write  after EOF, > > But it is for test purpose, to test the kernel if it can return a > -EFBIG or not. > >> The thing is, >> Thomas both authored the limit checks in drm_fb_helper_deferred_io() and >> the patch which broken them again, so clearly this isn't very >> obvious. I'm >> thinking of something like this: >> >> >> diff --git a/drivers/gpu/drm/drm_fb_helper.c >> b/drivers/gpu/drm/drm_fb_helper.c >> index ef4eb8b12766..726dab67c359 100644 >> --- a/drivers/gpu/drm/drm_fb_helper.c >> +++ b/drivers/gpu/drm/drm_fb_helper.c >> @@ -697,10 +697,7 @@ void drm_fb_helper_deferred_io(struct fb_info >> *info, struct list_head *pagerefli >>        * of the screen and account for non-existing scanlines. Hence, >>        * keep the covered memory area within the screen buffer. >>        */ >> -    if (info->screen_size) >> -        total_size = info->screen_size; >> -    else >> -        total_size = info->fix.smem_len; >> +    total_size = helper->fb->height * helper->fb->pitches[0]; > > This is just to mitigate the mistakes already has been made, > > because it  do not do a good splitting between the *clip* part and the > *damage update* part. > > An ideal clipping do not obscure its updating backend with a > out-of-bound damage rectangle. > > Why did the drm_fb_helper_memory_range_to_clip() can not do a good job > in all case > > to pass its backend a always meaningful damage rect ? > >>       max_off = min(max_off, total_size); >>         if (min_off < max_off) { >> >> >> I think that would make it utmost clear on what we're doing and why. >> Otherwise we're just going to re-create the same bug again, like we've >> done already :-) > > No, we create no bugs, we fix one. > > Thanks. > But honestly I do not have strong feel toward this, I just type what I'm understand without seeing you resend a V3. It's OK in overall,  I will help to test this tomorrow.  :-) >> -Daniel >> >>>       screen_buffer = vzalloc(screen_size); >>>       if (!screen_buffer) { >>>           ret = -ENOMEM; >>> -- >>> 2.25.1 >>>