From nobody Tue Oct 27 08:54:32 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4jDPSS74hPz6xCVl for ; Tue, 27 Oct 2026 08:54:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4jDPSS5p27z4lYf for ; Tue, 27 Oct 2026 08:54:32 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793091272; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=lRLGqJfJQ0BhpyL7WIk1B4t9Ew4dkNDDubRnLItthOU=; b=AQOto15JfgJ7r4OGcsNvefQ6LrKOkZMVvGzuAAggal9/6WUh1Ip6l98Jv/3bTXKRmVgM6s dHPNqx99JRWwBvsWT2WvCX5GcHRgqNx6FdflYiDQeiSrPyU8hFqEDJtdLS5AIWI7vMC76f fp2O5nEJNcD/h2VFFMYzlpdxUHH8Au5SYEe4V4PdPSGjR3aPpy/X/G0l3tmoLgB/6GmH7W Uue7HD5u9jFh5qIW+sFG1lDsLy1ayMX/bzFouJzxYlNiiIGjDYLtkEGPIg0fFfgb+y2MO+ KMRX2sriW2cSK/e13Tl8s6aUq9wSZ4+rxI4BN5mEqQjfG2XXoAcmjNRPYowYNA== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1793091272; b=h/4w5PBp7+D2OmGIKzqqlsCTyra1rn/alq0jk6Odx87Yc+bVmBna3fxDkN1/VgMq61xcp8 5W7ZU7eQKfx5TlHowcewVxcsYsa3AkB3YSbEFVN5OPps37gjT3L0vOV9IbieCnRew2H+bW Vldd2G7HGRDOzHBopXLoqORsp4Ln3lu294H0ODptAlRZ4Zjt6BoL1+LiIKt2r+QccB036z iGlnf+ln0a8zyv4VLNbw872qGyslNanfGxLBsvX29yVk4lGyssTMaK7OQWI114Bg7uCC2w 82Ow2TJQmQfRbqr86VxHmV2HVxn5gK2++2WpkOmE13aBzmxhJkfXYNFULhWbEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793091272; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=lRLGqJfJQ0BhpyL7WIk1B4t9Ew4dkNDDubRnLItthOU=; b=A2/bS15EUC16tTaNJGx+G7pGKLtihynoe4E+Md0z1TR7Ci7JsQO+SMJRBtUXNI1R8P2qjh mw8mOLcFigqI9p6jhBNH+gXMazVKbTbWLCVfWItBTYpDdUrraN/GqsoQr7I0E7g2SQtbMs 6kCEtfEj+Ktme9GgzhmyDzaZABXYmeZHcFd8EfVFZCEWXRR98nzZrozBRG6Jfj1d9YFqNd HF5x14iAYXPgkKyyeYrFowldHChYuuLb81ZNZgSIm0gXdvQ01UFeQBYkEJQIBSisCz9RjK t+Gwr9rYLoSMO4/3zmx/KCKr9pB+ht6qC6+q6USwjDMV3TM77XLGAViitsC3mw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4jDPSS4j3dzDdQ for ; Tue, 27 Oct 2026 08:54:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 461cf by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 27 Oct 2026 08:54:32 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Ram Kishore Vegesna Subject: git: 039a8e11f887 - main - ocs_fc: Fix config space bounds, double PRLI response and a stack overflow List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: Commit messages for all branches of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: ram X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 039a8e11f887e359af1346b04e05180b9a49920c Auto-Submitted: auto-generated Date: Tue, 27 Oct 2026 08:54:32 +0000 Message-Id: <6ae066c8.461cf.2be9e139@gitrepo.freebsd.org> The branch main has been updated by ram: URL: https://cgit.FreeBSD.org/src/commit/?id=039a8e11f887e359af1346b04e05180b9a49920c commit 039a8e11f887e359af1346b04e05180b9a49920c Author: Ram Kishore Vegesna AuthorDate: 2026-10-19 17:29:31 +0000 Commit: Ram Kishore Vegesna CommitDate: 2026-10-27 08:52:14 +0000 ocs_fc: Fix config space bounds, double PRLI response and a stack overflow Fix three unrelated problems found by security review of the driver. ECD helper ioctl: - OCS_ECD_HELPER_CFG_READ* and OCS_ECD_HELPER_CFG_WRITE* passed a user supplied offset straight to pci_read_config() and pci_write_config(). Reject accesses that extend past PCIE_REGMAX, so that a wide access starting in range cannot run past the end of config space. - Use the real access width (1, 2 or 4 bytes) of the command for both the BAR and the config space checks, rather than assuming 4 bytes, so that narrow accesses at the very end of the BAR or config space are not rejected while wider ones remain bounded. PRLI: - When a PRLI carries an FC-4 type other than the one the driver supports, ocs_d_send_prli_rsp() sent an LS_RJT and started node shutdown, but then fell through and sent a second response on the same IO (another LS_RJT, or a PRLI LS_ACC when the initiator is accepted), followed by a conflicting transition to __ocs_d_device_ready. The two responses posted two WQEs for one IO and caused a double ocs_ref_put(), a use after free of the ELS IO. Return after dispatching the LS_RJT so that exactly one response is sent. - __ocs_d_port_logged_in calls ocs_d_send_prli_rsp() without checking the FC-4 type, so any port that has completed a PLOGI can trigger this with a single PRLI, whether or not target mode is enabled. Management: - The active profile id is a uint32_t that is formatted as "0x%02x" with sprintf() into a buffer of MAX_PROFILE_LENGTH (5) bytes, which overflows for any id above 0xff. Size the buffer for the longest possible string ("0x" plus 8 hex digits and the terminating NUL) and use ocs_snprintf(). - Use ocs_snprintf() for nv_wwpn as well, as nv_wwnn already does. MFC after: 1 week Sponsored by: Broadcom Reviewed by: ken --- sys/dev/ocs_fc/ocs_device.c | 2 ++ sys/dev/ocs_fc/ocs_ioctl.c | 42 +++++++++++++++++++++++++++++++++++++++++- sys/dev/ocs_fc/ocs_mgmt.c | 8 +++++--- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/sys/dev/ocs_fc/ocs_device.c b/sys/dev/ocs_fc/ocs_device.c index d9c283541d3c..4d85970df675 100644 --- a/sys/dev/ocs_fc/ocs_device.c +++ b/sys/dev/ocs_fc/ocs_device.c @@ -74,6 +74,8 @@ ocs_d_send_prli_rsp(ocs_io_t *io, uint16_t ox_id) FC_EXPL_REQUEST_NOT_SUPPORTED, 0, NULL, NULL); node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT; ocs_node_transition(node, __ocs_d_initiate_shutdown, NULL); + /* Send only one response per PRLI; the LS_RJT owns the IO */ + return; } /* If the back-end doesn't want to talk to this initiator, we send an LS_RJT */ diff --git a/sys/dev/ocs_fc/ocs_ioctl.c b/sys/dev/ocs_fc/ocs_ioctl.c index a978f1084452..18dd3fbbac4c 100644 --- a/sys/dev/ocs_fc/ocs_ioctl.c +++ b/sys/dev/ocs_fc/ocs_ioctl.c @@ -41,6 +41,8 @@ #include #include +#include + static d_open_t ocs_open; static d_close_t ocs_close; static d_ioctl_t ocs_ioctl; @@ -299,6 +301,28 @@ no_support: return error; } +/** + * @brief return the access width in bytes of an ECD helper BAR/config command + */ +static uint32_t +ocs_ecd_helper_width(ocs_ecd_helper_cmd_t cmd) +{ + switch (cmd) { + case OCS_ECD_HELPER_BAR_READ8: + case OCS_ECD_HELPER_BAR_WRITE8: + case OCS_ECD_HELPER_CFG_READ8: + case OCS_ECD_HELPER_CFG_WRITE8: + return (sizeof(uint8_t)); + case OCS_ECD_HELPER_BAR_READ16: + case OCS_ECD_HELPER_BAR_WRITE16: + case OCS_ECD_HELPER_CFG_READ16: + case OCS_ECD_HELPER_CFG_WRITE16: + return (sizeof(uint16_t)); + default: + return (sizeof(uint32_t)); + } +} + /** * @brief perform requested Elx CoreDump helper function * @@ -318,6 +342,7 @@ ocs_process_ecd_helper (ocs_t *ocs, ocs_ioctl_ecd_helper_t *req) uint8_t v8; uint16_t v16; uint32_t v32; + uint32_t width; /* Check the BAR read/write commands for valid bar */ switch(req->cmd) { @@ -327,6 +352,7 @@ ocs_process_ecd_helper (ocs_t *ocs, ocs_ioctl_ecd_helper_t *req) case OCS_ECD_HELPER_BAR_WRITE8: case OCS_ECD_HELPER_BAR_WRITE16: case OCS_ECD_HELPER_BAR_WRITE32: + width = ocs_ecd_helper_width(req->cmd); if (req->bar >= PCI_MAX_BAR) { device_printf(ocs->dev, "Error: bar %d out of range\n", req->bar); return -EFAULT; @@ -335,13 +361,27 @@ ocs_process_ecd_helper (ocs_t *ocs, ocs_ioctl_ecd_helper_t *req) device_printf(ocs->dev, "Error: bar %d not defined\n", req->bar); return -EFAULT; } - if ((uint64_t)req->offset + sizeof(uint32_t) > + if ((uint64_t)req->offset + width > rman_get_size(ocs->reg[req->bar].res)) { device_printf(ocs->dev, "Error: bar %d offset 0x%x out of range\n", req->bar, req->offset); return -EFAULT; } break; + case OCS_ECD_HELPER_CFG_READ8: + case OCS_ECD_HELPER_CFG_READ16: + case OCS_ECD_HELPER_CFG_READ32: + case OCS_ECD_HELPER_CFG_WRITE8: + case OCS_ECD_HELPER_CFG_WRITE16: + case OCS_ECD_HELPER_CFG_WRITE32: + width = ocs_ecd_helper_width(req->cmd); + if ((uint64_t)req->offset + width - 1 > PCIE_REGMAX) { + device_printf(ocs->dev, + "Error: config offset 0x%x out of range\n", + req->offset); + return -EFAULT; + } + break; default: break; } diff --git a/sys/dev/ocs_fc/ocs_mgmt.c b/sys/dev/ocs_fc/ocs_mgmt.c index 5b7f6557c017..483e80ce649a 100644 --- a/sys/dev/ocs_fc/ocs_mgmt.c +++ b/sys/dev/ocs_fc/ocs_mgmt.c @@ -2076,7 +2076,8 @@ ocs_mgmt_get_active_profile_cb(int32_t status, uint32_t active_profile, void *ul ocs_sem_v(&(result->semaphore)); } -#define MAX_PROFILE_LENGTH 5 +/* "0x", up to 8 hex digits and a NUL for a uint32_t id */ +#define MAX_PROFILE_LENGTH 11 /** * @brief Get active profile @@ -2107,7 +2108,7 @@ get_active_profile(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) } if (result.status == 0) { /* Success. */ - sprintf(result_string, "0x%02x", result.active_profile_id); + ocs_snprintf(result_string, sizeof(result_string), "0x%02x", result.active_profile_id); ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "active_profile", result_string); } else { ocs_log_test(ocs, "getting active profile status 0x%x\n", result.status); @@ -2225,7 +2226,8 @@ get_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) } if (result.status == 0) { /* Success. Copy wwpn from result struct to result string */ - sprintf(result_string, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + ocs_snprintf(result_string, sizeof(result_string), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", result.wwpn[0], result.wwpn[1], result.wwpn[2], result.wwpn[3], result.wwpn[4], result.wwpn[5], result.wwpn[6], result.wwpn[7]);