[PATCH 0/7] cifs: Improve client SFU support for special files

From: Pali Rohár
Date: Thu Sep 12 2024 - 08:06:34 EST


This patch series implement full support for SFU-style of special files
(fifo, socket, block, char, symlink) and makes client cifs's -o sfu
mount option to be fully compatible with SFU.

Before this patch series, kernel cifs client was able to:
* create new char and block devices in SFU-style, and detect them
* detect existing SFU fifo, but no create/mkfifo SFU functionality
* detect symlink SFU symlink, but no readlink() functionality and
neither no create SFU symlink functionality

And it was able to create some SFU-incompatible sockets and fifos (when
-o sfu was specified) which were not recognized by neither original MS
SFU implementation and neither by others.

This patch series implements missing functionality, which is:
* detect existing SFU sockets
* create new SFU sockets
* create new SFU fifos
* create new SFU symlink
* readlink() support for existing SFU symlinks

In following pragraphs are some details about these SFU special files
which usage on Linux has to be activated by -o sfu mount option.

SFU-style fifo is empty file with system attribute set. This format is
used by old Microsoft POSIX subsystem and later also by OpenNT/Interix
subsystem (which replaced Microsoft POSIX subsystem and is part of
Microsoft SFU). OpenNT is previous name of Interix versions 1.x/2.x.
Microsoft POSIX subsystem is available since the first Windows NT
version 3.1, and it was replaced by Interix since Windows XP. Interix
continue to use this format up to the its last released version for
Windows 8 / Server 2012 (part of Subsystem for UNIX-based Applications).
Hence these SFU-style fifos are for very long time unified and widely
supported.

SFU-style socket is file which has system attribute set and file content
is one zero byte.

SFU-style symlink is file which has system attribute set and file content
is buffer "IntxLNK\1" (8th byte is 0x01) followed by the target location
encoded in little endian UCS-2/UTF-16. There is no trailing nul.

SFU-style char or block device is file which has system attribute set
and file content is buffer "IntxBLK\0" or "IntxCHR\0" (8th byte is 0x00)
followed by major and minor numbers encoded in twos 64-bit little endian.

Format of SFU-style sockets, symlinks, char and block devices was
introduced in Interix 3.0 subsystem, as part of the Microsoft SFU 3.0
and is used also by all later versions, up to the Windows 8 / Server 2012
(part of Subsystem for UNIX-based Applications) where it was deprecated.
Previous OpenNT/Interix versions had no support for UNIX domain sockets
(and socket files), symlinks or possibility to create character or block
devices (but they had block/char devices in-memory, returned by stat()).

Microsoft NFS server up to the version included in Windows Server 2008 R2
also uses this SFU-style format of special files when storing them on
local filesystem. Later Microsoft NFS server versions (starting in
Windows Server 2012) use new NFS reparse format, which Interix subsystem
(included in SFU or SUA) does not understand.

Even SFU-style of special files is old format, it has one big advantage,
this format does not require any support on SMB/CIFS server of special
files, as everything is stored only in the file content. The only
requirement from server is support for system attribute. So this allows
to store special files also on FAT filesystem.

This patch series makes cifs -o sfu mount option compatible with
SFU-style of special files, and so compatible with the latest SFU/SUA.

Note that -o sfu is by default turned off, so these changes should have
no effect on default cifs mounts.

Manually tested with MS SFU 3.5 (for Windows XP) and MS SUA 6.2 (latest
released version of Interix) that interop works correctly, special files
created by POSIX/Interix application can be recognized by Linux cifs
client (exported over MS SMB) with these patches (and vice-versa setup,
created by Linux cifs client and recognized in POSIX/Interix subsystem).

Manually tested that old Linux 4.19 cifs client version can recognize
SFU-style of special files created by Linux cifs client this patch
series (except socket, which is unsupported in this Linux cifs version).

Patch series is based on the latest upstream tag v6.11-rc7.

Pali Rohár (7):
cifs: Fix recognizing SFU symlinks
cifs: Add support for reading SFU symlink location
cifs: Put explicit zero byte into SFU block/char types
cifs: Show debug message when SFU Fifo type was detected
cifs: Recognize SFU socket type
cifs: Fix creating of SFU fifo and socket special files
cifs: Add support for creating SFU symlinks

fs/smb/client/cifspdu.h | 6 ---
fs/smb/client/cifsproto.h | 4 ++
fs/smb/client/cifssmb.c | 8 ++--
fs/smb/client/fs_context.c | 13 ++++---
fs/smb/client/inode.c | 42 ++++++++++++++++++--
fs/smb/client/link.c | 3 ++
fs/smb/client/smb1ops.c | 2 +-
fs/smb/client/smb2ops.c | 78 ++++++++++++++++++++++++++++----------
8 files changed, 117 insertions(+), 39 deletions(-)

--
2.20.1