Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp2833096pxb; Mon, 1 Nov 2021 02:48:08 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzjyVVZKNclZzTwrqeYlmMCwWIdMmqb+WNj2x//ICPUVm1tWkvc80oX/A7trw4OvJ+KVVHI X-Received: by 2002:a05:6602:2dd5:: with SMTP id l21mr3770190iow.87.1635760088123; Mon, 01 Nov 2021 02:48:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1635760088; cv=none; d=google.com; s=arc-20160816; b=ERiesbLZI2s/ivXJew5mx3zSr22nier5bY0QDFK32Rts4ADlJGCzSUevIshAbn6ctG 79nQdfYEjP4fZT7n7jil7A/gr0GNoRF4lgfXcfWnTIIDC/KEogoUleZAuaN1DsCKU1YG 4fNoNo8DdGvwLG8HU17Ottjq2KTyi6orC5G72ltm48vcp/tquOUx3QGosWsm5VeKWvlW xPhGC8K8fptmEy2m8PyEfUtd2JwiwOOrXYRdJkQsO0NgjQmUR9gfuWx9iMF2EnnzHPB/ pPzHspD1wmYKpSW4HY++jwfcAJi+xb0m8pn66Rec5Vd7TpaqlvfP55yVQL3QQv17zmf8 jyrQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=a9hJz+CaeXjr8dWRE0qM12cTMeujZPtahxBMufU9WSo=; b=kZ9ga7pNR3/PIUJIlF1RUvK5JTaFey+eKV8Vlmaa8LtaPEd7qBOvsdPEIQ2NFcY6CE s8qk3cDudeyNTpskqGVxVHW1BPG7bsBtOtE854zY/h7v3zYBs36mRLGAszpBg/+WbXW8 t6FPwXd4zA02h0h9JIVOmttnRkqTiw2upYLc00TZm2toW7EtLZXKExG5vw8MGmlMjDsH Hx27EukaD38qphOLAv6FDWfGHxIGuSRJPEDOGdEH3HfVawdoA26U0/zDN12CyYgJg7ei C1+nizvyTpK6p7EjEWXGycGWEjNrvHynRs9nvSl4bKcbSLhz1P9KFdRO/T8/aw43GNAR GjpQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=SI7fviDP; 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=pass (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 f3si4893583ilu.70.2021.11.01.02.47.56; Mon, 01 Nov 2021 02:48:08 -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=@linuxfoundation.org header.s=korg header.b=SI7fviDP; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232509AbhKAJtP (ORCPT + 99 others); Mon, 1 Nov 2021 05:49:15 -0400 Received: from mail.kernel.org ([198.145.29.99]:47842 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234411AbhKAJom (ORCPT ); Mon, 1 Nov 2021 05:44:42 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id DF8DC613C8; Mon, 1 Nov 2021 09:29:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1635758975; bh=B7NlcoXBbcEdEpxjA4R1Eluq85rgu6AyqC7x2HEKsC0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SI7fviDPpA2FOr8OjatzMviGMjm0JV95AVqsaitoR+nCArzt+N5Vj4H2eR1nh0zMW uIJ9zn+m9wtI566ZbLuYpoHw4xEtiJ460tARZlrLaFojS9puxOmBgN6IMiSTucJHzT MD1PDCaX2gLX+Ws8AmHXjzsxmYGZNhG/rD2Gs7EQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Lorenzo Bianconi , =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= , Alexei Starovoitov Subject: [PATCH 5.14 061/125] bpf: Fix potential race in tail call compatibility check Date: Mon, 1 Nov 2021 10:17:14 +0100 Message-Id: <20211101082544.747102496@linuxfoundation.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211101082533.618411490@linuxfoundation.org> References: <20211101082533.618411490@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Toke Høiland-Jørgensen commit 54713c85f536048e685258f880bf298a74c3620d upstream. Lorenzo noticed that the code testing for program type compatibility of tail call maps is potentially racy in that two threads could encounter a map with an unset type simultaneously and both return true even though they are inserting incompatible programs. The race window is quite small, but artificially enlarging it by adding a usleep_range() inside the check in bpf_prog_array_compatible() makes it trivial to trigger from userspace with a program that does, essentially: map_fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, 4, 4, 2, 0); pid = fork(); if (pid) { key = 0; value = xdp_fd; } else { key = 1; value = tc_fd; } err = bpf_map_update_elem(map_fd, &key, &value, 0); While the race window is small, it has potentially serious ramifications in that triggering it would allow a BPF program to tail call to a program of a different type. So let's get rid of it by protecting the update with a spinlock. The commit in the Fixes tag is the last commit that touches the code in question. v2: - Use a spinlock instead of an atomic variable and cmpxchg() (Alexei) v3: - Put lock and the members it protects into an embedded 'owner' struct (Daniel) Fixes: 3324b584b6f6 ("ebpf: misc core cleanup") Reported-by: Lorenzo Bianconi Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/20211026110019.363464-1-toke@redhat.com Signed-off-by: Greg Kroah-Hartman --- include/linux/bpf.h | 7 +++++-- kernel/bpf/arraymap.c | 1 + kernel/bpf/core.c | 20 +++++++++++++------- kernel/bpf/syscall.c | 6 ++++-- 4 files changed, 23 insertions(+), 11 deletions(-) --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -900,8 +900,11 @@ struct bpf_array_aux { * stored in the map to make sure that all callers and callees have * the same prog type and JITed flag. */ - enum bpf_prog_type type; - bool jited; + struct { + spinlock_t lock; + enum bpf_prog_type type; + bool jited; + } owner; /* Programs with direct jumps into programs part of this array. */ struct list_head poke_progs; struct bpf_map *map; --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -1051,6 +1051,7 @@ static struct bpf_map *prog_array_map_al INIT_WORK(&aux->work, prog_array_map_clear_deferred); INIT_LIST_HEAD(&aux->poke_progs); mutex_init(&aux->poke_mutex); + spin_lock_init(&aux->owner.lock); map = array_map_alloc(attr); if (IS_ERR(map)) { --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -1821,20 +1821,26 @@ static unsigned int __bpf_prog_ret0_warn bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp) { + bool ret; + if (fp->kprobe_override) return false; - if (!array->aux->type) { + spin_lock(&array->aux->owner.lock); + + if (!array->aux->owner.type) { /* There's no owner yet where we could check for * compatibility. */ - array->aux->type = fp->type; - array->aux->jited = fp->jited; - return true; + array->aux->owner.type = fp->type; + array->aux->owner.jited = fp->jited; + ret = true; + } else { + ret = array->aux->owner.type == fp->type && + array->aux->owner.jited == fp->jited; } - - return array->aux->type == fp->type && - array->aux->jited == fp->jited; + spin_unlock(&array->aux->owner.lock); + return ret; } static int bpf_check_tail_call(const struct bpf_prog *fp) --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -543,8 +543,10 @@ static void bpf_map_show_fdinfo(struct s if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) { array = container_of(map, struct bpf_array, map); - type = array->aux->type; - jited = array->aux->jited; + spin_lock(&array->aux->owner.lock); + type = array->aux->owner.type; + jited = array->aux->owner.jited; + spin_unlock(&array->aux->owner.lock); } seq_printf(m,