Received: by 2002:a9a:4c47:0:b029:116:c383:538 with SMTP id u7csp1178773lko; Tue, 13 Jul 2021 18:55:29 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwSVbmlVdfRR6Wpror4xnr8/A2i2pZpZfix9rhmY7M5dxy5B1I+8dzRA91jK1lLLg2vrnlM X-Received: by 2002:a05:6e02:c87:: with SMTP id b7mr5013106ile.210.1626227729571; Tue, 13 Jul 2021 18:55:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1626227729; cv=none; d=google.com; s=arc-20160816; b=EFnNLKk6PvY8ujGC9PhWyL4/Zt/gLXSeQhi5REsRXe4UYM5lo0iOp2IMMnKWfEYcKD TNjU5Cm15O1Tp0xsnI8wP7ZqhqFTT0tKbTZ2ugUd20/q8T8tIufU5GeTy6Ob0it4JqLz uD/KNEsrjaZnYJQy2uvLGh4mjHD4idotKFZqiCk+lPGikune9Az+p1c81REPc+zOc+i0 iMlBU1hcvK/TU9BbHxgxAi3XDjEH8mMo2lxjO8UNLyDrDGUnt2DGfeSCX38L/tMbdGnE XicoPANwqBUiNMG9QNCpGEShlx+h3CInCSgT1XBzig7gKPxfp9eLYf8oHOfXRX26F8G2 2D3Q== 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 :mime-version:user-agent:date:message-id:from:references:cc:to :subject; bh=5dFH0UHYiBQr04sYR0QYZV/CypxUyYFCqWI4xDfVngM=; b=mX29EjD10mWXIsZjPSjyrDK8zs5GQ9Pq4mHQjd0FHYvvXtArN4+Kmgxe+FRykyooQr 0pQ+mawctagrGIR9gYowicdUyd2um+8sPsg1Bmbbr6lOn0kb9F4fG5WQrWTIX6SKBei+ iCTOPbdIB/ONYFF02qpz+aQYc1kKz5XMH4wAs2xOivcZGoFjzgIGygp1x+el8qrJRSE9 hGVmoz05SezR7BppVe6+JO3Q8m9c5c3GioDeKitRA9nal6Sg77O/eWrup7D6gHE2K6mf qqdXei7AYCdgcOC0EjrwyL+6rf9LFZLmjiyGUENccbipThrzsVX+T8RZAcpGQZ2oU8Gq WbsA== ARC-Authentication-Results: i=1; mx.google.com; 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=huawei.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id o192si942756jao.55.2021.07.13.18.55.05; Tue, 13 Jul 2021 18:55:29 -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; 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=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237374AbhGNB4l (ORCPT + 99 others); Tue, 13 Jul 2021 21:56:41 -0400 Received: from szxga03-in.huawei.com ([45.249.212.189]:11298 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229843AbhGNB4k (ORCPT ); Tue, 13 Jul 2021 21:56:40 -0400 Received: from dggeme751-chm.china.huawei.com (unknown [172.30.72.57]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4GPgR26GCCz8sd4; Wed, 14 Jul 2021 09:49:18 +0800 (CST) Received: from [10.67.110.55] (10.67.110.55) by dggeme751-chm.china.huawei.com (10.3.19.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2176.2; Wed, 14 Jul 2021 09:53:46 +0800 Subject: Re: [bpf-next 3/3] bpf: Fix a use after free in bpf_check() To: Alexei Starovoitov CC: Song Liu , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , "David S . Miller" , Jakub Kicinski , Networking , bpf , open list References: <20210707043811.5349-1-hefengqing@huawei.com> <20210707043811.5349-4-hefengqing@huawei.com> <1c5b393d-6848-3d10-30cf-7063a331f76c@huawei.com> <21d8cd9e-487e-411f-1cfd-67cebc86b221@huawei.com> From: He Fengqing Message-ID: Date: Wed, 14 Jul 2021 09:53:46 +0800 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.7.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset="utf-8"; format=flowed Content-Transfer-Encoding: 8bit X-Originating-IP: [10.67.110.55] X-ClientProxiedBy: dggeme713-chm.china.huawei.com (10.1.199.109) To dggeme751-chm.china.huawei.com (10.3.19.97) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 在 2021/7/14 7:17, Alexei Starovoitov 写道: > On Sun, Jul 11, 2021 at 7:17 PM He Fengqing wrote: >> >> >> >> 在 2021/7/9 23:12, Alexei Starovoitov 写道: >>> On Fri, Jul 9, 2021 at 4:11 AM He Fengqing wrote: >>>> >>>> >>>> >>>> 在 2021/7/8 11:09, Alexei Starovoitov 写道: >>>>> On Wed, Jul 7, 2021 at 8:00 PM He Fengqing wrote: >>>>>> >>>>>> Ok, I will change this in next version. >>>>> >>>>> before you spam the list with the next version >>>>> please explain why any of these changes are needed? >>>>> I don't see an explanation in the patches and I don't see a bug in the code. >>>>> Did you check what is the prog clone ? >>>>> When is it constructed? Why verifier has anything to do with it? >>>>> . >>>>> >>>> >>>> >>>> I'm sorry, I didn't describe these errors clearly. >>>> >>>> bpf_check(bpf_verifier_env) >>>> | >>>> |->do_misc_fixups(env) >>>> | | >>>> | |->bpf_patch_insn_data(env) >>>> | | | >>>> | | |->bpf_patch_insn_single(env->prog) >>>> | | | | >>>> | | | |->bpf_prog_realloc(env->prog) >>>> | | | | | >>>> | | | | |->construct new_prog >>>> | | | | | free old_prog(env->prog) >>>> | | | | | >>>> | | | | |->return new_prog; >>>> | | | | >>>> | | | |->return new_prog; >>>> | | | >>>> | | |->adjust_insn_aux_data >>>> | | | | >>>> | | | |->return ENOMEM; >>>> | | | >>>> | | |->return NULL; >>>> | | >>>> | |->return ENOMEM; >>>> >>>> bpf_verifier_env->prog had been freed in bpf_prog_realloc function. >>>> >>>> >>>> There are two errors here, the first is memleak in the >>>> bpf_patch_insn_data function, and the second is use after free in the >>>> bpf_check function. >>>> >>>> memleak in bpf_patch_insn_data: >>>> >>>> Look at the call chain above, if adjust_insn_aux_data function return >>>> ENOMEM, bpf_patch_insn_data will return NULL, but we do not free the >>>> new_prog. >>>> >>>> So in the patch 2, before bpf_patch_insn_data return NULL, we free the >>>> new_prog. >>>> >>>> use after free in bpf_check: >>>> >>>> If bpf_patch_insn_data function return NULL, we will not assign new_prog >>>> to the bpf_verifier_env->prog, but bpf_verifier_env->prog has been freed >>>> in the bpf_prog_realloc function. Then in bpf_check function, we will >>>> use bpf_verifier_env->prog after do_misc_fixups function. >>>> >>>> In the patch 3, I added a free_old parameter to bpf_prog_realloc, in >>>> this scenario we don't free old_prog. Instead, we free it in the >>>> do_misc_fixups function when bpf_patch_insn_data return a valid new_prog. >>> >>> Thanks for explaining. >>> Why not to make adjust_insn_aux_data() in bpf_patch_insn_data() first then? >>> Just changing the order will resolve both issues, no? >>> . >>> >> adjust_insn_aux_data() need the new constructed new_prog as an input >> parameter, so we must call bpf_patch_insn_single() before >> adjust_insn_aux_data(). > > Right. I forgot about insn_has_def32() logic and > commit b325fbca4b13 ("bpf: verifier: mark patched-insn with > sub-register zext flag") > that added that extra parameter. > >> But we can make adjust_insn_aux_data() never return ENOMEM. In >> bpf_patch_insn_data(), first we pre-malloc memory for new aux_data, then >> call bpf_patch_insn_single() to constructed the new_prog, at last call >> adjust_insn_aux_data() functin. In this way, adjust_insn_aux_data() >> never fails. >> >> bpf_patch_insn_data(env) { >> struct bpf_insn_aux_data *new_data = vzalloc(); >> struct bpf_prog *new_prog; >> if (new_data == NULL) >> return NULL; >> >> new_prog = bpf_patch_insn_single(env->prog); >> if (new_prog == NULL) { >> vfree(new_data); >> return NULL; >> } >> >> adjust_insn_aux_data(new_prog, new_data); >> return new_prog; >> } >> What do you think about it? > > That's a good idea. Let's do that. The new size for vzalloc is easy to compute. > What should be the commit in the Fixes tag? > commit 8041902dae52 ("bpf: adjust insn_aux_data when patching insns") > right? Ok, I will add this in the commit message. > 4 year old bug then. > I wonder why syzbot with malloc error injection didn't catch it sooner. > . >