From nobody Thu Apr 25 00:33:15 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1678969289; cv=none; d=zohomail.com; s=zohoarc; b=dVkSW+Bm3o0gSuTZPlwPXhN0AvR46J1G4l9mg58VcToDHUwPlZQ2EzeCVU991KSkCmWVOSpFFTxp0cjrlDzvAHKIDlK2TCHzFXX78604CN3EPy+AgHBPijNU7ox0tH0ZcwgyOiEkqvep3zzAKGmW9ZbW9i4vp0MyQ3k1fF7J/t8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1678969289; h=Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject; bh=aiFE+JXZjnXVcnflnkzhrmIYOBgtl1lEZX6c1WWpjbM=; b=XDc882zPN0wZ+OWdHc7PclRO8qgBF/91kxz3EqWktMAoly/1nCB7di8LE17BDurSR8y5SBRrCmJMPz80O2NaQHMgOtcrgVMxOchfuBJLqkneP0VS3Szv5oGDUKNdacDZa/cM2MkhGK95Po0ZBErdt/rFjIamShJ4PMH00R48k8s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1678969289770706.6449823353702; Thu, 16 Mar 2023 05:21:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pcmbW-0002yv-7e; Thu, 16 Mar 2023 08:21:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pcmbU-0002yj-SA for qemu-devel@nongnu.org; Thu, 16 Mar 2023 08:21:08 -0400 Received: from mail-pj1-x102a.google.com ([2607:f8b0:4864:20::102a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pcmbS-0000rS-0k for qemu-devel@nongnu.org; Thu, 16 Mar 2023 08:21:08 -0400 Received: by mail-pj1-x102a.google.com with SMTP id gp15-20020a17090adf0f00b0023d1bbd9f9eso5210639pjb.0 for ; Thu, 16 Mar 2023 05:21:05 -0700 (PDT) Received: from alarm.flets-east.jp ([2400:4050:a840:1e00:4457:c267:5e09:481b]) by smtp.gmail.com with ESMTPSA id p11-20020a1709026b8b00b001a042f532cfsm5506555plk.27.2023.03.16.05.21.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Mar 2023 05:21:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20210112.gappssmtp.com; s=20210112; t=1678969264; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=aiFE+JXZjnXVcnflnkzhrmIYOBgtl1lEZX6c1WWpjbM=; b=SEHjaEU2vvcqaFxu2ooFiV3Ui8GGxK43UV7zW7yGJkRgJAHMetuI0pIEtzosoYoxT/ TEf0aMbYCM7Qsk+XchfqgW7z6tYQc1qdEKdrMeRSblE7NFbMk9Pa50XbdvFhkx7Mmqhz vAW2j7EkCgVJBBEE9K6EKY0aJ65Kj+IJsuAgyQ3aljv6nlNRhRlQXzkLWnpDwP5YW9J1 pXhMC7YdClsqIFyFX0p92zeoNb+2EL+GWwt1S8m1fbN1ZBqHQYtD8db0FTnn8+Iay6UN OUx5jglCry4vhtq9iqpllWtGxAXitb0D4roohL+V5xQvEQBJsnyeB+EnUMKrYhnzcPc/ eQnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678969264; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=aiFE+JXZjnXVcnflnkzhrmIYOBgtl1lEZX6c1WWpjbM=; b=GYKTjsKv+YD2dzUXRUELQjh4ilKZRwIDgijtRyr0M+6Yv5ZbhWy8CKc97A0vnfZOfW I8K+NWHCO0R6P+8DUiUKJt4FlKsUnuYljqo7SpznLb+TOJoJ4F8kuzXN/3lwF9sssbqa eXuF4N8TOeEkiYlkV1lvfjKcjw3/9RwOYGHwEC848cJq0k65MwdUzM7H9oJVw4/DPg35 BN/7PL/MwiRde13C3llvVgLBhPGdz4R3OMLKKqQ7Kb+nogD8HfY55amNWSIoKGYB+hLl ApZqt2qllYsARhZ/a+GPritH3XqEQGWx/vbEPFwIw+wl5tOrYib3+Mxoyx2XCpxs706+ HI+w== X-Gm-Message-State: AO0yUKVrFKEbF7l8CtiuvSIBrMbzEGmG23rEWfpDl+tP/Xw+kCs9qpAT yEpZF2gWhr2Cyo/WpkjKkICPAs7a1i3aeZdRCUg7Tg== X-Google-Smtp-Source: AK7set+8XSB+4mUJoRrwCqwP0R1+z5+ZZXDp9mkl6BttGQhZSOAx/U4P+Jngcd3m2eq7Wey1wRuG4Q== X-Received: by 2002:a17:903:6c5:b0:1a0:5bb1:3f0a with SMTP id kj5-20020a17090306c500b001a05bb13f0amr2908639plb.47.1678969264016; Thu, 16 Mar 2023 05:21:04 -0700 (PDT) From: Akihiko Odaki To: Cc: qemu-devel@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , David Hildenbrand , Peter Xu , Paolo Bonzini , Alexander Bulekov , Akihiko Odaki Subject: [PATCH for 8.0] memory: Prevent recursive memory access Date: Thu, 16 Mar 2023 21:20:45 +0900 Message-Id: <20230316122045.8896-1-akihiko.odaki@daynix.com> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=2607:f8b0:4864:20::102a; envelope-from=akihiko.odaki@daynix.com; helo=mail-pj1-x102a.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @daynix-com.20210112.gappssmtp.com) X-ZM-MESSAGEID: 1678969291044100001 Content-Type: text/plain; charset="utf-8" A guest may request ask a memory-mapped device to perform DMA. If the address specified for DMA is the device performing DMA, it will create recursion. It is very unlikely that device implementations are prepared for such an abnormal access, which can result in unpredictable behavior. In particular, such a recursion breaks e1000e, a network device. If the device is configured to write the received packet to the register to trigger receiving, it triggers re-entry to the Rx logic of e1000e. This causes use-after-free since the Rx logic is not re-entrant. As there should be no valid reason to perform recursive memory access, check for recursion before accessing memory-mapped device. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1543 Signed-off-by: Akihiko Odaki --- softmmu/memory.c | 79 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 17 deletions(-) diff --git a/softmmu/memory.c b/softmmu/memory.c index 4699ba55ec..0743aff3d3 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -50,6 +50,10 @@ static QTAILQ_HEAD(, AddressSpace) address_spaces =20 static GHashTable *flat_views; =20 +static const Object **accessed_region_owners; +static size_t accessed_region_owners_capacity; +static size_t accessed_region_owners_num; + typedef struct AddrRange AddrRange; =20 /* @@ -1394,6 +1398,16 @@ bool memory_region_access_valid(MemoryRegion *mr, return false; } =20 + for (size_t i =3D 0; i < accessed_region_owners_num; i++) { + if (accessed_region_owners[i] =3D=3D mr->owner) { + qemu_log_mask(LOG_GUEST_ERROR, "Invalid %s at addr 0x%" HWADDR= _PRIX + ", size %u, region '%s', reason: recursive acces= s\n", + is_write ? "write" : "read", + addr, size, memory_region_name(mr)); + return false; + } + } + /* Treat zero as compatibility all valid */ if (!mr->ops->valid.max_access_size) { return true; @@ -1413,6 +1427,34 @@ bool memory_region_access_valid(MemoryRegion *mr, return true; } =20 +static bool memory_region_access_start(MemoryRegion *mr, + hwaddr addr, + unsigned size, + bool is_write, + MemTxAttrs attrs) +{ + if (!memory_region_access_valid(mr, addr, size, is_write, attrs)) { + return false; + } + + accessed_region_owners_num++; + if (accessed_region_owners_num >=3D accessed_region_owners_capacity) { + accessed_region_owners_capacity =3D accessed_region_owners_num; + accessed_region_owners =3D g_realloc_n(accessed_region_owners, + accessed_region_owners_num, + sizeof(*accessed_region_owner= s)); + } + + accessed_region_owners[accessed_region_owners_num - 1] =3D mr->owner; + + return true; +} + +static void memory_region_access_end(void) +{ + accessed_region_owners_num--; +} + static MemTxResult memory_region_dispatch_read1(MemoryRegion *mr, hwaddr addr, uint64_t *pval, @@ -1450,12 +1492,13 @@ MemTxResult memory_region_dispatch_read(MemoryRegio= n *mr, mr->alias_offset + addr, pval, op, attrs); } - if (!memory_region_access_valid(mr, addr, size, false, attrs)) { + if (!memory_region_access_start(mr, addr, size, false, attrs)) { *pval =3D unassigned_mem_read(mr, addr, size); return MEMTX_DECODE_ERROR; } =20 r =3D memory_region_dispatch_read1(mr, addr, pval, size, attrs); + memory_region_access_end(); adjust_endianness(mr, pval, op); return r; } @@ -1493,13 +1536,14 @@ MemTxResult memory_region_dispatch_write(MemoryRegi= on *mr, MemTxAttrs attrs) { unsigned size =3D memop_size(op); + MemTxResult result; =20 if (mr->alias) { return memory_region_dispatch_write(mr->alias, mr->alias_offset + addr, data, op, attrs); } - if (!memory_region_access_valid(mr, addr, size, true, attrs)) { + if (!memory_region_access_start(mr, addr, size, true, attrs)) { unassigned_mem_write(mr, addr, data, size); return MEMTX_DECODE_ERROR; } @@ -1508,23 +1552,24 @@ MemTxResult memory_region_dispatch_write(MemoryRegi= on *mr, =20 if ((!kvm_eventfds_enabled()) && memory_region_dispatch_write_eventfds(mr, addr, data, size, attrs)= ) { - return MEMTX_OK; - } - - if (mr->ops->write) { - return access_with_adjusted_size(addr, &data, size, - mr->ops->impl.min_access_size, - mr->ops->impl.max_access_size, - memory_region_write_accessor, mr, - attrs); + result =3D MEMTX_OK; + } else if (mr->ops->write) { + result =3D access_with_adjusted_size(addr, &data, size, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_write_accessor, m= r, + attrs); } else { - return - access_with_adjusted_size(addr, &data, size, - mr->ops->impl.min_access_size, - mr->ops->impl.max_access_size, - memory_region_write_with_attrs_acces= sor, - mr, attrs); + result =3D access_with_adjusted_size(addr, &data, size, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_write_with_attrs_= accessor, + mr, attrs); } + + memory_region_access_end(); + + return result; } =20 void memory_region_init_io(MemoryRegion *mr, --=20 2.39.2