All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steve French <smfrench@gmail.com>
To: linux-cifs@vger.kernel.org
Cc: Steve French <stfrench@microsoft.com>
Subject: [PATCH v2] smb: client: preserve leading slash for POSIX absolute symlink targets
Date: Sun,  5 Jul 2026 16:17:57 -0500	[thread overview]
Message-ID: <20260705211757.60659-1-stfrench@microsoft.com> (raw)

When creating a native SMB symbolic link (CIFS_SYMLINK_TYPE_NATIVE) whose
target is an absolute path on a mount that uses POSIX paths, the leading
path separator was silently dropped from the stored symlink target.

create_native_symlink() converted the target to UTF-16 with
cifs_convert_path_to_utf16().  That helper is intended for share-relative
SMB paths and therefore unconditionally strips a leading path separator.
For an absolute POSIX symlink target the leading '/' is significant, so a
target of "/foo/bar" was stored - and read back - as "foo/bar", even
though the reparse point was still flagged as absolute
(SYMLINK_FLAG_RELATIVE cleared).

On a POSIX paths mount the symlink target is stored verbatim, so convert
it directly with cifs_strndup_to_utf16() instead.  This preserves the
leading separator, avoids the leading-backslash stripping that
cifs_convert_path_to_utf16() also performs (a backslash is a valid POSIX
filename character), and uses NO_MAP_UNI_RSVD to match the readback path
in smb2_parse_native_symlink(), which always converts the target with
cifs_strndup_from_utf16() / NO_MAP_UNI_RSVD.  This mirrors how the NFS and
WSL reparse symlink creators convert their targets.

The NT-style absolute symlink handling, which needs the "\??\" prefix and
drive-letter colon preserved, continues to use cifs_convert_path_to_utf16()
together with the existing masking of those bytes.

Fixes: 12b466eb52d9 ("cifs: Fix creating and resolving absolute NT-style symlinks")
Signed-off-by: Steve French <stfrench@microsoft.com>
---
 fs/smb/client/reparse.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index cd1e1eaee67a..5cc5b0410d48 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -67,6 +67,7 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
 	char *sym = NULL;
 	struct kvec iov;
 	bool directory;
+	int path_len;
 	int rc = 0;
 
 	if (strlen(symname) > REPARSE_SYM_PATH_MAX)
@@ -168,7 +169,21 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
 	if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/')
 		sym[0] = sym[1] = sym[2] = sym[5] = '_';
 
-	path = cifs_convert_path_to_utf16(sym, cifs_sb);
+	/*
+	 * On a POSIX paths mount the symlink target is stored verbatim, so
+	 * convert it with cifs_strndup_to_utf16().  cifs_convert_path_to_utf16()
+	 * must not be used here: it strips a leading path separator (it is
+	 * meant for share-relative SMB paths), which would corrupt an absolute
+	 * POSIX symlink target such as "/foo/bar".  Using NO_MAP_UNI_RSVD also
+	 * matches the readback path in smb2_parse_native_symlink().
+	 */
+	if (sbflags & CIFS_MOUNT_POSIX_PATHS)
+		path = cifs_strndup_to_utf16(sym, strlen(sym), &path_len,
+					     cifs_sb->local_nls,
+					     NO_MAP_UNI_RSVD);
+	else
+		path = cifs_convert_path_to_utf16(sym, cifs_sb);
+
 	if (!path) {
 		rc = -ENOMEM;
 		goto out;
-- 
2.53.0


             reply	other threads:[~2026-07-05 21:18 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-05 21:17 Steve French [this message]
2026-07-05 22:24 ` [PATCH v2] smb: client: preserve leading slash for POSIX absolute symlink targets Paulo Alcantara
2026-07-06  5:17 ` Ralph Boehme

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260705211757.60659-1-stfrench@microsoft.com \
    --to=smfrench@gmail.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=stfrench@microsoft.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.