From nobody Sat Nov 1 07:39:38 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1527137313445952.7993311668679; Wed, 23 May 2018 21:48:33 -0700 (PDT) Received: from localhost ([::1]:36476 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fLiAy-0000Ve-Lg for importer@patchew.org; Thu, 24 May 2018 00:48:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43548) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fLi7c-0006v6-TA for qemu-devel@nongnu.org; Thu, 24 May 2018 00:45:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fLi7b-0002AA-8j for qemu-devel@nongnu.org; Thu, 24 May 2018 00:45:04 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:34436 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fLi7b-0002A1-4v for qemu-devel@nongnu.org; Thu, 24 May 2018 00:45:03 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B1D2A4067F19; Thu, 24 May 2018 04:45:02 +0000 (UTC) Received: from xz-mi.redhat.com (ovpn-12-95.pek2.redhat.com [10.72.12.95]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0330C2166BB2; Thu, 24 May 2018 04:44:59 +0000 (UTC) From: Peter Xu To: qemu-devel@nongnu.org Date: Thu, 24 May 2018 12:44:53 +0800 Message-Id: <20180524044454.11792-2-peterx@redhat.com> In-Reply-To: <20180524044454.11792-1-peterx@redhat.com> References: <20180524044454.11792-1-peterx@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Thu, 24 May 2018 04:45:02 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Thu, 24 May 2018 04:45:02 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'peterx@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v4 1/2] qemu-error: introduce {error|warn}_report_once X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Michael S . Tsirkin" , Jason Wang , Markus Armbruster , peterx@redhat.com, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" There are many error_report()s that can be used in frequently called functions, especially on IO paths. That can be unideal in that malicious guest can try to trigger the error tons of time which might use up the log space on the host (e.g., libvirt can capture the stderr of QEMU and put it persistently onto disk). In VT-d emulation code, we have trace_vtd_error() tracer. AFAIU all those places can be replaced by something like error_report() but trace points are mostly used to avoid the DDOS attack that mentioned above. However using trace points mean that errors are not dumped if trace not enabled. It's not a big deal in most modern server managements since we have things like logrotate to maintain the logs and make sure the quota is expected. However it'll still be nice that we just provide another way to restrict message generations. In most cases, this kind of error_report()s will only provide valid information on the first message sent, and all the rest of similar messages will be mostly talking about the same thing. This patch introduces *_report_once() helpers to allow a message to be dumped only once during one QEMU process's life cycle. It will make sure: (1) it's on by deffault, so we can even get something without turning the trace on and reproducing, and (2) it won't be affected by DDOS attack. To implement it, I stole the printk_once() macro from Linux. CC: Eric Blake CC: Markus Armbruster Signed-off-by: Peter Xu Reviewed-by: Markus Armbruster --- include/qemu/error-report.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h index e1c8ae1a52..c7ec54cb97 100644 --- a/include/qemu/error-report.h +++ b/include/qemu/error-report.h @@ -44,6 +44,38 @@ void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, = 2); void warn_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2); void info_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2); =20 +/* + * Similar to error_report(), but it only prints the message once. It + * returns true when it prints the first time, otherwise false. + */ +#define error_report_once(fmt, ...) \ + ({ \ + static bool print_once_; \ + bool ret_print_once_ =3D !print_once_; \ + \ + if (!print_once_) { \ + print_once_ =3D true; \ + error_report(fmt, ##__VA_ARGS__); \ + } \ + unlikely(ret_print_once_); \ + }) + +/* + * Similar to warn_report(), but it only prints the message once. It + * returns true when it prints the first time, otherwise false. + */ +#define warn_report_once(fmt, ...) \ + ({ \ + static bool print_once_; \ + bool ret_print_once_ =3D !print_once_; \ + \ + if (!print_once_) { \ + print_once_ =3D true; \ + warn_report(fmt, ##__VA_ARGS__); \ + } \ + unlikely(ret_print_once_); \ + }) + const char *error_get_progname(void); extern bool enable_timestamp_msg; =20 --=20 2.17.0 From nobody Sat Nov 1 07:39:38 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1527137188178360.7697385570591; Wed, 23 May 2018 21:46:28 -0700 (PDT) Received: from localhost ([::1]:36468 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fLi8x-0007dP-4t for importer@patchew.org; Thu, 24 May 2018 00:46:27 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43572) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fLi7g-0006xX-LL for qemu-devel@nongnu.org; Thu, 24 May 2018 00:45:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fLi7f-0002BQ-3o for qemu-devel@nongnu.org; Thu, 24 May 2018 00:45:08 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:34442 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fLi7e-0002BE-Uh for qemu-devel@nongnu.org; Thu, 24 May 2018 00:45:07 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 74A9B4067F19; Thu, 24 May 2018 04:45:06 +0000 (UTC) Received: from xz-mi.redhat.com (ovpn-12-95.pek2.redhat.com [10.72.12.95]) by smtp.corp.redhat.com (Postfix) with ESMTP id C1EDE2157F42; Thu, 24 May 2018 04:45:03 +0000 (UTC) From: Peter Xu To: qemu-devel@nongnu.org Date: Thu, 24 May 2018 12:44:54 +0800 Message-Id: <20180524044454.11792-3-peterx@redhat.com> In-Reply-To: <20180524044454.11792-1-peterx@redhat.com> References: <20180524044454.11792-1-peterx@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Thu, 24 May 2018 04:45:06 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Thu, 24 May 2018 04:45:06 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'peterx@redhat.com' RCPT:'' Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v4 2/2] intel-iommu: start to use error_report_once X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Michael S . Tsirkin" , Jason Wang , Markus Armbruster , peterx@redhat.com, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Replace existing trace_vtd_err() with error_report_once() then stderr will capture something if any of the error happens, meanwhile we don't suffer from any DDOS. Then remove the trace point. Since at it, provide more information where proper (now we can pass parameters into the report function). Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Peter Xu --- hw/i386/intel_iommu.c | 59 ++++++++++++++++++++++++------------------- hw/i386/trace-events | 1 - 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index fb31de9416..fa6df921ee 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -285,14 +285,14 @@ static void vtd_generate_fault_event(IntelIOMMUState = *s, uint32_t pre_fsts) { if (pre_fsts & VTD_FSTS_PPF || pre_fsts & VTD_FSTS_PFO || pre_fsts & VTD_FSTS_IQE) { - trace_vtd_err("There are previous interrupt conditions " - "to be serviced by software, fault event " - "is not generated."); + error_report_once("There are previous interrupt conditions " + "to be serviced by software, fault event " + "is not generated"); return; } vtd_set_clear_mask_long(s, DMAR_FECTL_REG, 0, VTD_FECTL_IP); if (vtd_get_long_raw(s, DMAR_FECTL_REG) & VTD_FECTL_IM) { - trace_vtd_err("Interrupt Mask set, irq is not generated."); + error_report_once("Interrupt Mask set, irq is not generated"); } else { vtd_generate_interrupt(s, DMAR_FEADDR_REG, DMAR_FEDATA_REG); vtd_set_clear_mask_long(s, DMAR_FECTL_REG, VTD_FECTL_IP, 0); @@ -400,20 +400,20 @@ static void vtd_report_dmar_fault(IntelIOMMUState *s,= uint16_t source_id, trace_vtd_dmar_fault(source_id, fault, addr, is_write); =20 if (fsts_reg & VTD_FSTS_PFO) { - trace_vtd_err("New fault is not recorded due to " - "Primary Fault Overflow."); + error_report_once("New fault is not recorded due to " + "Primary Fault Overflow"); return; } =20 if (vtd_try_collapse_fault(s, source_id)) { - trace_vtd_err("New fault is not recorded due to " - "compression of faults."); + error_report_once("New fault is not recorded due to " + "compression of faults"); return; } =20 if (vtd_is_frcd_set(s, s->next_frcd_reg)) { - trace_vtd_err("Next Fault Recording Reg is used, " - "new fault is not recorded, set PFO field."); + error_report_once("Next Fault Recording Reg is used, " + "new fault is not recorded, set PFO field"); vtd_set_clear_mask_long(s, DMAR_FSTS_REG, 0, VTD_FSTS_PFO); return; } @@ -421,8 +421,8 @@ static void vtd_report_dmar_fault(IntelIOMMUState *s, u= int16_t source_id, vtd_record_frcd(s, s->next_frcd_reg, source_id, addr, fault, is_write); =20 if (fsts_reg & VTD_FSTS_PPF) { - trace_vtd_err("There are pending faults already, " - "fault event is not generated."); + error_report_once("There are pending faults already, " + "fault event is not generated"); vtd_set_frcd_and_update_ppf(s, s->next_frcd_reg); s->next_frcd_reg++; if (s->next_frcd_reg =3D=3D DMAR_FRCD_REG_NR) { @@ -1339,7 +1339,8 @@ static uint64_t vtd_context_cache_invalidate(IntelIOM= MUState *s, uint64_t val) break; =20 default: - trace_vtd_err("Context cache invalidate type error."); + error_report_once("%s: invalid context: 0x%"PRIx64, + __func__, val); caig =3D 0; } return caig; @@ -1445,7 +1446,8 @@ static uint64_t vtd_iotlb_flush(IntelIOMMUState *s, u= int64_t val) am =3D VTD_IVA_AM(addr); addr =3D VTD_IVA_ADDR(addr); if (am > VTD_MAMV) { - trace_vtd_err("IOTLB PSI flush: address mask overflow."); + error_report_once("%s: address mask overflow: 0x%"PRIx64, + __func__, vtd_get_quad_raw(s, DMAR_IVA_REG)); iaig =3D 0; break; } @@ -1454,7 +1456,8 @@ static uint64_t vtd_iotlb_flush(IntelIOMMUState *s, u= int64_t val) break; =20 default: - trace_vtd_err("IOTLB flush: invalid granularity."); + error_report_once("%s: invalid granularity: 0x%"PRIx64, + __func__, val); iaig =3D 0; } return iaig; @@ -1604,8 +1607,8 @@ static void vtd_handle_ccmd_write(IntelIOMMUState *s) /* Context-cache invalidation request */ if (val & VTD_CCMD_ICC) { if (s->qi_enabled) { - trace_vtd_err("Queued Invalidation enabled, " - "should not use register-based invalidation"); + error_report_once("Queued Invalidation enabled, " + "should not use register-based invalidation"= ); return; } ret =3D vtd_context_cache_invalidate(s, val); @@ -1625,8 +1628,8 @@ static void vtd_handle_iotlb_write(IntelIOMMUState *s) /* IOTLB invalidation request */ if (val & VTD_TLB_IVT) { if (s->qi_enabled) { - trace_vtd_err("Queued Invalidation enabled, " - "should not use register-based invalidation."); + error_report_once("Queued Invalidation enabled, " + "should not use register-based invalidation"= ); return; } ret =3D vtd_iotlb_flush(s, val); @@ -1644,7 +1647,7 @@ static bool vtd_get_inv_desc(dma_addr_t base_addr, ui= nt32_t offset, dma_addr_t addr =3D base_addr + offset * sizeof(*inv_desc); if (dma_memory_read(&address_space_memory, addr, inv_desc, sizeof(*inv_desc))) { - trace_vtd_err("Read INV DESC failed."); + error_report_once("Read INV DESC failed"); inv_desc->lo =3D 0; inv_desc->hi =3D 0; return false; @@ -1999,7 +2002,8 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr add= r, unsigned size) trace_vtd_reg_read(addr, size); =20 if (addr + size > DMAR_REG_SIZE) { - trace_vtd_err("Read MMIO over range."); + error_report_once("%s: MMIO over range: addr=3D0x%"PRIx64 + " size=3D0x%u", __func__, addr, size); return (uint64_t)-1; } =20 @@ -2050,7 +2054,8 @@ static void vtd_mem_write(void *opaque, hwaddr addr, trace_vtd_reg_write(addr, size, val); =20 if (addr + size > DMAR_REG_SIZE) { - trace_vtd_err("Write MMIO over range."); + error_report_once("%s: MMIO over range: addr=3D0x%"PRIx64 + " size=3D0x%u", __func__, addr, size); return; } =20 @@ -2432,7 +2437,8 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint1= 6_t index, addr =3D iommu->intr_root + index * sizeof(*entry); if (dma_memory_read(&address_space_memory, addr, entry, sizeof(*entry))) { - trace_vtd_err("Memory read failed for IRTE."); + error_report_once("%s: read failed: ind=3D0x%"PRIu16 + " addr=3D0x%"PRIx64, __func__, index, addr); return -VTD_FR_IR_ROOT_INVAL; } =20 @@ -2564,14 +2570,15 @@ static int vtd_interrupt_remap_msi(IntelIOMMUState = *iommu, } =20 if (origin->address & VTD_MSI_ADDR_HI_MASK) { - trace_vtd_err("MSI address high 32 bits non-zero when " - "Interrupt Remapping enabled."); + error_report_once("%s: MSI address high 32 bits non-zero detected:= " + "address=3D0x%"PRIx64, __func__, origin->address= ); return -VTD_FR_IR_REQ_RSVD; } =20 addr.data =3D origin->address & VTD_MSI_ADDR_LO_MASK; if (addr.addr.__head !=3D 0xfee) { - trace_vtd_err("MSI addr low 32 bit invalid."); + error_report_once("%s: MSI address low 32 bit invalid: 0x%"PRIx32, + __func__, addr.data); return -VTD_FR_IR_REQ_RSVD; } =20 diff --git a/hw/i386/trace-events b/hw/i386/trace-events index 22d44648af..e08cf2a9a7 100644 --- a/hw/i386/trace-events +++ b/hw/i386/trace-events @@ -68,7 +68,6 @@ vtd_ir_remap_msi_req(uint64_t addr, uint64_t data) "addr = 0x%"PRIx64" data 0x%"PR vtd_fsts_ppf(bool set) "FSTS PPF bit set to %d" vtd_fsts_clear_ip(void) "" vtd_frr_new(int index, uint64_t hi, uint64_t lo) "index %d high 0x%"PRIx64= " low 0x%"PRIx64 -vtd_err(const char *str) "%s" vtd_err_dmar_iova_overflow(uint64_t iova) "iova 0x%"PRIx64 vtd_err_dmar_slpte_read_error(uint64_t iova, int level) "iova 0x%"PRIx64" = level %d" vtd_err_dmar_slpte_perm_error(uint64_t iova, int level, uint64_t slpte, bo= ol is_write) "iova 0x%"PRIx64" level %d slpte 0x%"PRIx64" write %d" --=20 2.17.0