linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/35] cifs: Fix SMB rmdir() and unlink() against Windows SMB servers
@ 2025-08-31 12:35 Pali Rohár
  2025-08-31 12:35 ` [PATCH 01/35] cifs: Fix and improve cifs_is_path_accessible() function Pali Rohár
                   ` (35 more replies)
  0 siblings, 36 replies; 40+ messages in thread
From: Pali Rohár @ 2025-08-31 12:35 UTC (permalink / raw)
  To: Steve French, Paulo Alcantara, ronnie sahlberg; +Cc: linux-cifs, linux-kernel

This patch series improves Linux rmdir() and unlink() syscalls called on
SMB mounts exported from Windows SMB servers which do not implement
POSIX semantics of the file and directory removal.

This patch series should have no impact and no function change when
communicating with the POSIX SMB servers, as they should implement
proper rmdir and unlink logic.

When issuing remove path command against non-POSIX / Windows SMB server,
it let the directory entry which is being removed in the directory until
all users / clients close all handles / references to that path.

POSIX requires from rmdir() and unlink() syscalls that after successful
call, the requested path / directory entry is released and allows to
create a new file or directory with that name. This is currently not
working against non-POSIX / Windows SMB servers.

To workaround this problem fix and improve existing cifs silly rename
code and extend it also to SMB2 and SMB3 dialects when communicating
with Windows SMB servers. Silly rename is applied only when it is
necessary (when some other client has opened file or directory).
If no other client has the file / dir open then silly rename is not
used.

With this patch series, after successful rmdir() or unlink() call from
Linux userspace application, the path is released, it is not visible in
the followup readdir() call, also stat() properly returns ENOENT and it
is possible to call creat() or mkdir() on the same path to create new
node. Silly rename is used to ensure that path is released.

Before this change, the original path was visible in the readdir() call
and create() or mkdir() was failing with EEXIST, even rmdir() or
unlink() on that path returned success.


Test cases when "path" is opened on Windows server by other client, so
path cannot be removed.

1.
  unlink("path");
  mkdir("path");

  before: unlink returns success but mkdir returns EEXIST.
  after: unlink returns success, mkdir creates new directory and the
  orignal one is silly renamed.

2.
  unlink("path")
  open("path") without O_CREAT
  mkdir("path")

  before: unlink returns success, open returns ENOENT and mkdir returns
  EEXIST.
  after: unlink returns success, open returns ENOENT, mkdir creates
  new directory and the original path is silly renamed.

3.
  unlink("path")
  stat("path")
  mkdir("path")

  before: unlink returns success, stat returns ENOENT and mkdir returns
  EEXIST.
  after: unlink returns success, stat returns ENOENT, mkdir creates new
  directory and the original path is silly renamed.

4.
  unlink("path")
  stat("path")
  open("path") with O_CREAT | O_EXCL

  before: unlink returns success, stat returns ENOENT and open returns
  EEXIST.
  after: unlink returns success, stat returns ENOENT, open creates new
  file and the original path is silly renamed.

5.
  unlink("path")
  readdir("parent_of_path")

  before: unlink returns success but readdir returns entry corresponding
  to path.
  after: unlink returns success, original path is silly renamed and
  readdir returns the entry under new silly name.


Test case when "tmp_path" on the Windows server was created (or opened)
as a exclusive temporary file with the DELETE_PENDING flag set:

Before:

  stat("tmp_path") - returns ENOENT
  mkdir("tmp_path") - returns EEXIST
  open("tmp_path") without O_CREAT - returns ENOENT
  open("tmp_path") with O_CREAT | O_EXCL - return EEXIST
  unlink("tmp_path") - returns ENOENT
  readdir(parent_of_tmp_path) - returns the "tmp_path" entry

After:

  stat("tmp_path") - success
  mkdir("tmp_path") - returns EEXIST
  open("tmp_path") without O_CREAT - returns EBUSY
  open("tmp_path") with O_CREAT | O_EXCL - return EEXIST
  unlink("tmp_path") - returns EBUSY
  readdir(parent_of_tmp_path) - returns the "tmp_path" entry

The difference is in stat(), open() and unlink() syscalls. Now Linux
applications can stat such files, so file attributes are now visible in
"ls -l -a" output, but trying to open / modify / delete them fails with
EBUSY instead of ENOENT.


Pali Rohár (35):
  cifs: Fix and improve cifs_is_path_accessible() function
  cifs: Allow fallback code in smb_set_file_info() also for directories
  cifs: Add fallback code path for cifs_mkdir_setinfo()
  cifs: Remove code for querying FILE_INFO_STANDARD via
    CIFSSMBQPathInfo()
  cifs: Remove CIFSSMBSetPathInfoFB() fallback function
  cifs: Remove cifs_backup_query_path_info() and replace it by
    cifs_query_path_info()
  cifs: Change translation of STATUS_DELETE_PENDING to -EBUSY
  cifs: Improve SMB2+ stat() to work also for paths in DELETE_PENDING
    state
  cifs: Improve SMB1 stat() to work also for paths in DELETE_PENDING
    state
  cifs: Improve detect_directory_symlink_target() function
  cifs: Fix random name construction for cifs_rename_pending_delete()
  cifs: Fix DELETE comments in cifs_rename_pending_delete()
  cifs: Avoid dynamic memory allocation of FILE_BASIC_INFO buffer in
    cifs_rename_pending_delete()
  cifs: Extend CIFSSMBRenameOpenFile() function for overwrite parameter
  cifs: Do not try to overwrite existing sillyname in
    cifs_rename_pending_delete()
  cifs: Add comments for DeletePending assignments in open functions
  cifs: Use NT_STATUS_DELETE_PENDING for filling fi.DeletePending in
    cifs_query_path_info()
  cifs: Do not set NumberOfLinks to 1 from open or query calls
  cifs: Fix cifs_rename_pending_delete() for files with more hardlinks
  cifs: Fix permission logic in cifs_rename_pending_delete()
  cifs: Propagate error code from CIFSSMBSetFileInfo() to
    cifs_rename_pending_delete()
  cifs: Improve cifs_rename_pending_delete() to work without the
    PASSTHRU support
  cifs: Fix SMBLegacyOpen() function
  cifs: Add a new callback set_file_disp() for setting file disposition
    (delete pending state)
  cifs: Add a new callback rename_opened_file() for renaming an opened
    file
  cifs: Add SMB2+ support into cifs_rename_pending_delete() function.
  cifs: Move SMB1 usage of CIFSPOSIXDelFile() from inode.c to cifssmb.c
  cifs: Fix smb2_unlink() to fail on directory
  cifs: Fix smb2_rmdir() on reparse point
  cifs: Simplify SMB2_OP_DELETE API usage
  cifs: Deduplicate smb2_unlink() and smb2_rmdir() into one common
    function
  cifs: Use cifs_rename_pending_delete() fallback also for rmdir()
  cifs: Add a new open flag CREATE_OPTION_EXCLUSIVE to open with deny
    all shared reservation
  cifs: Use CREATE_OPTION_EXCLUSIVE when opening file/dir for SMB2+
    non-POSIX unlink/rmdir
  cifs: Use CREATE_OPTION_EXCLUSIVE when doing SMB1 rmdir on NT server

 fs/smb/client/cifsglob.h     |  11 +-
 fs/smb/client/cifspdu.h      |   5 +
 fs/smb/client/cifsproto.h    |   6 +-
 fs/smb/client/cifssmb.c      | 228 +++++++++++++----------
 fs/smb/client/inode.c        | 346 ++++++++++++++++-------------------
 fs/smb/client/netmisc.c      |   2 +-
 fs/smb/client/reparse.c      |  75 +++-----
 fs/smb/client/smb1ops.c      |  84 +++++++--
 fs/smb/client/smb2glob.h     |   1 +
 fs/smb/client/smb2inode.c    | 264 +++++++++++++++++++++++---
 fs/smb/client/smb2maperror.c |   2 +-
 fs/smb/client/smb2ops.c      |  24 +++
 fs/smb/client/smb2pdu.c      |  51 +++++-
 fs/smb/client/smb2proto.h    |   6 +
 14 files changed, 704 insertions(+), 401 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2025-09-02 16:30 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-31 12:35 [PATCH 00/35] cifs: Fix SMB rmdir() and unlink() against Windows SMB servers Pali Rohár
2025-08-31 12:35 ` [PATCH 01/35] cifs: Fix and improve cifs_is_path_accessible() function Pali Rohár
2025-08-31 12:35 ` [PATCH 02/35] cifs: Allow fallback code in smb_set_file_info() also for directories Pali Rohár
2025-08-31 12:35 ` [PATCH 03/35] cifs: Add fallback code path for cifs_mkdir_setinfo() Pali Rohár
2025-08-31 12:35 ` [PATCH 04/35] cifs: Remove code for querying FILE_INFO_STANDARD via CIFSSMBQPathInfo() Pali Rohár
2025-08-31 12:35 ` [PATCH 05/35] cifs: Remove CIFSSMBSetPathInfoFB() fallback function Pali Rohár
2025-08-31 12:35 ` [PATCH 06/35] cifs: Remove cifs_backup_query_path_info() and replace it by cifs_query_path_info() Pali Rohár
2025-08-31 12:35 ` [PATCH 07/35] cifs: Change translation of STATUS_DELETE_PENDING to -EBUSY Pali Rohár
2025-08-31 12:35 ` [PATCH 08/35] cifs: Improve SMB2+ stat() to work also for paths in DELETE_PENDING state Pali Rohár
2025-08-31 12:35 ` [PATCH 09/35] cifs: Improve SMB1 " Pali Rohár
2025-08-31 12:35 ` [PATCH 10/35] cifs: Improve detect_directory_symlink_target() function Pali Rohár
2025-08-31 12:35 ` [PATCH 11/35] cifs: Fix random name construction for cifs_rename_pending_delete() Pali Rohár
2025-08-31 12:35 ` [PATCH 12/35] cifs: Fix DELETE comments in cifs_rename_pending_delete() Pali Rohár
2025-08-31 12:35 ` [PATCH 13/35] cifs: Avoid dynamic memory allocation of FILE_BASIC_INFO buffer " Pali Rohár
2025-08-31 12:35 ` [PATCH 14/35] cifs: Extend CIFSSMBRenameOpenFile() function for overwrite parameter Pali Rohár
2025-08-31 12:35 ` [PATCH 15/35] cifs: Do not try to overwrite existing sillyname in cifs_rename_pending_delete() Pali Rohár
2025-08-31 12:35 ` [PATCH 16/35] cifs: Add comments for DeletePending assignments in open functions Pali Rohár
2025-08-31 12:35 ` [PATCH 17/35] cifs: Use NT_STATUS_DELETE_PENDING for filling fi.DeletePending in cifs_query_path_info() Pali Rohár
2025-08-31 12:35 ` [PATCH 18/35] cifs: Do not set NumberOfLinks to 1 from open or query calls Pali Rohár
2025-08-31 12:35 ` [PATCH 19/35] cifs: Fix cifs_rename_pending_delete() for files with more hardlinks Pali Rohár
2025-08-31 12:35 ` [PATCH 20/35] cifs: Fix permission logic in cifs_rename_pending_delete() Pali Rohár
2025-08-31 12:35 ` [PATCH 21/35] cifs: Propagate error code from CIFSSMBSetFileInfo() to cifs_rename_pending_delete() Pali Rohár
2025-08-31 12:35 ` [PATCH 22/35] cifs: Improve cifs_rename_pending_delete() to work without the PASSTHRU support Pali Rohár
2025-08-31 12:35 ` [PATCH 23/35] cifs: Fix SMBLegacyOpen() function Pali Rohár
2025-08-31 12:35 ` [PATCH 24/35] cifs: Add a new callback set_file_disp() for setting file disposition (delete pending state) Pali Rohár
2025-08-31 12:35 ` [PATCH 25/35] cifs: Add a new callback rename_opened_file() for renaming an opened file Pali Rohár
2025-08-31 12:35 ` [PATCH 26/35] cifs: Add SMB2+ support into cifs_rename_pending_delete() function Pali Rohár
2025-08-31 12:35 ` [PATCH 27/35] cifs: Move SMB1 usage of CIFSPOSIXDelFile() from inode.c to cifssmb.c Pali Rohár
2025-08-31 12:35 ` [PATCH 28/35] cifs: Fix smb2_unlink() to fail on directory Pali Rohár
2025-08-31 12:35 ` [PATCH 29/35] cifs: Fix smb2_rmdir() on reparse point Pali Rohár
2025-08-31 12:35 ` [PATCH 30/35] cifs: Simplify SMB2_OP_DELETE API usage Pali Rohár
2025-08-31 12:35 ` [PATCH 31/35] cifs: Deduplicate smb2_unlink() and smb2_rmdir() into one common function Pali Rohár
2025-08-31 12:35 ` [PATCH 32/35] cifs: Use cifs_rename_pending_delete() fallback also for rmdir() Pali Rohár
2025-08-31 12:36 ` [PATCH 33/35] cifs: Add a new open flag CREATE_OPTION_EXCLUSIVE to open with deny all shared reservation Pali Rohár
2025-08-31 12:36 ` [PATCH 34/35] cifs: Use CREATE_OPTION_EXCLUSIVE when opening file/dir for SMB2+ non-POSIX unlink/rmdir Pali Rohár
2025-08-31 12:36 ` [PATCH 35/35] cifs: Use CREATE_OPTION_EXCLUSIVE when doing SMB1 rmdir on NT server Pali Rohár
2025-09-01  7:55 ` [PATCH 00/35] cifs: Fix SMB rmdir() and unlink() against Windows SMB servers Stefan Metzmacher
2025-09-01 17:02   ` Pali Rohár
2025-09-02 15:17     ` Stefan Metzmacher
2025-09-02 16:30       ` Pali Rohár

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).