From nobody Mon Sep 28 05:39:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 E94C937C113; Tue, 25 Aug 2026 23:06:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699200; cv=none; b=u34XXXX5feADJ1K0K10sZKkCwSp9v1L+JypzitCwcT9uPRKs54S+3e+e93mgu7O9TFM74Z69DEm6qCHoYmEGdLJXLJ0Y2Ri4uKZPJ9S939Fd0Gw1/hf/4IQff8Myl55E3qmiV6zOv8vEtPG6F9JmGuJWCqPFeJz9il6zz4b+UBc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699200; c=relaxed/simple; bh=JhkMWWqRJx9psoumgsDK98+2tpoQ068BSJ78/2DGbyk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=kvE0F0SjDavLPEDfq1JyNNCraPlMzN4v7MAe9ocBuo6phyiAfpEtCus7lj1uQbvUy34TrXoXy/e7Iv/CvGwbIMTipYOPvPOSqiEf6njl6uLj1eS7ScKII5vc9xqUVOQyjsIJwK/W5bGVT8uBq9xFhl9Hx+/oNPeiHhhhA87euaE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=L3Wa8HNs; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="L3Wa8HNs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7BFEB1F000E9; Tue, 25 Aug 2026 23:06:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787699198; bh=lQ/yTMtE+w6OzU2M5CM1aO06yMT7ElEm71XdraXjWes=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=L3Wa8HNsc9zCaOaeIbtwedG2aQi21Cuv9h+/uCraQWms7rtCUQ0Ekpf4nhFeT75Z+ YFs2P+YyOkkFqQHY0856Op11f8fZVdDgW5GkEfsCU2txiSyj9a9SIGBatQLj88X7j4 IQKkNOEIYsNzWguS/UpeWvqEc7MrdXi7zOq+A9kePDucvqocizCSXLY0w46x7KmIsL Y619lxtaEHhlY+FlbKw6ORTZXzJqAfAZHVavySRyuzWF65/Qlwc4QvLKu/elC2DxoY vJ0Q6+Gq4ISrP0Mkg4yvaqtKnB0oQ53EJ5WWTRMZERGEY/0NA5VRi3RVULKbyp3os5 yXUUxCsoUYbxw== Received: by pali.im (Postfix) id 19865A4E; Wed, 26 Aug 2026 01:06:38 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Paulo Alcantara , Namjae Jeon Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/9] cifs: Remove code for querying FILE_INFO_STANDARD via CIFSSMBQPathInfo() Date: Wed, 26 Aug 2026 01:06:14 +0200 Message-Id: <20260825230622.24617-2-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260825230622.24617-1-pali@kernel.org> References: <20260821214722.q7rkflclyyugdxll@pali> <20260825230622.24617-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Querying FILE_INFO_STANDARD structure via SMB_INFO_STANDARD level over TRANS2_QUERY_PATH_INFORMATION or TRANS2_QUERY_FILE_INFORMATION command (implemented in CIFSSMBQPathInfo() when called with argument legacy=3Dtrue) is mostly unusable. Win9x SMB server returns over those commands the FILE_INFO_STANDARD structure with swapped TIME and DATE fields, compared with [MS-CIFS] spec and Samba server implementation. Therefore this command cannot be used unless we know against which server implementation we are connected. There are already two fallback mechanisms for querying information about path which are working correctly against Samba, NT and Win9x servers: CIFSFindFirst() and SMBQueryInformation() commands. So remove TRANS2_QUERY_PATH_INFORMATION/SMB_INFO_STANDARD code from CIFSSMBQPathInfo() function, when the function is called with legacy=3Dtrue. Note that there is no use of CIFSSMBQPathInfo(legacy=3Dtrue) anymore. Signed-off-by: Pali Roh=C3=A1r --- fs/smb/client/cifssmb.c | 23 +++-------------------- fs/smb/client/smb1ops.c | 4 ++-- fs/smb/client/smb1proto.h | 1 - 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index f5aad5f61dce..a972950b7e09 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -4119,7 +4119,6 @@ CIFSSMBQFileInfo(const unsigned int xid, struct cifs_= tcon *tcon, int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, const char *search_name, FILE_ALL_INFO *data, - int legacy /* old style infolevel */, const struct nls_table *nls_codepage, int remap) { /* level 263 SMB_QUERY_FILE_ALL_INFO */ @@ -4169,10 +4168,7 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs= _tcon *tcon, byte_count =3D params + 1 /* pad */ ; pSMB->TotalParameterCount =3D cpu_to_le16(params); pSMB->ParameterCount =3D pSMB->TotalParameterCount; - if (legacy) - pSMB->InformationLevel =3D cpu_to_le16(SMB_INFO_STANDARD); - else - pSMB->InformationLevel =3D cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); + pSMB->InformationLevel =3D cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); pSMB->Reserved4 =3D 0; in_len +=3D byte_count; pSMB->ByteCount =3D cpu_to_le16(byte_count); @@ -4187,27 +4183,14 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cif= s_tcon *tcon, if (rc) /* BB add auto retry on EOPNOTSUPP? */ rc =3D smb_EIO2(smb_eio_trace_qpathinfo_invalid, get_bcc(&pSMBr->hdr), 40); - else if (!legacy && get_bcc(&pSMBr->hdr) < 40) + else if (get_bcc(&pSMBr->hdr) < 40) rc =3D smb_EIO2(smb_eio_trace_qpathinfo_bcc_too_small, get_bcc(&pSMBr->hdr), 40); - else if (legacy && get_bcc(&pSMBr->hdr) < 24) - /* 24 or 26 expected but we do not read last field */ - rc =3D smb_EIO2(smb_eio_trace_qpathinfo_bcc_too_small, - get_bcc(&pSMBr->hdr), 24); else if (data) { int size; __u16 data_offset =3D le16_to_cpu(pSMBr->t2.DataOffset); =20 - /* - * On legacy responses we do not read the last field, - * EAsize, fortunately since it varies by subdialect and - * also note it differs on Set vs Get, ie two bytes or 4 - * bytes depending but we don't care here. - */ - if (legacy) - size =3D sizeof(FILE_INFO_STANDARD); - else - size =3D sizeof(FILE_ALL_INFO); + size =3D sizeof(FILE_ALL_INFO); memcpy((char *) data, (char *) &pSMBr->hdr.Protocol + data_offset, size); } else diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index 3ac4126267f6..9c77752cb7f9 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -510,7 +510,7 @@ cifs_is_path_accessible(const unsigned int xid, struct = cifs_tcon *tcon, =20 if (tcon->ses->capabilities & CAP_NT_SMBS) rc =3D CIFSSMBQPathInfo(xid, tcon, full_path, &file_info, - 0 /* not legacy */, cifs_sb->local_nls, + cifs_sb->local_nls, cifs_remap(cifs_sb)); =20 /* @@ -556,7 +556,7 @@ static int cifs_query_path_info(const unsigned int xid, * do not even use CIFSSMBQPathInfo() or CIFSSMBQFileInfo() function. */ if (tcon->ses->capabilities & CAP_NT_SMBS) - rc =3D CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, + rc =3D CIFSSMBQPathInfo(xid, tcon, full_path, &fi, cifs_sb->local_nls, cifs_remap(cifs_sb)); =20 /* diff --git a/fs/smb/client/smb1proto.h b/fs/smb/client/smb1proto.h index 80eaeb3dd2ec..f0350fa3f173 100644 --- a/fs/smb/client/smb1proto.h +++ b/fs/smb/client/smb1proto.h @@ -141,7 +141,6 @@ int CIFSSMBQFileInfo(const unsigned int xid, struct cif= s_tcon *tcon, u16 netfid, FILE_ALL_INFO *pFindData); int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, const char *search_name, FILE_ALL_INFO *data, - int legacy /* old style infolevel */, const struct nls_table *nls_codepage, int remap); int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, u16 netfid, FILE_UNIX_BASIC_INFO *pFindData); --=20 2.20.1 From nobody Mon Sep 28 05:39:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 761F23AD539; Tue, 25 Aug 2026 23:06:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699200; cv=none; b=XZnR60CDKNTivvrT4fYs4ZFEJ+PplDuzWOOu6KRXjsAgz2WpWMj15N4S3UgRPDqGa2EFZgOVCetlVn2W1amI/YuK97OXDLgpg/zxXbGtu12a3TikrFNkmBIyVWT0edC9/emaudnnioVk1maZl8KEiTNoxGhRv85tyx9LL2pYcqE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699200; c=relaxed/simple; bh=pFzHvlTXc1rqFQljxVWQXdatV81xMEL+ZNONZpGfWrw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=N2V2p5n8EtNqup0+KHHO6CBgJpzP8ZdwY3+lIj0BcZZb+iLyfE2cZZve20fYv7MK+V9FQezvuSWDd9jlheTPRFnw6GWykqcnOu86YYDSPeJ24om9oHaECfcNDogiXd9S9CU+cTAoOityoWEJPt1/MHJlyzMRSFjiBiajoW471kI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CGErFt6T; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CGErFt6T" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8A70A1F00A3A; Tue, 25 Aug 2026 23:06:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787699198; bh=yX1zCwM0MN6Wp1aXNNFAVvJ91aOPpZNfkxMWeKivRhU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=CGErFt6TVevbBEvFCgcBwIehQyJUBCsfSNBssZkKWelSPS1PHpm4jdN3Sx53v1BvE T6kuILJuM75CJXsXJkvUitoA8R6u69GGcKhhDYhR8dH+vYDXZLAJXerVSd7+f/RzUK 8nmhsEmhLNN+JlVQLVezqx+WNPksSMrHFPwF2rwMgAvFTioMVaf1K+nVj4C7zcnCZQ 7kIT7SFi+mLNuWEddCDbzM570F4iagm89J7cP2UKdzkr9OdTQHYIPjyYSpddTLxmrA D96mmxzfv3XBtQTXbZx7wBxKL6gWqWIeW32Kh8XU1lTYwL/hTV4/vaViv6tswvzT6X 1kAlfoTLvTIXA== Received: by pali.im (Postfix) id 45F5BB82; Wed, 26 Aug 2026 01:06:38 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Paulo Alcantara , Namjae Jeon Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/9] cifs: Remove cifs_backup_query_path_info() and replace it by cifs_query_path_info() Date: Wed, 26 Aug 2026 01:06:15 +0200 Message-Id: <20260825230622.24617-3-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260825230622.24617-1-pali@kernel.org> References: <20260821214722.q7rkflclyyugdxll@pali> <20260825230622.24617-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Response handling of cifs_backup_query_path_info() function in cifs_get_fattr() is broken and can cause buffer overflows because cifs_backup_query_path_info() prepares request with different info levels but the response parser in cifs_get_fattr() always expects response structure FILE_DIRECTORY_INFO. Code which queries file/dir attributes via CIFSFindFirst() is already implemented in cifs_query_path_info() function, so extend it for backup_cred(), which is the only missing functionality compared to cifs_backup_query_path_info(). With this change the cifs_query_path_info() would do everything which is open-coded in cifs_set_fattr_ino() and cifs_backup_query_path_info() functions for SMB1. So remove that SMB1 code from cifs_set_fattr_ino() and also remove whole cifs_backup_query_path_info() function. Signed-off-by: Pali Roh=C3=A1r --- fs/smb/client/inode.c | 97 ----------------------------------------- fs/smb/client/smb1ops.c | 7 ++- 2 files changed, 5 insertions(+), 99 deletions(-) diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index 12ed8db10e00..4ccfc83f7d3b 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -1063,61 +1063,6 @@ static __u64 simple_hashstr(const char *str) return hash; } =20 -#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY -/** - * cifs_backup_query_path_info - SMB1 fallback code to get ino - * - * Fallback code to get file metadata when we don't have access to - * full_path (EACCES) and have backup creds. - * - * @xid: transaction id used to identify original request in logs - * @tcon: information about the server share we have mounted - * @sb: the superblock stores info such as disk space available - * @full_path: name of the file we are getting the metadata for - * @resp_buf: will be set to cifs resp buf and needs to be freed with - * cifs_buf_release() when done with @data - * @data: will be set to search info result buffer - */ -static int -cifs_backup_query_path_info(int xid, - struct cifs_tcon *tcon, - struct super_block *sb, - const char *full_path, - void **resp_buf, - FILE_ALL_INFO **data) -{ - struct cifs_sb_info *cifs_sb =3D CIFS_SB(sb); - struct cifs_search_info info =3D {0}; - u16 flags; - int rc; - - *resp_buf =3D NULL; - info.endOfSearch =3D false; - if (tcon->unix_ext) - info.info_level =3D SMB_FIND_FILE_UNIX; - else if ((tcon->ses->capabilities & - tcon->ses->server->vals->cap_nt_find) =3D=3D 0) - info.info_level =3D SMB_FIND_FILE_INFO_STANDARD; - else if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM) - info.info_level =3D SMB_FIND_FILE_ID_FULL_DIR_INFO; - else /* no srvino useful for fallback to some netapp */ - info.info_level =3D SMB_FIND_FILE_DIRECTORY_INFO; - - flags =3D CIFS_SEARCH_CLOSE_ALWAYS | - CIFS_SEARCH_CLOSE_AT_END | - CIFS_SEARCH_BACKUP_SEARCH; - - rc =3D CIFSFindFirst(xid, tcon, full_path, - cifs_sb, NULL, flags, &info, false); - if (rc) - return rc; - - *resp_buf =3D (void *)info.ntwrk_buf_start; - *data =3D (FILE_ALL_INFO *)info.srch_entries_start; - return 0; -} -#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ - static void cifs_set_fattr_ino(int xid, struct cifs_tcon *tcon, struct sup= er_block *sb, struct inode **inode, const char *full_path, struct cifs_open_info_data *data, struct cifs_fattr *fattr) @@ -1333,45 +1278,6 @@ static int cifs_get_fattr(struct cifs_open_info_data= *data, cifs_create_junction_fattr(fattr, sb); rc =3D 0; break; - case -EACCES: -#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY - /* - * perm errors, try again with backup flags if possible - * - * For SMB2 and later the backup intent flag - * is already sent if needed on open and there - * is no path based FindFirst operation to use - * to retry with - */ - if (backup_cred(cifs_sb) && is_smb1_server(server)) { - /* for easier reading */ - FILE_ALL_INFO *fi; - FILE_DIRECTORY_INFO *fdi; - FILE_ID_FULL_DIR_INFO *si; - - rc =3D cifs_backup_query_path_info(xid, tcon, sb, - full_path, - &smb1_backup_rsp_buf, - &fi); - if (rc) - goto out; - - move_cifs_info_to_smb2(&data->fi, fi); - fdi =3D (FILE_DIRECTORY_INFO *)fi; - si =3D (FILE_ID_FULL_DIR_INFO *)fi; - - cifs_dir_info_to_fattr(fattr, fdi, cifs_sb); - fattr->cf_uniqueid =3D le64_to_cpu(si->UniqueId); - /* uniqueid set, skip get inum step */ - goto handle_mnt_opt; - } else { - /* nothing we can do, bail out */ - goto out; - } -#else - goto out; -#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ - break; default: cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc); goto out; @@ -1386,9 +1292,6 @@ static int cifs_get_fattr(struct cifs_open_info_data = *data, /* * 4. Tweak fattr based on mount options */ -#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY -handle_mnt_opt: -#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ sbflags =3D cifs_sb_flags(cifs_sb); /* query for SFU type info if supported and needed */ if ((fattr->cf_cifsattrs & ATTR_SYSTEM) && diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index 9c77752cb7f9..be73e4b9028c 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -569,15 +569,18 @@ static int cifs_query_path_info(const unsigned int xi= d, /* * Then fallback to CIFSFindFirst() which works also with non-NT servers * but does not does not provide NumberOfLinks. + * Can be used with backup intent flag to overcome -EACCES error. */ - if ((rc =3D=3D -EOPNOTSUPP || rc =3D=3D -EINVAL) && + if ((rc =3D=3D -EOPNOTSUPP || rc =3D=3D -EINVAL || + (backup_cred(cifs_sb) && rc =3D=3D -EACCES)) && !non_unicode_wildcard) { if (!(tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find)) search_info.info_level =3D SMB_FIND_FILE_INFO_STANDARD; else search_info.info_level =3D SMB_FIND_FILE_FULL_DIRECTORY_INFO; rc =3D CIFSFindFirst(xid, tcon, full_path, cifs_sb, NULL, - CIFS_SEARCH_CLOSE_ALWAYS | CIFS_SEARCH_CLOSE_AT_END, + CIFS_SEARCH_CLOSE_ALWAYS | CIFS_SEARCH_CLOSE_AT_END | + (backup_cred(cifs_sb) ? CIFS_SEARCH_BACKUP_SEARCH : 0), &search_info, false); if (rc =3D=3D 0) { if (!(tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find)) { --=20 2.20.1 From nobody Mon Sep 28 05:39:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 E943F3537E8; Tue, 25 Aug 2026 23:06:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699200; cv=none; b=kgjTt8TfSvxGvKGNfs+xD9pCctnH3go4OLvKZ+cIKagCw8ZMTpnV49Oa8rWMPc8Zna/7RxHLDQj63zwLGUEkQMJ6/im5DjLUGa1hc2XSPLZPKRn6N5tGMgT/oe9rpXLrwXBgnovxPApZs7c3rVk9RPgvYbYdYbamnTsIMkG0AN8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699200; c=relaxed/simple; bh=GWsv3jOj5PgnZcHsP+q22FRAkF3pR+epOTcSSgg+DT0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=Eed3PTFGVObiK9/oEGLEcxF4HVUwjWxIPx6RR2QbJKUDpSyXUV1KEtCwvlzUg00pOAPlSnq/oJeD+t+c0Zr0KEApwqPDEAU2IjFRlsJocnKyVNI3vTusTJX3+89E7NVGTRidNykWCoNXcBSzF4QwxqVgabX/Yh6eAsEwCYb1T5U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c4mJXEH6; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="c4mJXEH6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9B71E1F00A3E; Tue, 25 Aug 2026 23:06:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787699198; bh=neQF4B6OBFlvD3OKwkgOO4uxQY+f5mHZZ0FJmjmke2c=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=c4mJXEH6OaS1XkJqy8IBmZ/WbfPTHsD8MAhR3c1Qd8WYRbBmd0fRZ+mbPDKwvYwB+ aJ/2MLlNcBoOz+KfHfkQaV0GJe8oxRy/e86/04Rn6/ngGzL7Mwp7hTlLw5O2y4Rb4w onQ8PrZsz8MSfhOyYsWqKdRx1V8Z14dpxckY9awVlw169+qOtkRC66L+K3LQJeuyV7 FNP3S3tvjlB8uaiUUa0SMhCaJqwkYoeRvFzLwn9Mxj7u4X6lmxBQx5Pmh+j85eGxZR rMZKi8puEh5whPICCKGnR3wN02qJekxHnO2YLseQm9ngijxzh+6Z2znMK0JmnIqwpe Yqw8W1Yoo/hQA== Received: by pali.im (Postfix) id 699CB110A; Wed, 26 Aug 2026 01:06:38 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Paulo Alcantara , Namjae Jeon Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/9] cifs: Fix validation of EAs for WSL reparse points Date: Wed, 26 Aug 2026 01:06:16 +0200 Message-Id: <20260825230622.24617-4-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260825230622.24617-1-pali@kernel.org> References: <20260821214722.q7rkflclyyugdxll@pali> <20260825230622.24617-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable When wsl_to_fattr() is called from readdir() then we should skip validation of WSL EAs because readdir FIND_FIRST/NEXT results do not provide EA values at all. For readdir() reply in this case return DT_UNKNOWN type instead of DT_REG (which is the result of failed WSL EAs validation). When validation is skipped and some required EAs are missing then returns true from wsl_to_fattr() function but do not set fattr->cf_mode. This makes readdir() to return DT_UNKNOWN type in the same way as it is doing NFS reparse point function. This change fixes readdir() result that for some WSL reparse points returns DT_REG due to missing EAs. After this change it returns DT_UNKNOWN, which is better than returning wrong type. Fixes: ef201e8759d2 ("cifs: Validate EAs for WSL reparse points") Signed-off-by: Pali Roh=C3=A1r --- fs/smb/client/reparse.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index 5cc5b0410d48..d4052f6c6e6c 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -1138,27 +1138,39 @@ static bool wsl_to_fattr(struct cifs_open_info_data= *data, u32 tag, struct cifs_fattr *fattr) { struct smb2_file_full_ea_info *ea; + bool ignore_missing_eas =3D false; bool have_xattr_dev =3D false; + umode_t reparse_mode_type =3D 0; u32 next =3D 0; =20 switch (tag) { case IO_REPARSE_TAG_LX_SYMLINK: - fattr->cf_mode |=3D S_IFLNK; + reparse_mode_type =3D S_IFLNK; break; case IO_REPARSE_TAG_LX_FIFO: - fattr->cf_mode |=3D S_IFIFO; + reparse_mode_type =3D S_IFIFO; break; case IO_REPARSE_TAG_AF_UNIX: - fattr->cf_mode |=3D S_IFSOCK; + reparse_mode_type =3D S_IFSOCK; break; case IO_REPARSE_TAG_LX_CHR: - fattr->cf_mode |=3D S_IFCHR; + reparse_mode_type =3D S_IFCHR; break; case IO_REPARSE_TAG_LX_BLK: - fattr->cf_mode |=3D S_IFBLK; + reparse_mode_type =3D S_IFBLK; break; + default: + return false; } =20 + /* + * When reparse buffer is not available then this is from readdir() call + * which does not provide EAs. readdir() can return DT_UNKNOWN type, + * which is signaled by no filling the fattr->cf_mode and returning true. + */ + if (!data->reparse.buf && !data->wsl.eas_len) + ignore_missing_eas =3D true; + if (!data->wsl.eas_len) goto out; =20 @@ -1183,7 +1195,7 @@ static bool wsl_to_fattr(struct cifs_open_info_data *= data, fattr->cf_gid =3D wsl_make_kgid(cifs_sb, v); else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen)) { /* File type in reparse point tag and in xattr mode must match. */ - if (S_DT(fattr->cf_mode) !=3D S_DT(le32_to_cpu(*(__le32 *)v))) + if (S_DT(reparse_mode_type) !=3D S_DT(le32_to_cpu(*(__le32 *)v))) return false; fattr->cf_mode =3D (umode_t)le32_to_cpu(*(__le32 *)v); } else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen)) { @@ -1195,8 +1207,9 @@ static bool wsl_to_fattr(struct cifs_open_info_data *= data, =20 /* Major and minor numbers for char and block devices are mandatory. */ if (!have_xattr_dev && (tag =3D=3D IO_REPARSE_TAG_LX_CHR || tag =3D=3D IO= _REPARSE_TAG_LX_BLK)) - return false; + return ignore_missing_eas; =20 + fattr->cf_mode |=3D reparse_mode_type; return true; } =20 --=20 2.20.1 From nobody Mon Sep 28 05:39:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 E9398345729; Tue, 25 Aug 2026 23:06:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699200; cv=none; b=M8HUN2N8FmGiCoeL7u3vsqpcXrgP0xe2PWuL9k0H2c1bA801LvFWTdFUqUEhJ54gj/GGdrftOnYrVu+RXtGbsVbi2t4eIoFj+1Zh9yGjPEzaRn7r3Q0NH2GeQER/hGQTTqXfPk4fjgDxYkuSGJ7O15YNihYENUAKQ7MMI6heSy0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699200; c=relaxed/simple; bh=7T1imIKO5QjKfyKOa/wE22gU63MG4l2XuQL51nOuXcQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=WXcB7ZGc6qFvqfbddSIa6CoMqyNN8vCnSuy4scVgpWXYl+sPRUaexY/gG4wLKx2Iyah+NASkFuHKJrQop/+L3/eSkBR7BtB7xLAjl+MaI2k+UIYZf5S6qHAlcUmR9aBo6F4sw7iY/t8vE6QQq9B97lKopGOE6qMQe0N3nj9YMeA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N00xddOJ; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="N00xddOJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9F9731F00A3F; Tue, 25 Aug 2026 23:06:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787699198; bh=+Q0/RIbHsAYjAAWNFCwTWF4fj8J6f3yrdQslB6mf/cM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=N00xddOJ96HrqbFEa2uD3a1YQT2c7UYzKmViHcYmrAkiRBu5PKWJn5ewowUAPkRwy xNvJuYMcUd10HtXiUpLx4MDoN9jf1+MvT+x3krIgqFKnwCh1uRdKNG3K0/3mofCpsV i8/SxaV8dAHQeFjIVBE6BW40C6ZpIzW1jpk/LriqBP3ds5DZWZZ3IxnTZxtzlLHYC+ WC2kVBgy7CpoSXXn/s9dYBk2xUxExOzIJaGTwdhVDdB7y+m/WaHB3UtSlU4TlgyaK2 02eo+6tbGdWnMc1VTSUdJxo0n2GmgaovjA4Q7WDU9gUp8YhNaggbmRgm6H7SKgvmox MLzb6o0oVo3ew== Received: by pali.im (Postfix) id 8CCCF11DD; Wed, 26 Aug 2026 01:06:38 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Paulo Alcantara , Namjae Jeon Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/9] cifs: Validate presence of EA $LXMOD for WSL reparse points Date: Wed, 26 Aug 2026 01:06:17 +0200 Message-Id: <20260825230622.24617-5-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260825230622.24617-1-pali@kernel.org> References: <20260821214722.q7rkflclyyugdxll@pali> <20260825230622.24617-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable S_DT part of xattr $LXMOD is mandatory for all WSL reparse points except the WSL symlink and Win32 socket. Microsoft WSL subsystem does not recognize them without xattr $LXMOD too, and treat such inodes as regular files. Fixes: ef201e8759d2 ("cifs: Validate EAs for WSL reparse points") Fixes: 78e26bec4d6d ("smb: client: parse uid, gid, mode and dev from WSL re= parse points") Signed-off-by: Pali Roh=C3=A1r --- fs/smb/client/reparse.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index d4052f6c6e6c..233a445ba811 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -1139,6 +1139,7 @@ static bool wsl_to_fattr(struct cifs_open_info_data *= data, { struct smb2_file_full_ea_info *ea; bool ignore_missing_eas =3D false; + bool have_xattr_mode =3D false; bool have_xattr_dev =3D false; umode_t reparse_mode_type =3D 0; u32 next =3D 0; @@ -1198,6 +1199,7 @@ static bool wsl_to_fattr(struct cifs_open_info_data *= data, if (S_DT(reparse_mode_type) !=3D S_DT(le32_to_cpu(*(__le32 *)v))) return false; fattr->cf_mode =3D (umode_t)le32_to_cpu(*(__le32 *)v); + have_xattr_mode =3D true; } else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen)) { fattr->cf_rdev =3D reparse_mkdev(v); have_xattr_dev =3D true; @@ -1209,6 +1211,16 @@ static bool wsl_to_fattr(struct cifs_open_info_data = *data, if (!have_xattr_dev && (tag =3D=3D IO_REPARSE_TAG_LX_CHR || tag =3D=3D IO= _REPARSE_TAG_LX_BLK)) return ignore_missing_eas; =20 + /* + * S_DT part of xattr MODE is mandatory for all WSL reparse points except= the WSL symlink. + * Microsoft WSL does not recognize them without xattr MODE too (except t= he WSL symlink). + * IO_REPARSE_TAG_AF_UNIX is here an exception because this reparse point= is used by both + * WSL subsystem and native NT/WinAPI subsystems. And NT/WinAPI creates A= F UNIX socket + * without the xattr MODE and recognize it also without the xattr MODE. + */ + if (!have_xattr_mode && (tag !=3D IO_REPARSE_TAG_AF_UNIX && tag !=3D IO_R= EPARSE_TAG_LX_SYMLINK)) + return ignore_missing_eas; + fattr->cf_mode |=3D reparse_mode_type; return true; } --=20 2.20.1 From nobody Mon Sep 28 05:39:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 49D6148F840; Tue, 25 Aug 2026 23:06:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699201; cv=none; b=uNR5jcG4XMu6leALr4nvIe34FNKuM2WT3xfEAva+xJ9xeY6ikK/JRdYkws0N+zK0888bdH+oQUX99gZPV1UXWTKmkPCY++Eg8Q/yGTjKOh4oUvkR9CUrORf6uvMoBHUFNW2Bh8OXuQs/clFbT0hdzMaDSZ2ietqL7V6+27KwzCc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699201; c=relaxed/simple; bh=q2Ei41Y11MFF2/b53uWHu8ayeIPSqaktV1miV0qAvI4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=g06aWqOhnkIdanlI8/sXp+eNQO/0+THQK9OqRwg9dEBnsrpDxZb14vRBZVGNfLXuLV3xbTXBm7HWfqItB10U0wptlPuizJO+VY3dtg0PU3xqRgHHCXQuZBaVo0Rjv5MhttedE+O2zb/501KVx+7dgqLP3CnkdPxMsYJFTkZ5JNQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WVLWZtat; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WVLWZtat" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2E65C1F00AC4; Tue, 25 Aug 2026 23:06:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787699199; bh=FiJW31P5b4O0YSIeFro0cKeuQPEuh4lHSwZF2XN4elM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=WVLWZtatFJBqdsOwFXPvVYuRYxkwNASZ51M06Ry3giclJhrKQ0iugMgqZZxn+HmV4 DQNw/mRNmXKIAsPdZSnpOwpHexnYOzyIfxHLl+6PbPk6AO2tWf6NkXXFtXNkO0zCGo LCG5gOWfvCrCXJgriwumPaumd1HP55sPnyFH6T/j/7dQjAwUZF3CxrBWeSQE+C8UQZ XFj2E8e2lJgIpEN75fOHZE/SJGT7wGoYzmsRPiHzJ306QR/leJ6RL/tmwfFsclxPuH j3afwVTvzFDOCDWlyexR5suR3Eqa6Q+qEab6IkZMyCSCXqHlSfG4FRID1eKln1O5j4 8LhnMpsL5bgAQ== Received: by pali.im (Postfix) id B1D1311E3; Wed, 26 Aug 2026 01:06:38 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Paulo Alcantara , Namjae Jeon Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/9] cifs: Check if server supports EAs before trying to set it for WSL Date: Wed, 26 Aug 2026 01:06:18 +0200 Message-Id: <20260825230622.24617-6-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260825230622.24617-1-pali@kernel.org> References: <20260821214722.q7rkflclyyugdxll@pali> <20260825230622.24617-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable WSL special files store information into EAs. When EAs are not supported on the server filesystem then fast fail in mknod_wsl() function. Signed-off-by: Pali Roh=C3=A1r --- fs/smb/client/reparse.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index 233a445ba811..0829f5373a38 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -683,6 +683,13 @@ static int mknod_wsl(unsigned int xid, struct inode *i= node, struct kvec reparse_iov, xattr_iov; int rc; =20 + /* + * WSL special files store information into EAs. When EAs are not + * supported on the server filesystem then fast fail. + */ + if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_EXTENDED_A= TTRIBUTES)) + return -EOPNOTSUPP; + rc =3D wsl_set_reparse_buf(&buf, mode, symname, cifs_sb, &reparse_iov); if (rc) return rc; --=20 2.20.1 From nobody Mon Sep 28 05:39:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 49E0B48F857; Tue, 25 Aug 2026 23:06:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699202; cv=none; b=BtpA5/BEDY55K7C5bUs7uwJAk9dq+6LgMdHCQaIUualqVb/lzdOw9R5Wn5yv0NZXfFvdji6SgayQTVISexo8UlfszIiEcWp5M2AGcuEsVsukWau/q1U4hv0RKLDW8vMZbDpBtPQVbetz6GPXky021fq+FU/RmmOuPbMToWz28eI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699202; c=relaxed/simple; bh=PR/pUpcB5yaE23zjxWP1ZO3tVoiYnuUAEiEPwcupKZs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=KGwvfzWrChaLHfZlyGsCu/tssRnCvsSxybdvaMKjlq5Xv3SCa7en+e6a/VhoRwBdn94bqDzLojn7kgxDmeceQY/6DFtAKNANBXpNkSlPvM4AuLgQuJuBUwrJz/F4rzh8NR3XBCq3ERkIY+8EgDcxhdfH3i85/L7vBFO32JNmOMw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=f987Usp8; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="f987Usp8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39A4F1F00ACA; Tue, 25 Aug 2026 23:06:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787699199; bh=2fcRQiSc3pci6kKiy80yvqf0h9OfRYTVvHvtZ4XwXqU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=f987Usp8aLC1Q2mWMarpMCr/PlWh7UHwqGSMt60ElYuC2rk0CJK9YB+0qxckXqTjF ZiRxWfuSToqs7velvFDfnolw/SluOG0SNCMo93Iv3xC5AGcwTBhJ368I0vcGKt+Kzi OQ9WyWoXz3K+YnDjUZU0ireR1fkYmEOAetY5SzO2gn/FQlEXvpsNOSAdKnK64Gp/Qn nnmUKDtfOhfZM8HKUUy2SGn20sjTpjutnYCYHp61xgYwcvPp4Y4KdomwRUTeIanqKr QgUpeTiE+5/fKpY+zLofp5xvX9srgzyldgqqBaiu6/UGheEdgefUHhjLzM7C+m3Kxn L6KbUZlGBDiIA== Received: by pali.im (Postfix) id E047613FE; Wed, 26 Aug 2026 01:06:38 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Paulo Alcantara , Namjae Jeon Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 6/9] cifs: Extend ->set_EA() callback to allow operate on reparse point Date: Wed, 26 Aug 2026 01:06:19 +0200 Message-Id: <20260825230622.24617-7-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260825230622.24617-1-pali@kernel.org> References: <20260821214722.q7rkflclyyugdxll@pali> <20260825230622.24617-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Upcoming changes for setting EAs needs to operate on the reparse point iself. This change extend >set_EA() callback with a new boolean parameter to allow it. Signed-off-by: Pali Roh=C3=A1r --- fs/smb/client/cifsglob.h | 1 + fs/smb/client/cifssmb.c | 20 +++++++++++++++++++- fs/smb/client/smb1proto.h | 3 ++- fs/smb/client/smb2ops.c | 6 ++++-- fs/smb/client/xattr.c | 3 ++- 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 79e4e84f8985..c5fdc0138165 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -570,6 +570,7 @@ struct smb_version_operations { const unsigned char *, const unsigned char *, char *, size_t, struct cifs_sb_info *); int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, + bool open_reparse_point, const char *, const void *, const __u16, const struct nls_table *, struct cifs_sb_info *); struct smb_ntsd * (*get_acl)(struct cifs_sb_info *cifssb, struct inode *i= no, diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index a972950b7e09..371dbfc2780f 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -3150,6 +3150,7 @@ struct inode *cifs_create_reparse_inode(struct cifs_o= pen_info_data *data, rc =3D CIFSSMBSetEA(xid, tcon, full_path, + true /* open reparse point */, &ea->ea_data[0], &ea->ea_data[ea->ea_name_length+1], le16_to_cpu(ea->ea_value_length), @@ -6297,7 +6298,8 @@ CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tc= on *tcon, =20 int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, - const char *fileName, const char *ea_name, const void *ea_value, + const char *fileName, bool open_reparse_point, + const char *ea_name, const void *ea_value, const __u16 ea_value_len, const struct nls_table *nls_codepage, struct cifs_sb_info *cifs_sb) { @@ -6311,6 +6313,22 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tco= n *tcon, __u16 params, param_offset, byte_count, offset, count; int remap =3D cifs_remap(cifs_sb); =20 + /* + * On NT systems which supports reparse points, the TRANS2_SET_PATH_INFOR= MATION + * operates on the reparse point itself and not the path location where r= eparse + * point redirects. So the behavior of TRANS2_SET_PATH_INFORMATION is as = if the + * path was opened with OPEN_REPARSE_POINT flag. Hence this SMB1 SetEA fu= nction + * implements only the behavior of "open_reparse_point=3Dtrue" parameter. + * + * TODO: Implement "open_reparse_point=3Dfalse" support for SMB1 SetEA. F= or this + * is needed to call NT OPEN without OPEN_REPARSE_POINT flag and then call + * TRANS2_SET_FILE_INFORMATION. + * + * On systems which do not support reparse points, the behavior of both + * "open_reparse_point=3Dtrue" and "open_reparse_point=3Dfalse" is same. + */ + (void)open_reparse_point; + cifs_dbg(FYI, "In SetEA\n"); SetEARetry: rc =3D smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, diff --git a/fs/smb/client/smb1proto.h b/fs/smb/client/smb1proto.h index f0350fa3f173..8a17350fee7c 100644 --- a/fs/smb/client/smb1proto.h +++ b/fs/smb/client/smb1proto.h @@ -209,7 +209,8 @@ ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct c= ifs_tcon *tcon, const unsigned char *ea_name, char *EAData, size_t buf_size, struct cifs_sb_info *cifs_sb); int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, - const char *fileName, const char *ea_name, + const char *fileName, bool open_reparse_point, + const char *ea_name, const void *ea_value, const __u16 ea_value_len, const struct nls_table *nls_codepage, struct cifs_sb_info *cifs_sb); diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 7d6738ffcb80..d2ba1a3e8ee3 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -1179,7 +1179,8 @@ smb2_query_eas(const unsigned int xid, struct cifs_tc= on *tcon, =20 static int smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, - const char *path, const char *ea_name, const void *ea_value, + const char *path, bool open_reparse_point, + const char *ea_name, const void *ea_value, const __u16 ea_value_len, const struct nls_table *nls_codepage, struct cifs_sb_info *cifs_sb) { @@ -1281,7 +1282,8 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon = *tcon, .path =3D path, .desired_access =3D FILE_WRITE_EA, .disposition =3D FILE_OPEN, - .create_options =3D cifs_create_options(cifs_sb, 0), + .create_options =3D cifs_create_options(cifs_sb, + open_reparse_point ? OPEN_REPARSE_POINT : 0), .fid =3D &fid, .replay =3D !!(retries), }; diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c index 5091f6c0d7fe..93e4cc114d75 100644 --- a/fs/smb/client/xattr.c +++ b/fs/smb/client/xattr.c @@ -154,7 +154,8 @@ static int cifs_xattr_set(const struct xattr_handler *h= andler, =20 if (pTcon->ses->server->ops->set_EA) { rc =3D pTcon->ses->server->ops->set_EA(xid, pTcon, - full_path, name, value, (__u16)size, + full_path, false /* open reparse point */, + name, value, (__u16)size, cifs_sb->local_nls, cifs_sb); if (rc =3D=3D 0) inode_set_ctime_current(inode); --=20 2.20.1 From nobody Mon Sep 28 05:39:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 49C9F48F836; Tue, 25 Aug 2026 23:06:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699201; cv=none; b=h/bvbUr6Zrkg/cz0xzwQ9qeLm4Sk0e+I8De6k+QqJm2YX4rJQ1KUJIg6MiN92FYV4SIlAd/YD+lTQYtf7DYlrKTbqOD5d6T2M8MuwLyFi2hHFkNnTOb0ugcwsIhaXXD8JmdT7+GJMk8/4hNGVnLN+4FoZ01yAh/vsQIhIbYWip8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699201; c=relaxed/simple; bh=ODZY08rGRpu1bMBIuLXXLpP4TGc/a5RVqujJigqPHCI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=NHurZwwtT36Mm20uJFp1V96C7IQ9PNfAESQ5c5vTbuG8Wc7KUtZItSWFHI4LhkhDENKMhvjPDfWpYUXhFb/Y0QwqZ6V/TWp8THRgJ+k6flbpzmf4P8SXHE2if4L8/Cpr3at18I32K98drbr6RlLVxhnA8W+UVUjaOFGqT8FxhyI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GCH1XkNd; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GCH1XkNd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3AFAB1F00ACF; Tue, 25 Aug 2026 23:06:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787699199; bh=quCzjb53wdGaHiRz14QLt+nRl+z3UnuHae+QbIgP0r8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=GCH1XkNdWvm+A4F8R0AErthm1mqFh2hMILNJ8de6WNbEdRa1p5Fp+AYvTRiAEP9B/ KSuIO++Nrp2gSiYmkZaqWFsJx7Y2gdSE5TMMzsBvGVcoExprGn+LK7PM5t6gnlX1Q3 ec5Y6hraZfdCnDyVh8SytHV+Sv7u6Ohv0RfqORArXs2Sl8M6F+EopAxHUwevM6G6rP rBU34SRap/MJsNyi3UD1RsWIbZMj6uv3FXQm8RnXRzDY7oiQnAwbNJ51yZ6THZmetj +xn5mxAqO9GUcbDi0PxguNoC+IXsYJfeYPFBapr/q/ElyxfGP2DJuPcnW4GkFafpvu DUM28/e+QRR7A== Received: by pali.im (Postfix) id 1C1B11B5C; Wed, 26 Aug 2026 01:06:39 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Paulo Alcantara , Namjae Jeon Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 7/9] cifs: Create native Window socket file compatible also with WSL subsystem Date: Wed, 26 Aug 2026 01:06:20 +0200 Message-Id: <20260825230622.24617-8-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260825230622.24617-1-pali@kernel.org> References: <20260821214722.q7rkflclyyugdxll@pali> <20260825230622.24617-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable After creating a native socket via the IO_REPARSE_TAG_AF_UNIX reparse point, try to set also the WSL EA $LXMOD. This makes the native Win32 / NT socket file recognized also under WSL subsystem. WSL subsystem uses same reparse point tag but requires also to be EA $LXMOD set. Fixes: 45a99d5d1173 ("cifs: Add support for creating native Windows sockets= ") Signed-off-by: Pali Roh=C3=A1r --- fs/smb/client/reparse.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index 0829f5373a38..4dd81e40e947 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -399,7 +399,7 @@ static int detect_directory_symlink_target(struct cifs_= sb_info *cifs_sb, =20 static int create_native_socket(const unsigned int xid, struct inode *inod= e, struct dentry *dentry, struct cifs_tcon *tcon, - const char *full_path) + const char *full_path, umode_t mode) { struct reparse_data_buffer buf =3D { .ReparseTag =3D cpu_to_le32(IO_REPARSE_TAG_AF_UNIX), @@ -413,6 +413,10 @@ static int create_native_socket(const unsigned int xid= , struct inode *inode, .iov_base =3D &buf, .iov_len =3D sizeof(buf), }; +#ifdef CONFIG_CIFS_XATTR + const __le64 xattr_mode_val =3D cpu_to_le64(mode); + struct cifs_sb_info *cifs_sb =3D CIFS_SB(inode->i_sb); +#endif struct inode *new; int rc =3D 0; =20 @@ -423,6 +427,28 @@ static int create_native_socket(const unsigned int xid= , struct inode *inode, d_instantiate(dentry, new); else rc =3D PTR_ERR(new); + + /* + * Try to set also optional WSL EA $LXMOD but ignore errors. + * WSL socket and native Win32/NT sockets uses same reparse point + * tag IO_REPARSE_TAG_AF_UNIX. WSL subsystem additionally requires + * EA $LXMOD to be set with the S_IFSOCK value. So setting this EA + * allows native socket to be recognized also by WSL subsystem. + * Note that setting of both EAs and reparse points is not supported + * by NTFS filesystem on Windows 8 / Windows Server 2012 and always + * fails. So ignore failures from this set_EA call. + */ +#ifdef CONFIG_CIFS_XATTR + if (!rc && tcon->ses->server->ops->set_EA && + (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_EXTENDED_AT= TRIBUTES)) + tcon->ses->server->ops->set_EA(xid, tcon, full_path, + true /* open reparse point */, + SMB2_WSL_XATTR_MODE, + &xattr_mode_val, + SMB2_WSL_XATTR_MODE_SIZE, + cifs_sb->local_nls, cifs_sb); +#endif + cifs_free_open_info(&data); return rc; } @@ -732,7 +758,7 @@ int mknod_reparse(unsigned int xid, struct inode *inode, struct smb3_fs_context *ctx =3D CIFS_SB(inode->i_sb)->ctx; =20 if (S_ISSOCK(mode) && !ctx->nonativesocket && ctx->reparse_type !=3D CIFS= _REPARSE_TYPE_NONE) - return create_native_socket(xid, inode, dentry, tcon, full_path); + return create_native_socket(xid, inode, dentry, tcon, full_path, mode); =20 switch (ctx->reparse_type) { case CIFS_REPARSE_TYPE_NFS: --=20 2.20.1 From nobody Mon Sep 28 05:39:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 49BF948CD71; Tue, 25 Aug 2026 23:06:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699202; cv=none; b=YMJ3QwqJLbhVvXlHU0yTQ+hflsRCoLxt/jg17E1bBU/2XpH8b7x9sKUfaQpcXeqsNpOP90y1QgENLixorkLD0ruI4rWdqCxsR4j4042ksPUm0a7/EkjGIFNGK9s4O9Ujo9pgU3S5KhQMb7x4HSEz8ikvH0EeEtiCPpTtXewjBao= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699202; c=relaxed/simple; bh=6zoOok7nDLcFpLtZ3dCqN4LFtkr5+8frvCGRYZIVtNY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=ilVaICdqObqbsPf47lhNxtepTeu6RLN/XQ5v+L/WgO0pZMDGr3r3+FeK0gDmQ4StZkqwjVoceTBUIqmM13oNLksyWzG9rVFv4J0VqrixGqAoUUxWIXxUtog45I4OT4tFhzfohyMpXeQeCdCIhl6zE0spLhYLiWQ4LYIoPyM10gQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Z2RrIqdM; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Z2RrIqdM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3FD961F00ADB; Tue, 25 Aug 2026 23:06:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787699199; bh=qEeKNh0uyUzktaibHMyUiwpjiDLZbdvfOq8fZCJ66Ow=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Z2RrIqdMWSqlsxk9iwYUcj+ncIzTbKHOvT97ja5+ii0lkpC50HEwkAE/Fv0NEfgbV 7T2hNxOYHks7C9X5Tq/UF8l1A98gIj9EktJ3wGUBVlDRfkym/Y3WwwbuanFRBhwoqS AtkznkVmPZz+2iDYBdYj3UGtjA5Kk8cefo5XcVDa4UsMbmZWaSBKRtcV7o1iamRrxx H2oGxnr0aY438RCArpkeZJHxsAQmI/1JlJobbaEV03Al+SxPtPF9TOFKICqPGKwsQV SgHH06dfE+1m9vWo5T/qKKMkTwja6h9IsGcn4K7r/WzHexRosqDGIgMZQp8W1XJg0g objD2fQyzSwjw== Received: by pali.im (Postfix) id 4ACD51D4B; Wed, 26 Aug 2026 01:06:39 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Paulo Alcantara , Namjae Jeon Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 8/9] cifs: Add support for parsing WSL symlinks in version 1 format Date: Wed, 26 Aug 2026 01:06:21 +0200 Message-Id: <20260825230622.24617-9-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260825230622.24617-1-pali@kernel.org> References: <20260821214722.q7rkflclyyugdxll@pali> <20260825230622.24617-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MS-FSCC 2.1.2.7 for IO_REPARSE_TAG_LX_SYMLINK reparse points currently documents only layout version 2 format. IO_REPARSE_TAG_LX_SYMLINK reparse point buffer of layout version 1 format is documented in the newly released Microsoft WSL source code at github: https://github.com/microsoft/WSL/blob/2.5.8/test/windows/DrvFsTests.cpp#L77= 5-L815 Difference between version 1 and version 2 is that version 1 stores the symlink target location into data section of the file, but version 2 stores it directly into the reparse point buffer. This change implements support for parsing WSL symlinks in this layout version 1 format by Linux SMB client and so allow to recognize these type of symlinks like Windows WSL. Signed-off-by: Pali Roh=C3=A1r --- fs/smb/client/cifsproto.h | 1 + fs/smb/client/inode.c | 1 + fs/smb/client/reparse.c | 123 ++++++++++++++++++++++++++++++++------ fs/smb/common/fscc.h | 5 +- 4 files changed, 110 insertions(+), 20 deletions(-) diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 00168839c123..1202934d7b94 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -390,6 +390,7 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs= _sb, char *prefix); char *extract_hostname(const char *unc); char *extract_sharename(const char *unc); int parse_reparse_point(struct reparse_data_buffer *buf, u32 plen, + unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, struct cifs_open_info_data *data); int __cifs_sfu_make_node(unsigned int xid, struct inode *inode, diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index 4ccfc83f7d3b..8d0282599876 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -1175,6 +1175,7 @@ static int reparse_info_to_fattr(struct cifs_open_inf= o_data *data, =20 reparse_buf =3D server->ops->get_reparse_point_buffer(iov, &reparse_len= ); rc =3D parse_reparse_point(reparse_buf, reparse_len, + xid, tcon, cifs_sb, full_path, data); /* * If the reparse point was not handled but it is the diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index 4dd81e40e947..bed6f764c0bc 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -1060,51 +1060,129 @@ static int parse_reparse_native_symlink(struct rep= arse_symlink_data_buffer *sym, } =20 static int parse_reparse_wsl_symlink(struct reparse_wsl_symlink_data_buffe= r *buf, + unsigned int xid, + struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, + const char *full_path, struct cifs_open_info_data *data) { int len =3D le16_to_cpu(buf->ReparseDataLength); int data_offset =3D offsetof(typeof(*buf), Target) - offsetof(typeof(*buf= ), Version); - int symname_utf8_len; + bool free_symname_utf8 =3D false; + struct cifs_open_parms oparms; + struct cifs_io_parms io_parms; + unsigned int symname_utf8_len; + char *symname_utf8 =3D NULL; __le16 *symname_utf16; int symname_utf16_len; + struct cifs_fid fid; + u64 file_size; + __u32 oplock; + int buf_type; + int rc =3D 0; =20 - if (len <=3D data_offset) { + if (len < data_offset) { cifs_dbg(VFS, "srv returned malformed wsl symlink buffer\n"); - return smb_EIO2(smb_eio_trace_reparse_wsl_symbuf, + rc =3D smb_EIO2(smb_eio_trace_reparse_wsl_symbuf, len, data_offset); + goto out; } =20 - /* MS-FSCC 2.1.2.7 defines layout of the Target field only for Version 2.= */ u32 version =3D le32_to_cpu(buf->Version); + switch (version) { + case 1: + /* + * Layout version 1 stores the symlink target in the data section of + * the file encoded in UTF-8 without trailing null-term byte. + */ + + file_size =3D data->contains_posix_file_info ? + le64_to_cpu(data->posix_fi.EndOfFile) : + le64_to_cpu(data->fi.EndOfFile); + + free_symname_utf8 =3D true; + symname_utf8_len =3D file_size; + symname_utf8 =3D kmalloc(symname_utf8_len, GFP_KERNEL); + if (!symname_utf8) { + rc =3D -ENOMEM; + goto out; + } + + oparms =3D CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_DATA, + FILE_OPEN, CREATE_NOT_DIR | OPEN_REPARSE_POINT, + ACL_NO_MODE); + oparms.fid =3D &fid; + oplock =3D tcon->ses->server->oplocks ? REQ_OPLOCK : 0; + rc =3D tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); + if (rc) + goto out; + + buf_type =3D CIFS_NO_BUFFER; + io_parms =3D (struct cifs_io_parms) { + .netfid =3D fid.netfid, + .pid =3D current->tgid, + .tcon =3D tcon, + .offset =3D 0, + .length =3D symname_utf8_len, + }; + rc =3D tcon->ses->server->ops->sync_read(xid, &fid, &io_parms, + &symname_utf8_len, + &symname_utf8, + &buf_type); + if (!rc && symname_utf8_len !=3D file_size) + rc =3D -EIO; =20 - if (version !=3D 2) { + tcon->ses->server->ops->close(xid, tcon, &fid); + + if (rc) { + cifs_dbg(VFS, "cannot read wsl symlink target location: %d\n", rc); + goto out; + } + + break; + case 2: + /* + * Layout version 2 stores the symlink target in the reparse buffer + * field Target encoded in UTF-8 without trailing null-term byte. + */ + symname_utf8_len =3D len - data_offset; + symname_utf8 =3D buf->Target; + break; + default: cifs_dbg(VFS, "srv returned unsupported wsl symlink version %u\n", versi= on); return smb_EIO1(smb_eio_trace_reparse_wsl_ver, version); } =20 - /* Target for Version 2 is in UTF-8 but without trailing null-term byte */ - symname_utf8_len =3D len - data_offset; + if (symname_utf8_len =3D=3D 0) { + cifs_dbg(VFS, "srv returned empty wsl symlink target location\n"); + rc =3D -EIO; + goto out; + } + /* * Check that buffer does not contain null byte * because Linux cannot process symlink with null byte. */ - size_t ulen =3D strnlen(buf->Target, symname_utf8_len); + size_t ulen =3D strnlen(symname_utf8, symname_utf8_len); =20 if (ulen !=3D symname_utf8_len) { cifs_dbg(VFS, "srv returned null byte in wsl symlink target location\n"); - return smb_EIO2(smb_eio_trace_reparse_wsl_ver, + rc =3D smb_EIO2(smb_eio_trace_reparse_wsl_ver, ulen, symname_utf8_len); + goto out; } symname_utf16 =3D kzalloc(symname_utf8_len * 2, GFP_KERNEL); - if (!symname_utf16) - return -ENOMEM; - symname_utf16_len =3D utf8s_to_utf16s(buf->Target, symname_utf8_len, + if (!symname_utf16) { + rc =3D -ENOMEM; + goto out; + } + symname_utf16_len =3D utf8s_to_utf16s(symname_utf8, symname_utf8_len, UTF16_LITTLE_ENDIAN, (wchar_t *) symname_utf16, symname_utf8_len * 2); if (symname_utf16_len < 0) { kfree(symname_utf16); - return symname_utf16_len; + rc =3D symname_utf16_len; + goto out; } symname_utf16_len *=3D 2; /* utf8s_to_utf16s() returns number of u16 item= s, not byte length */ =20 @@ -1112,14 +1190,23 @@ static int parse_reparse_wsl_symlink(struct reparse= _wsl_symlink_data_buffer *buf symname_utf16_len, true, cifs_sb->local_nls); kfree(symname_utf16); - if (!data->symlink_target) - return -ENOMEM; + if (!data->symlink_target) { + rc =3D -ENOMEM; + goto out; + } =20 - return 0; +out: + if (free_symname_utf8) + kfree(symname_utf8); + + return rc; } =20 int parse_reparse_point(struct reparse_data_buffer *buf, - u32 plen, struct cifs_sb_info *cifs_sb, + u32 plen, + unsigned int xid, + struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, const char *full_path, struct cifs_open_info_data *data) { @@ -1137,7 +1224,7 @@ int parse_reparse_point(struct reparse_data_buffer *b= uf, case IO_REPARSE_TAG_LX_SYMLINK: return parse_reparse_wsl_symlink( (struct reparse_wsl_symlink_data_buffer *)buf, - cifs_sb, data); + xid, tcon, cifs_sb, full_path, data); case IO_REPARSE_TAG_AF_UNIX: case IO_REPARSE_TAG_LX_FIFO: case IO_REPARSE_TAG_LX_CHR: diff --git a/fs/smb/common/fscc.h b/fs/smb/common/fscc.h index e46d3379b779..dee4fb6af16a 100644 --- a/fs/smb/common/fscc.h +++ b/fs/smb/common/fscc.h @@ -69,12 +69,13 @@ struct reparse_nfs_data_buffer { __u8 DataBuffer[]; } __packed; =20 -/* For IO_REPARSE_TAG_LX_SYMLINK - see MS-FSCC 2.1.2.7 */ +/* For IO_REPARSE_TAG_LX_SYMLINK - see MS-FSCC 2.1.2.7 and + * https://github.com/microsoft/WSL/blob/2.5.8/test/windows/DrvFsTests.cpp= #L775-L815 */ struct reparse_wsl_symlink_data_buffer { __le32 ReparseTag; __le16 ReparseDataLength; __u16 Reserved; - __le32 Version; /* Always 2 */ + __le32 Version; /* 1 - stores symlink path in file data section; 2 - stor= es symlink path in Target[] field */ __u8 Target[]; /* Variable Length UTF-8 string without nul-term */ } __packed; =20 --=20 2.20.1 From nobody Mon Sep 28 05:39:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 A44B44908D1; Tue, 25 Aug 2026 23:06:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699202; cv=none; b=QYb7yEMKY2eUqWQ1XzMCPypNzaKUJD/9RHVGAiS+Qkv4DrCa4Hnx09/fIPcZ64q51WV9poQj+eNDbKB0wJjH41wLyuupjpWWJYgZ1MYhhvo0YW+biGbKSg5X6EdIr5wETRuLSEgm0/M+1YRA8UZ26b46Rs6+zEMfLd1pz2CIqIc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787699202; c=relaxed/simple; bh=uJl6+u4IT6R6cYAnu6cpKW7n0ib/6o30MU37gqEZi9s=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=tGBeBSnHY4LKh/xe/9LeUuO/BBec5vYJlijPX2hlaLMTdGgWskazaxjEWDVBhzTbl6Qz5bM+p1OLwcWV/pgtppipNvHEDKSlXdaSoSICknNyhl8bI4Kgux6m5z9uJQO0m5lhAZcpHXLukzK/57NYuF1TyYIgPn/FZa5o5jmVah4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hj6WRJdB; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Hj6WRJdB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 524D51F00ADE; Tue, 25 Aug 2026 23:06:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787699199; bh=VkFv/3g462ZHWt9QeDtU8ukZ5sPoH60t9HVUIUoRDVI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Hj6WRJdBg/DGaj3fNo0ZXLFCnq/AvwpdprpXrcRg+tlyADJaFszOh1ST5wkqX0QYF IrfrS1zffuYTHyahwW7HWxNhK8e/Y8nW593d8QevOxenWuDGQUfbrwIOxAJI3epO6G O5D1LI7iol+XBEtv2THCkvbVQy/88pv647tWlglGcFybf8PhFaOik4/wUB6qwzNBxe kUbzufVZ+7zgrrSbm5ghy1ZvbK9BN5gBNcMxPwq+gYIyuM4qDKlL6ZxY17heIGVr11 3odvaJu1aeSEQki1xAYN4IisJ1+JdfkCzqkV4rwereQq0WSHnU1VxgzcxaglQwvBNN R+PW+10PhYrYg== Received: by pali.im (Postfix) id 6E6FA1EB4; Wed, 26 Aug 2026 01:06:39 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Paulo Alcantara , Namjae Jeon Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 9/9] cifs: Add support for creating WSL symlinks in version 1 format Date: Wed, 26 Aug 2026 01:06:22 +0200 Message-Id: <20260825230622.24617-10-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260825230622.24617-1-pali@kernel.org> References: <20260821214722.q7rkflclyyugdxll@pali> <20260825230622.24617-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add a new mount option -o symlink=3Dwsl1 which cause that all newly created symlinks would be of WSL style in layout version 1 format. This type of symlinks is supported by all WSL versions. Existing mount option -o symlink=3Dwsl will be now an alias to -o symlink=3Dwsl2 which creates symlinks in layout version 2 format. Signed-off-by: Pali Roh=C3=A1r --- fs/smb/client/cifsglob.h | 9 +++-- fs/smb/client/fs_context.c | 11 ++++-- fs/smb/client/fs_context.h | 3 +- fs/smb/client/link.c | 3 +- fs/smb/client/reparse.c | 74 ++++++++++++++++++++++++++++++++------ 5 files changed, 82 insertions(+), 18 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index c5fdc0138165..66d4370f37dc 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -190,7 +190,8 @@ enum cifs_symlink_type { CIFS_SYMLINK_TYPE_MFSYMLINKS, CIFS_SYMLINK_TYPE_SFU, CIFS_SYMLINK_TYPE_NFS, - CIFS_SYMLINK_TYPE_WSL, + CIFS_SYMLINK_TYPE_WSL1, + CIFS_SYMLINK_TYPE_WSL2, }; =20 static inline const char *cifs_symlink_type_str(enum cifs_symlink_type typ= e) @@ -208,8 +209,10 @@ static inline const char *cifs_symlink_type_str(enum c= ifs_symlink_type type) return "sfu"; case CIFS_SYMLINK_TYPE_NFS: return "nfs"; - case CIFS_SYMLINK_TYPE_WSL: - return "wsl"; + case CIFS_SYMLINK_TYPE_WSL1: + return "wsl1"; + case CIFS_SYMLINK_TYPE_WSL2: + return "wsl2"; default: return "unknown"; } diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index abc29500a664..3e8e4b43690a 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -376,7 +376,9 @@ static const match_table_t symlink_flavor_tokens =3D { { Opt_symlink_mfsymlinks, "mfsymlinks" }, { Opt_symlink_sfu, "sfu" }, { Opt_symlink_nfs, "nfs" }, - { Opt_symlink_wsl, "wsl" }, + { Opt_symlink_wsl1, "wsl1" }, + { Opt_symlink_wsl2, "wsl2" }, + { Opt_symlink_wsl2, "wsl" }, /* wsl - alias for wsl2 */ { Opt_symlink_err, NULL }, }; =20 @@ -407,8 +409,11 @@ static int parse_symlink_flavor(struct fs_context *fc,= char *value, case Opt_symlink_nfs: ctx->symlink_type =3D CIFS_SYMLINK_TYPE_NFS; break; - case Opt_symlink_wsl: - ctx->symlink_type =3D CIFS_SYMLINK_TYPE_WSL; + case Opt_symlink_wsl1: + ctx->symlink_type =3D CIFS_SYMLINK_TYPE_WSL1; + break; + case Opt_symlink_wsl2: + ctx->symlink_type =3D CIFS_SYMLINK_TYPE_WSL2; break; default: cifs_errorf(fc, "bad symlink=3D option: %s\n", value); diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h index a80a5caff23c..56bbb20a30a3 100644 --- a/fs/smb/client/fs_context.h +++ b/fs/smb/client/fs_context.h @@ -72,7 +72,8 @@ enum cifs_symlink_parm { Opt_symlink_mfsymlinks, Opt_symlink_sfu, Opt_symlink_nfs, - Opt_symlink_wsl, + Opt_symlink_wsl1, + Opt_symlink_wsl2, Opt_symlink_err }; =20 diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c index 8d5d6aca742a..fd7203aa0917 100644 --- a/fs/smb/client/link.c +++ b/fs/smb/client/link.c @@ -604,7 +604,8 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *ino= de, =20 case CIFS_SYMLINK_TYPE_NATIVE: case CIFS_SYMLINK_TYPE_NFS: - case CIFS_SYMLINK_TYPE_WSL: + case CIFS_SYMLINK_TYPE_WSL1: + case CIFS_SYMLINK_TYPE_WSL2: if (CIFS_REPARSE_SUPPORT(pTcon)) { rc =3D create_reparse_symlink(xid, inode, direntry, pTcon, full_path, symname); diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index bed6f764c0bc..8db3e4917788 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -22,7 +22,7 @@ static int mknod_nfs(unsigned int xid, struct inode *inod= e, static int mknod_wsl(unsigned int xid, struct inode *inode, struct dentry *dentry, struct cifs_tcon *tcon, const char *full_path, umode_t mode, dev_t dev, - const char *symname); + const char *symname, int symver); =20 static int create_native_symlink(const unsigned int xid, struct inode *ino= de, struct dentry *dentry, struct cifs_tcon *tcon, @@ -43,8 +43,10 @@ int create_reparse_symlink(const unsigned int xid, struc= t inode *inode, return create_native_symlink(xid, inode, dentry, tcon, full_path, symnam= e); case CIFS_SYMLINK_TYPE_NFS: return mknod_nfs(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symnam= e); - case CIFS_SYMLINK_TYPE_WSL: - return mknod_wsl(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symnam= e); + case CIFS_SYMLINK_TYPE_WSL1: + return mknod_wsl(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symnam= e, 1); + case CIFS_SYMLINK_TYPE_WSL2: + return mknod_wsl(xid, inode, dentry, tcon, full_path, S_IFLNK, 0, symnam= e, 2); default: return -EOPNOTSUPP; } @@ -554,6 +556,7 @@ static int mknod_nfs(unsigned int xid, struct inode *in= ode, =20 static int wsl_set_reparse_buf(struct reparse_data_buffer **buf, mode_t mode, const char *symname, + int symver, struct cifs_sb_info *cifs_sb, struct kvec *iov) { @@ -589,15 +592,20 @@ static int wsl_set_reparse_buf(struct reparse_data_bu= ffer **buf, kfree(symname_utf16); return -ENOMEM; } - /* Version field must be set to 2 (MS-FSCC 2.1.2.7) */ - symlink_buf->Version =3D cpu_to_le32(2); - /* Target for Version 2 is in UTF-8 but without trailing null-term byte = */ + symlink_buf->Version =3D cpu_to_le32(symver); + /* Target is in UTF-8 but without trailing null-term byte */ symname_utf8_len =3D utf16s_to_utf8s((wchar_t *)symname_utf16, symname_u= tf16_len/2, UTF16_LITTLE_ENDIAN, symlink_buf->Target, symname_utf8_maxlen); *buf =3D (struct reparse_data_buffer *)symlink_buf; - buf_len =3D sizeof(struct reparse_wsl_symlink_data_buffer) + symname_utf= 8_len; + buf_len =3D sizeof(struct reparse_wsl_symlink_data_buffer); + /* + * Layout version 2 stores the symlink target in the reparse point buffe= r. + * Layout version 1 stores the symlink target in the data section of the= file. + */ + if (symver =3D=3D 2) + buf_len +=3D symname_utf8_len; kfree(symname_utf16); break; default: @@ -698,7 +706,7 @@ static int wsl_set_xattrs(struct inode *inode, umode_t = _mode, static int mknod_wsl(unsigned int xid, struct inode *inode, struct dentry *dentry, struct cifs_tcon *tcon, const char *full_path, umode_t mode, dev_t dev, - const char *symname) + const char *symname, int symver) { struct cifs_sb_info *cifs_sb =3D CIFS_SB(inode->i_sb); struct cifs_open_info_data data; @@ -707,6 +715,12 @@ static int mknod_wsl(unsigned int xid, struct inode *i= node, struct inode *new; unsigned int len; struct kvec reparse_iov, xattr_iov; + struct cifs_open_parms oparms; + struct cifs_io_parms io_parms; + unsigned int bytes_written; + struct kvec symv1_iov[2]; + struct cifs_fid fid; + __u32 oplock; int rc; =20 /* @@ -716,7 +730,7 @@ static int mknod_wsl(unsigned int xid, struct inode *in= ode, if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_EXTENDED_A= TTRIBUTES)) return -EOPNOTSUPP; =20 - rc =3D wsl_set_reparse_buf(&buf, mode, symname, cifs_sb, &reparse_iov); + rc =3D wsl_set_reparse_buf(&buf, mode, symname, symver, cifs_sb, &reparse= _iov); if (rc) return rc; =20 @@ -741,6 +755,46 @@ static int mknod_wsl(unsigned int xid, struct inode *i= node, &data, inode->i_sb, xid, tcon, full_path, false, &reparse_iov, &xattr_iov); + if (!IS_ERR(new) && mode =3D=3D S_IFLNK && symver =3D=3D 1) { + /* + * WSL symlink layout version 1 stores the symlink target + * location into the data section of the file. + * Store it now after the reparse point file was created. + * The target location was allocated into the buf but iov + * size filled in reparse_iov by wsl_set_reparse_buf() was + * set to smaller so the created reparse point does not + * contain it. + */ + oparms =3D CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA, + FILE_OPEN, CREATE_NOT_DIR | OPEN_REPARSE_POINT, + ACL_NO_MODE); + oparms.fid =3D &fid; + oplock =3D tcon->ses->server->oplocks ? REQ_OPLOCK : 0; + rc =3D tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); + if (!rc) { + symv1_iov[1].iov_base =3D ((struct reparse_wsl_symlink_data_buffer *)bu= f)->Target; + symv1_iov[1].iov_len =3D strlen((const char *)symv1_iov[1].iov_base); + io_parms =3D (struct cifs_io_parms) { + .netfid =3D fid.netfid, + .pid =3D current->tgid, + .tcon =3D tcon, + .offset =3D 0, + .length =3D symv1_iov[1].iov_len, + }; + rc =3D tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, + &bytes_written, + symv1_iov, + ARRAY_SIZE(symv1_iov)-1); + if (bytes_written !=3D symv1_iov[1].iov_len) + rc =3D -EIO; + tcon->ses->server->ops->close(xid, tcon, &fid); + } + if (rc) { + tcon->ses->server->ops->unlink(xid, tcon, full_path, cifs_sb, NULL); + iput(new); + new =3D ERR_PTR(rc); + } + } if (!IS_ERR(new)) d_instantiate(dentry, new); else @@ -764,7 +818,7 @@ int mknod_reparse(unsigned int xid, struct inode *inode, case CIFS_REPARSE_TYPE_NFS: return mknod_nfs(xid, inode, dentry, tcon, full_path, mode, dev, NULL); case CIFS_REPARSE_TYPE_WSL: - return mknod_wsl(xid, inode, dentry, tcon, full_path, mode, dev, NULL); + return mknod_wsl(xid, inode, dentry, tcon, full_path, mode, dev, NULL, 0= ); default: return -EOPNOTSUPP; } --=20 2.20.1