From patchwork Mon Feb 24 19:07:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13988827 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AE5021DD0D4 for ; Mon, 24 Feb 2025 19:07:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740424047; cv=none; b=Sj9ZsIGDKK9gUEW7vVap/H3WP3/pxWHCdBsU0iJQrd9uPYQFaGi5H5uTS4gvMxfLP49PbPqX07W7gOnQjFYke9Ry14f2rajp+eILZm7TB5NK568bOraqMJ0iIrg7+hsjz91c9BSyRw2Y6+2eTszUqwszKXJDMGzWRJ3l0tWbyMg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740424047; c=relaxed/simple; bh=jDZL9JBQze7jATv6nLZrrpFqNHkW55VduwVDMIICaKE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nmXq7jnyfGFDxhTyDGWoyHq/a9re2zTrTsjZ8XSnTk0RiHE5riYDGzk/YkMbsuaqewz1FoVnGRDcx95PIMxstiGDyWQvp53UcOk566hw2aBSp2lU/I9s2+kELbHPt19UdAAN6H9yDsc3Its63ns1ZFqDYCRhO0GjmDI3TJ7u80M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gHkkinzT; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gHkkinzT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2C078C4CED6; Mon, 24 Feb 2025 19:07:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740424047; bh=jDZL9JBQze7jATv6nLZrrpFqNHkW55VduwVDMIICaKE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=gHkkinzTKSO/7MvmzC/AkL7Q44U2A8D+MCV4FJdMvH8NGyANSYr8twBE7n4oTNZkJ 3bw8TkCPblMp3ST8WfYQtTk7I3HelkoTPObJFI+PzsnMuzYluHD42LZ5yoP5SI7cFU F3R6510YpwNNP+X8KQENlGqasIHfX+8BGO94hR8IgWVc+vjyqXzt6n4N7pdhqtzQcz 0y1WNmTuTp716t4lYj5SgRnAzBBGFDssSFAhmih9ulXwbdQOjsl6HeIukTd4YtaTY6 j9Dn4wZzUSMHFLsINsCxx92T8KC/La8XX7DMbt3EENNw6F0dcnR3WLLFzjldgR9/e3 52CPdVzo+yY4A== Date: Mon, 24 Feb 2025 11:07:26 -0800 Subject: [PATCH 1/3] xfs_scrub: fix buffer overflow in string_escape From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <174042401290.1205942.5986684789242095979.stgit@frogsfrogsfrogs> In-Reply-To: <174042401261.1205942.2400336290900827299.stgit@frogsfrogsfrogs> References: <174042401261.1205942.2400336290900827299.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Need to allocate one more byte for the null terminator, just in case the /entire/ input string consists of non-printable bytes e.g. emoji. Cc: # v4.15.0 Fixes: 396cd0223598bb ("xfs_scrub: warn about suspicious characters in directory/xattr names") Signed-off-by: "Darrick J. Wong" Reviewed-by: Andrey Albershteyn Reviewed-by: Christoph Hellwig --- scrub/common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scrub/common.c b/scrub/common.c index 6eb3c026dc5ac9..2b2d4a67bc47a2 100644 --- a/scrub/common.c +++ b/scrub/common.c @@ -320,7 +320,11 @@ string_escape( char *q; int x; - str = malloc(strlen(in) * 4); + /* + * Each non-printing byte renders as a four-byte escape sequence, so + * allocate 4x the input length, plus a byte for the null terminator. + */ + str = malloc(strlen(in) * 4 + 1); if (!str) return NULL; for (p = in, q = str; *p != '\0'; p++) { From patchwork Mon Feb 24 19:07:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13988828 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 695D116CD1D for ; Mon, 24 Feb 2025 19:07:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740424064; cv=none; b=OjFtlDrJum/GDnaoXUAIajIkzQR+mbRJ/DAjv+ynv8h4rrGOzNB6813wijH3bk1cwRzI46NqtOwHjgPvccDjUsquaulAq6doxt3dRA8uxv5YsjpVs2KcXJH0gE2T/OqqbYeXf4BEH+9lueReUlhKprFCgQZ8RQlaLUVCjVqN3ps= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740424064; c=relaxed/simple; bh=1GbE7yTHmiFpCumOEExXegjE2U4CIMZ5DqPDCfhIhcM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=p4Q4iLZELU9Eljwz1qWcj4PUPH1w2rEdRhRuEcjS0TrZq8lvVKGDL2rzucqHa6W8oiDBLufSGy+Hp2YMvA47ZcN7W2c08BsXlaWWDDEreM+kXLsnq0tU1mghiTI3Vwdem78Tdkh0ttCBP66VYFvrpcR6by2nOw1+FvRj+buu+Qc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CDjIMpUQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CDjIMpUQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DCA09C4CED6; Mon, 24 Feb 2025 19:07:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740424062; bh=1GbE7yTHmiFpCumOEExXegjE2U4CIMZ5DqPDCfhIhcM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=CDjIMpUQ8gle/GWbM1fYYGSK2A4TxICXKMllt09uHyVFnOZmew7EHZWJbDBmGo1pz Y45X8iaxxzqgn/IUkcyJxQRRzCVBhxUPR/Zb6wnaILyiY6UPN9114Zu5pbPitSAQtJ 2DiQSfrjLfflpDkFK7MnPHn4eauVq1EdsKd1wGjMX97GBKucrRKhwR4wAD94/rP1tO BQKy1pB2Vof/yR+tOG/d2IEX1p0Qyw1tBSpre9OolRWBzowfwC5PSqOMq6H/MX8qdr YEnl9uw2JHRVqxTQEE3bMD62diaP7wGOCu493Bp56Z6YMty/dvhow5pQiXBgZ7h2+H iIYmPO/kKa0NA== Date: Mon, 24 Feb 2025 11:07:42 -0800 Subject: [PATCH 2/3] xfs_scrub: don't warn about zero width joiner control characters From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <174042401309.1205942.12498812873396538376.stgit@frogsfrogsfrogs> In-Reply-To: <174042401261.1205942.2400336290900827299.stgit@frogsfrogsfrogs> References: <174042401261.1205942.2400336290900827299.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong The Unicode code point for "zero width joiners" (aka 0x200D) is used to hint to renderers that a sequence of simple code points should be combined into a more complex rendering. This is how compound emoji such as "wounded heart" are composed out of "heart" and "bandaid"; and how complex glyphs are rendered in Malayam. Emoji in filenames are a supported usecase, so stop warning about the mere existence of ZWJ. We already warn about ZWJ that are used to produce confusingly rendered names in a single namespace, so we're not losing any robustness here. Cc: # v6.10.0 Fixes: d43362c78e3e37 ("xfs_scrub: store bad flags with the name entry") Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- scrub/unicrash.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scrub/unicrash.c b/scrub/unicrash.c index 143060b569f27c..b83bef644b6dce 100644 --- a/scrub/unicrash.c +++ b/scrub/unicrash.c @@ -508,8 +508,14 @@ name_entry_examine( if (is_nonrendering(uchr)) ret |= UNICRASH_INVISIBLE; - /* control characters */ - if (u_iscntrl(uchr)) + /* + * Warn about control characters in filenames except for zero + * width joiners because those are used to construct compound + * emoji and glyphs in various languages. ZWJ is already + * covered by UNICRASH_INVISIBLE, so we can detect its use in + * confusing names. + */ + if (uchr != 0x200D && u_iscntrl(uchr)) ret |= UNICRASH_CONTROL_CHAR; switch (u_charDirection(uchr)) { From patchwork Mon Feb 24 19:07:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13988829 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3020C16CD1D for ; Mon, 24 Feb 2025 19:07:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740424079; cv=none; b=XKT4cnW4VpLZQgYK0os/YGfA6ev+WAeQHjNgklXMK1v8G8EtYdMJjRGy0c/CQqVQe3M3TOuRmQ7m27gQ/iHEbpCjJ/RWnQuKI5XMREqDKHm+AZCHxUqGg0/DyRET0+ASwe0TqUx0NVPRsOHowu71jAiyqFX53FB9eRTstHUu/oQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740424079; c=relaxed/simple; bh=+h/k9FYFwvOJp5nvbip9NvGb6DSd/vwhpWiVkIlSbjc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LSwozQhOV9LJ+wm5UBLyO3HfF7FSUPf1Y8fdpHpgdseR/T0bmLcdZ3KzO6jA2gMHLGoRpCPqjLXSuZ4+swnKxwSBVMhqOwRpM/jaOB5HuxrO2Dk5sI8h295Ya7Hcl8JITFFtdpuCmsGRulcT5gQdC/sn1CtjwtX4P4GYqzktakA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cjN+ot2W; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cjN+ot2W" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 90E65C4CED6; Mon, 24 Feb 2025 19:07:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740424078; bh=+h/k9FYFwvOJp5nvbip9NvGb6DSd/vwhpWiVkIlSbjc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=cjN+ot2WvOcvA0Djjyt5+dM+EYDxQ5gA5v3Nni6MMYR/vI1bYBCBiTqSUVu6Tqjwk 3Aj7mvLnS3Vncf1NDmgQMuWqZdSTuVFrzjGnSwuOgviopy0CAmZt+X0VZP/NZMXGN7 vUoOMQdF4sQJElXM+L9z+9tOiT6YDXjlUgO9Ni4jqsgtt/SSXMZjvk7SjfZ0pVSbBI uo/jLNjAOG5stXWDYTkfkvnYH4KYEi8qN137oumzhvW2DwVwmgbEZ8BkbD8BK7BoxC a6cpz0VsoCLpgwaoa7MBg/bBkD1UlkWY5P1I4MBl0aYMzLpsAfVa33LnFJbUuA/nvy qYj+sn5Ulf+bQ== Date: Mon, 24 Feb 2025 11:07:58 -0800 Subject: [PATCH 3/3] xfs_scrub: use the display mountpoint for reporting file corruptions From: "Darrick J. Wong" To: djwong@kernel.org, aalbersh@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <174042401327.1205942.4120060381904924599.stgit@frogsfrogsfrogs> In-Reply-To: <174042401261.1205942.2400336290900827299.stgit@frogsfrogsfrogs> References: <174042401261.1205942.2400336290900827299.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong In systemd service mode, we make systemd bind-mount the target mountpoint onto /tmp/scrub (/tmp is private to the service) so that updates to the global mountpoint in the shared mount namespace don't propagate into our service container and vice versa, and pass the path to the bind mount to xfs_scrub via -M. This solves races such as unmounting of the target mount point after service container creation but before process invocation that result in the wrong filesystem being scanned. IOWs, to scrub /usr, systemd runs "xfs_scrub -M /tmp/scrub /usr". Pretend that /usr is a separate filesystem. However, when xfs_scrub snapshots the handle of /tmp/scrub, libhandle remembers that /tmp/scrub the beginning of the path, not the pathname that we want to use for reporting (/usr). This means that handle_to_path returns /tmp/scrub and not /usr as well, with the unfortunate result that file corrupts are reported with the pathnames in the xfs_scrub@ service container, not the global ones. Put another way, xfs_scrub should complain that /usr/bin/X is corrupt, not /tmp/scrub/bin/X. Therefore, modify scrub_render_ino_descr to manipulate the path buffer during error reporting so that the user always gets the mountpoint passed in, even if someone tells us to use another path for the actual open() call in phase 1. Cc: # v6.10.0 Fixes: 9a8b09762f9a52 ("xfs_scrub: use parent pointers when possible to report file operations") Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- scrub/common.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/scrub/common.c b/scrub/common.c index 2b2d4a67bc47a2..14cd677ba5e9c4 100644 --- a/scrub/common.c +++ b/scrub/common.c @@ -418,15 +418,59 @@ scrub_render_ino_descr( if (ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_PARENT) { struct xfs_handle handle; + char *pathbuf = buf; + size_t used = 0; handle_from_fshandle(&handle, ctx->fshandle, ctx->fshandle_len); handle_from_inogen(&handle, ino, gen); + /* + * @actual_mntpoint is the path we used to open the filesystem, + * and @mntpoint is the path we use for display purposes. If + * these aren't the same string, then for reporting purposes + * we must fix the start of the path string. Start by copying + * the display mountpoint into buf, except for trailing + * slashes. At this point buf will not be null-terminated. + */ + if (ctx->actual_mntpoint != ctx->mntpoint) { + used = strlen(ctx->mntpoint); + while (used && ctx->mntpoint[used - 1] == '/') + used--; + + /* If it doesn't fit, report the handle instead. */ + if (used >= buflen) { + used = 0; + goto report_inum; + } + + memcpy(buf, ctx->mntpoint, used); + pathbuf += used; + } + ret = handle_to_path(&handle, sizeof(struct xfs_handle), 4096, - buf, buflen); + pathbuf, buflen - used); if (ret) goto report_inum; + /* + * Now that handle_to_path formatted the full path (including + * the actual mount point, stripped of any trailing slashes) + * into the rest of pathbuf, slide down the contents by the + * length of the actual mount point. Don't count any trailing + * slashes because handle_to_path uses libhandle, which strips + * trailing slashes. Copy one more byte to ensure we get the + * terminating null. + */ + if (ctx->actual_mntpoint != ctx->mntpoint) { + size_t len = strlen(ctx->actual_mntpoint); + + while (len && ctx->actual_mntpoint[len - 1] == '/') + len--; + + pathlen = strlen(pathbuf); + memmove(pathbuf, pathbuf + len, pathlen - len + 1); + } + /* * Leave at least 16 bytes for the description of what went * wrong. If we can't do that, we'll use the inode number.