From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C70E3B2FE7 for ; Mon, 10 Aug 2026 22:28:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786400882; cv=none; b=F6c3agYkbjq/sVm8Y6e6XWxYM9Tw33+5mgrmFfrmWxIhGKAqsFNrY2q9gVXK54l0kiYpRkhnaLuqyG0RRj4nk9Ji7Az1euWzgsxYb36yZwxume0O9OYQg66LEWjH0vSd8saekpKsh2dDhEJMtU6a+6tiGBMer27KJRIiEoI5uMc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786400882; c=relaxed/simple; bh=ocpeLQwBB2IKGxQapgMf/muYO0QsC5x7yDT2DqMNh1I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K91CXaFH/kUg6rkew82Q9TJcgcg1H4nGR69/4xTE7QhGbUjcz/zwR8u7zMvHrh9qc03CMFe57lWxB3JcUwKEmrcr5SsRrC0k1kylG/faXoPtrH1Kl8KiMO5Uy0L0x1hhtfZvopTMZgD8kXgImTDIciDjzXCmCIYf1dLcp6WkkWM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=FW68crmj; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FW68crmj" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-2d004f135b1so2465095ad.3 for ; Mon, 10 Aug 2026 15:28:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786400880; x=1787005680; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=EoJvKfC835hK+lVOdLfMGNXk8KCDAst2Mgrk/StD0vQ=; b=FW68crmjBpYp4r9ZGIStHFTd4J6tQOd7Y7oN/E7y2EiMbaM5EV4e0UEbYk+PIDgglV XYHDw/P/h2dfJiSFQu4eqxBo5TOtNOIe3S9hUtKhcBUbp5ZqgXubTV5Wds/Xe3XPpv4L DO0jXICvKCm/vm5ET3PK9jV5EAPB/zdjgIqNulgRmjh9r6f29tvmz/osGU+MkYU1nL9D zLAmYkKwfcLL1BQFM2YUehdP0CZLFheOTnen9ASJaHcWiRo7rJ1bbLplO2hHtyIiZbhg KQNRb/sRPUW4Tnms+wAT76simmGrjoXxRFNMpr3Jw0MMkOm347BvB2FuQKpJaQESAg5n wfwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786400880; x=1787005680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=EoJvKfC835hK+lVOdLfMGNXk8KCDAst2Mgrk/StD0vQ=; b=KcUaz6caj2QGeWrsO6krZM//aYD8JJwkbagBB3qR7F0/yEN6MR1Zxb5LBl/305Fbzd M8PRqbZx6I4+1ipmCruyXirnJ4TQeHyO1B6TfaaKDm0bl66pmG6GmSWUYRWcMMZPXw3i jRzne7AsoPtYrOoPbay0qX1aR9XNQFMonQuQCD7LV7urt+jZlv9Enf3I47Pn+3eRkBLE BTydb/cvKJ+ZBsplfHUbsXcA43axpR8mp7ecvEqflAmxXAgYTCkdn5MdY0cSeQFbit12 mmxH+WHvleIGqo/nsqxKphGRAJxshbhN/VtIemamKt4lzBb4ZiIyN0yiLSLVOdJC3iC7 lI8A== X-Forwarded-Encrypted: i=1; AHgh+RqYuHR05EpUv0YfsDMVZ8UwBURs0vI8H1d+Eytehdl8Z3CvWmlp/me4QLrlabmfc+BygsMtQYPMc69GWI0=@vger.kernel.org X-Gm-Message-State: AOJu0YysNra2b5Jhn44O+01Xml/po95n7ktZsbzMOUtPasEjC4rnkFGl 9ACVQZvc96GQvUTLR3xXHgXErcpZjSp45osyZYsGO4fS6Sn/hmWC+5Kp X-Gm-Gg: AR+sD13zd7NSb9WNHBqDBt2gHV3G5lHT+A0o6wxHctTl0nk0Gq7eP210FENSOmr36Vc Ky8o7Ce4sFyX+r8lKcCYv/CKgMbZHHRwQQQsFcQ5SkYvnPIVqRtXvstcn49ifUwNnmmTKDfCdrj L0XE9qxwUbQTD9n7X2Wq+jTWevRBEaGpSyDJtVOyi0+YKuFDli648M0VtlcrtvvHExaV4bb8H3j QfctXCXOhns1RLHWKk1Eq5pRPE78GIS1TE25Mt9Vj6wNaGDxzbK5SFMtCpVl/k2X0kc1Tw5tRT0 OTjlait9lHzEXJoOHt3ABc6cPv7QyjWmxiEMh186F0S8DcpHnkcd684jpffm43s44GYchgp+Crk iW3fQIuJqSsQly2Nb3h/e1wsbh4PD5UJR0Iq3lPFDecw6y+xCWDUrPXKHi8Ta1SLHduRRepik2/ AJe2BMIDDGs/sGuowK3BukM10v2B291FJ53TYpEQrNn/28QiUwXZukzcwvvOmzzChRwVQLcCdgL OSMtsLCYz1XRSXuIQxtshKrOrjWQFx3CAHlIIfoF+2P3uaZaQo/RXM5EeJV X-Received: by 2002:a17:902:e94c:b0:2c8:4c29:afeb with SMTP id d9443c01a7336-2d0ca7b5520mr594494185ad.8.1786400879796; Mon, 10 Aug 2026 15:27:59 -0700 (PDT) Received: from bloom.localdomain ([2604:3d09:178e:e100::6868]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d15ecf2496sm40870595ad.58.2026.08.10.15.27.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Aug 2026 15:27:58 -0700 (PDT) From: Ivy Lopez To: aacraid@microsemi.com, James.Bottomley@HansenPartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org, Ivy Lopez Subject: [PATCH v2] scsi: aacraid: fix DMA mapping leak in aac_send_raw_srb() Date: Mon, 10 Aug 2026 16:27:38 -0600 Message-ID: <20260810222738.26278-1-skunkolee@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260809033449.286233-1-skunkolee@gmail.com> References: <20260809033449.286233-1-skunkolee@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit aac_send_raw_srb() maps each scatter/gather entry for DMA via dma_map_single() across five separate code paths, depending on the adapter type and SG format (native HBA, 64-bit host SG, 32-bit host SG, and two legacy formats). None of these mappings are ever undone: there is no dma_unmap_single() call anywhere in the file, on the success path or any of the error paths that funnel through the single cleanup label. Every FSACTL_SEND_RAW_SRB ioctl that submits at least one SG entry therefore leaks that many DMA mappings permanently. Under an IOMMU or SWIOTLB this is a genuinely exhaustible resource: sustained use (e.g. periodic smartctl -d aacraid,... polling) eventually drives new DMA mappings to fail, surfacing as intermittent I/O failures (aac_fib_send failing with -ENOMEM) and, left long enough, adapter resets and system instability. Fix this by tracking the DMA address returned from each of the five dma_map_single() calls in a new per-entry array (sg_addr[]). Each entry is initialized to DMA_MAPPING_ERROR and checked with dma_mapping_error() immediately after mapping, bailing out to cleanup on failure rather than using a possibly-error address. Entries are unmapped exactly once: for SRB_DataIn (hardware writes via DMA), each entry is unmapped immediately before its copy_to_user() in the existing per-entry loop, since on non-coherent architectures dma_unmap_single() performs the cache invalidation needed before the CPU can safely read what the device wrote; unmapping only later in cleanup, after that read, could return stale pre-DMA-completion data to userspace. Entries handled this way are marked DMA_MAPPING_ERROR again so cleanup does not unmap them a second time. All other entries (SRB_DataOut-only, or any entry on an error path that never reaches the DataIn copy loop) are unmapped once in cleanup, guarded by the same sentinel check. v1 of this patch used 0 as the "unmapped" sentinel and unmapped every entry only in cleanup, after any copy_to_user() had already read from it. Both were wrong: 0 is a valid DMA address on some platforms (DMA_MAPPING_ERROR is ~(dma_addr_t)0, not 0), so a mapping that legitimately returned address 0 would never be unmapped; and unmapping only in cleanup meant SRB_DataIn transfers could read stale, not-yet-cache-invalidated data on non-coherent architectures. Both issues were caught in review by an automated reviewer (Sashiko AI) on the v1 submission. Link: https://bugzilla.kernel.org/show_bug.cgi?id=220504 Signed-off-by: Ivy Lopez --- drivers/scsi/aacraid/commctrl.c | 43 +++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index bd82aeb679ae..27482d98c6fd 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -492,6 +492,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) u32 data_dir; void __user *sg_user[HBA_MAX_SG_EMBEDDED]; void *sg_list[HBA_MAX_SG_EMBEDDED]; + dma_addr_t sg_addr[HBA_MAX_SG_EMBEDDED]; u32 sg_count[HBA_MAX_SG_EMBEDDED]; u32 sg_indx = 0; u32 byte_count = 0; @@ -517,6 +518,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */ + for (i = 0; i < HBA_MAX_SG_EMBEDDED; i++) + sg_addr[i] = DMA_MAPPING_ERROR; /* mark all entries unmapped */ if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){ dprintk((KERN_DEBUG"aacraid: Could not copy data size from user\n")); rcode = -EFAULT; @@ -690,6 +693,11 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = dma_map_single(&dev->pdev->dev, p, sg_count[i], data_dir); + if (dma_mapping_error(&dev->pdev->dev, addr)) { + rcode = -ENOMEM; + goto cleanup; + } + sg_addr[i] = addr; hbacmd->sge[i].addr_hi = cpu_to_le32((u32)(addr>>32)); hbacmd->sge[i].addr_lo = cpu_to_le32( (u32)(addr & 0xffffffff)); @@ -752,7 +760,11 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = dma_map_single(&dev->pdev->dev, p, sg_count[i], data_dir); - + if (dma_mapping_error(&dev->pdev->dev, addr)) { + rcode = -ENOMEM; + goto cleanup; + } + sg_addr[i] = addr; psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); psg->sg[i].addr[1] = cpu_to_le32(addr>>32); byte_count += sg_count[i]; @@ -808,7 +820,11 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = dma_map_single(&dev->pdev->dev, p, sg_count[i], data_dir); - + if (dma_mapping_error(&dev->pdev->dev, addr)) { + rcode = -ENOMEM; + goto cleanup; + } + sg_addr[i] = addr; psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); psg->sg[i].addr[1] = cpu_to_le32(addr>>32); byte_count += sg_count[i]; @@ -865,7 +881,11 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) addr = dma_map_single(&dev->pdev->dev, p, usg->sg[i].count, data_dir); - + if (dma_mapping_error(&dev->pdev->dev, addr)) { + rcode = -ENOMEM; + goto cleanup; + } + sg_addr[i] = addr; psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff); byte_count += usg->sg[i].count; psg->sg[i].count = cpu_to_le32(sg_count[i]); @@ -905,7 +925,11 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } addr = dma_map_single(&dev->pdev->dev, p, sg_count[i], data_dir); - + if (dma_mapping_error(&dev->pdev->dev, addr)) { + rcode = -ENOMEM; + goto cleanup; + } + sg_addr[i] = addr; psg->sg[i].addr = cpu_to_le32(addr); byte_count += sg_count[i]; psg->sg[i].count = cpu_to_le32(sg_count[i]); @@ -932,6 +956,11 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) if (flags & SRB_DataIn) { for(i = 0 ; i <= sg_indx; i++){ + if (sg_addr[i] != DMA_MAPPING_ERROR) { + dma_unmap_single(&dev->pdev->dev, sg_addr[i], + sg_count[i], data_dir); + sg_addr[i] = DMA_MAPPING_ERROR; + } if (copy_to_user(sg_user[i], sg_list[i], sg_count[i])) { dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n")); rcode = -EFAULT; @@ -986,8 +1015,12 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) cleanup: kfree(user_srbcmd); if (rcode != -ERESTARTSYS) { - for (i = 0; i <= sg_indx; i++) + for (i = 0; i <= sg_indx; i++) { + if (sg_addr[i] != DMA_MAPPING_ERROR) + dma_unmap_single(&dev->pdev->dev, sg_addr[i], + sg_count[i], data_dir); kfree(sg_list[i]); + } aac_fib_complete(srbfib); aac_fib_free(srbfib); } -- 2.55.0