From c300ed94060217232e6e3b3a36f819f0e5226a03 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 13 Aug 2025 17:02:16 +0200 Subject: [PATCH 1/8] smbtorture: fix locking offset in test_fruit_locking_conflict() AD_FILELOCK_RSRC_DENY_WR = AD_FILELOCK_BASE + 6 = (0x7FFFFFFFFFFFFFFF - 9) + 6 = 0x7FFFFFFFFFFFFFFC No change in behaviour though, just stumpled across it. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 3052839636f185307edb8832de9bdba4b2e2c83c) --- source4/torture/vfs/fruit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c index 6bad4e409c6e..e9ff4a57e66c 100644 --- a/source4/torture/vfs/fruit.c +++ b/source4/torture/vfs/fruit.c @@ -8002,7 +8002,7 @@ static bool test_fruit_locking_conflict(struct torture_context *tctx, /* Add AD_FILELOCK_RSRC_DENY_WR lock. */ el = (struct smb2_lock_element) { - .offset = 0xfffffffffffffffc, + .offset = 0x7ffffffffffffffc, .length = 1, .flags = SMB2_LOCK_FLAG_EXCLUSIVE, }; -- 2.50.0 From 543e64b28f39d004684867b24acd44e6fc0927e2 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 1 Aug 2025 17:28:04 +0200 Subject: [PATCH 2/8] smbd: don't use sticky write times on POSIX handles BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 795a8c0e84f2bf2b70c8070737183e33f4254a54) --- source3/smbd/dosmode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index c7ff427d7e30..331eac83ab80 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -1277,6 +1277,9 @@ int file_ntimes(connection_struct *conn, void set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime) { + if (fsp->fsp_flags.posix_open) { + return; + } if (is_omit_timespec(&mtime)) { return; } -- 2.50.0 From 0f9ff9db90e908324d028134dd344a21532bb302 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 19 Sep 2025 00:20:43 +0200 Subject: [PATCH 3/8] smbtorture: add test vfs.fruit.readonly-exclusive-lock Verify macOS clients get Windows byterange lock behavour by trying to set an exclusive lock on a file opened in read-only mode. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 777db5b50689d28c53d6b0116818601fd8e52aa8) --- source4/torture/vfs/fruit.c | 92 +++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c index e9ff4a57e66c..02f7acd0fead 100644 --- a/source4/torture/vfs/fruit.c +++ b/source4/torture/vfs/fruit.c @@ -7839,6 +7839,97 @@ static bool test_delete_trigger_convert_sharing_violation( return ret; } +/* + test exclusive byte range lock on read-only file +*/ +static bool test_readonly_exclusive_lock(struct torture_context *tctx, + struct smb2_tree *tree) +{ + NTSTATUS status; + bool ret = true; + struct smb2_handle h; + struct smb2_create create; + struct smb2_lock lock; + struct smb2_lock_element lock_element; + const char *fname = "readonly_lock_test.txt"; + + torture_comment(tctx, "Testing exclusive lock on read-only opened file\n"); + + ret = enable_aapl(tctx, tree); + torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed"); + + /* Clean up any existing file */ + smb2_util_unlink(tree, fname); + + /* Create the file first with write access to ensure it exists */ + ZERO_STRUCT(create); + create.in.desired_access = SEC_RIGHTS_FILE_ALL; + create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + create.in.share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE; + create.in.create_disposition = NTCREATEX_DISP_CREATE; + create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + create.in.security_flags = 0; + create.in.fname = fname; + + status = smb2_create(tree, tctx, &create); + CHECK_STATUS(status, NT_STATUS_OK); + + /* Write some data to the file */ + status = smb2_util_write(tree, create.out.file.handle, "test data", 0, 9); + CHECK_STATUS(status, NT_STATUS_OK); + + /* Close the file */ + status = smb2_util_close(tree, create.out.file.handle); + CHECK_STATUS(status, NT_STATUS_OK); + + /* Now open the file read-only */ + ZERO_STRUCT(create); + create.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE; + create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + create.in.share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE; + create.in.create_disposition = NTCREATEX_DISP_OPEN; + create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + create.in.security_flags = 0; + create.in.fname = fname; + + status = smb2_create(tree, tctx, &create); + CHECK_STATUS(status, NT_STATUS_OK); + h = create.out.file.handle; + + torture_comment(tctx, "File opened read-only successfully\n"); + + /* Attempt to set an exclusive byte-range lock */ + ZERO_STRUCT(lock); + ZERO_STRUCT(lock_element); + + lock.in.lock_count = 1; + lock.in.lock_sequence = 0; + lock.in.file.handle = h; + lock.in.locks = &lock_element; + + lock_element.offset = 0; + lock_element.length = 100; + lock_element.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; + + torture_comment(tctx, "Attempting to set exclusive lock on read-only file\n"); + + status = smb2_lock(tree, &lock); + CHECK_STATUS(status, NT_STATUS_OK); + +done: + /* Close the file */ + smb2_util_close(tree, h); + + /* Clean up */ + smb2_util_unlink(tree, fname); + + return ret; +} + /* * Note: This test depends on "vfs objects = catia fruit streams_xattr". For * some tests torture must be run on the host it tests and takes an additional @@ -7885,6 +7976,7 @@ struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx) torture_suite_add_1smb2_test(suite, "empty_stream", test_empty_stream); torture_suite_add_1smb2_test(suite, "writing_afpinfo", test_writing_afpinfo); torture_suite_add_1smb2_test(suite, "delete_trigger_convert_sharing_violation", test_delete_trigger_convert_sharing_violation); + torture_suite_add_1smb2_test(suite, "readonly-exclusive-lock", test_readonly_exclusive_lock); return suite; } -- 2.50.0 From 7e1a6815e98d10b3c67cb7f320aab5b6afc8d94b Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 19 Sep 2025 06:43:57 +0200 Subject: [PATCH 4/8] smbtorture: add test vfs.fruit.case_insensitive_find Verifies case insensitive directory scanning works. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 68ed6279335cfac13a624ae8a7738dac3d9b0d1a) --- source4/torture/vfs/fruit.c | 85 ++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c index 02f7acd0fead..a6f86cd5edf9 100644 --- a/source4/torture/vfs/fruit.c +++ b/source4/torture/vfs/fruit.c @@ -7930,6 +7930,89 @@ static bool test_readonly_exclusive_lock(struct torture_context *tctx, return ret; } +/* + * Test case-insensitive file finding with AAPL extensions + * Add this function to source4/torture/vfs/fruit.c + */ + +static bool test_case_insensitive_find(struct torture_context *tctx, + struct smb2_tree *tree) +{ + NTSTATUS status; + bool ret = true; + const char *fname = "TestFile.txt"; + const char *fname_upper = "TESTFILE.TXT"; + struct smb2_handle testdirh; + struct smb2_handle h1; + struct smb2_create create; + struct smb2_find f; + union smb_search_data *d; + uint_t count; + + smb2_deltree(tree, BASEDIR); + + status = torture_smb2_testdir(tree, BASEDIR, &testdirh); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir failed"); + + /* Enable AAPL extensions */ + ret = enable_aapl(tctx, tree); + torture_assert_goto(tctx, ret, ret, done, + "enable_aapl failed"); + + /* Create test file */ + ZERO_STRUCT(create); + create.in.desired_access = SEC_RIGHTS_FILE_ALL; + create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + create.in.share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE; + create.in.create_disposition = NTCREATEX_DISP_CREATE; + create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + create.in.fname = talloc_asprintf(tctx, "%s\\%s", BASEDIR, fname); + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + talloc_asprintf(tctx, "failed to create %s", fname)); + h1 = create.out.file.handle; + + /* Close the file */ + status = smb2_util_close(tree, h1); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "failed to close test file"); + + /* Search for file using different case */ + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = fname_upper, + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + }; + + status = smb2_find_level(tree, tctx, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + talloc_asprintf(tctx, "smb2_find_level failed searching for %s", fname_upper)); + + /* Verify we found exactly one file */ + torture_assert_int_equal_goto(tctx, count, 1, ret, done, + talloc_asprintf(tctx, "Expected 1 file, got %u", count)); + + /* Verify the filename matches our original file (case may differ) */ + torture_assert_str_equal_goto(tctx, + d[0].id_both_directory_info.name.s, fname, ret, done, + talloc_asprintf(tctx, "Found file name '%s' doesn't match expected '%s'", + d[0].directory_info.name.s, fname)); + + torture_comment(tctx, "Case-insensitive find test passed: " + "searched for '%s', found '%s'\n", + fname_upper, d[0].id_both_directory_info.name.s); + +done: + smb2_util_close(tree, testdirh); + smb2_deltree(tree, BASEDIR); + return ret; +} + /* * Note: This test depends on "vfs objects = catia fruit streams_xattr". For * some tests torture must be run on the host it tests and takes an additional @@ -7977,7 +8060,7 @@ struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx) torture_suite_add_1smb2_test(suite, "writing_afpinfo", test_writing_afpinfo); torture_suite_add_1smb2_test(suite, "delete_trigger_convert_sharing_violation", test_delete_trigger_convert_sharing_violation); torture_suite_add_1smb2_test(suite, "readonly-exclusive-lock", test_readonly_exclusive_lock); - + torture_suite_add_1smb2_test(suite, "case_insensitive_find", test_case_insensitive_find); return suite; } -- 2.50.0 From 619c89f94fbb328e3ba2d590697ad9698dfb3ba0 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 10 Mar 2025 15:01:42 +0100 Subject: [PATCH 5/8] vfs_fruit: add option "fruit:posix_opens = yes|no" (default: yes) Tags alls opens as POSIX by setting fsp_flags.posix_open to true. POSIX handles have different behaviour compared to Windows: Behaviour | POSIX | Windows | macOS |fruit:posix_opens = yes -----------------------------------+------------+---------------------------------------- Deleting files with open handles | yes | no | yes | yes Moving directories with open files | yes | no | yes | yes Byterange locks behaviour | POSIX-ish | Window-ish | POSIX-ish | POSIX-ish Sticky writetime | no | yes | no | no Case sensitive | no | yes | yes | yes Streams allowed | no | yes | yes | yes macOS follows POSIX for the first four, but needs case insensitive behaviour and needs streams. By carefully setting fsp_flags.posix_open to true *after* going through the path resolution logic, but before opens are added to locking.tdb, with "fruit:posix_opens = yes" we get closest to macOS semantics. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (backported from commit e86f0c2de80e2409bfe3fc12df24e94470988e3c) [slow@samba.org: conflict due to optino veto_localized only present in master] --- docs-xml/manpages/vfs_fruit.8.xml | 15 +++++++++++++ selftest/knownfail.d/samba3.vfs.fruit | 2 ++ source3/include/vfs.h | 18 ++++++++++++++++ source3/modules/vfs_fruit.c | 31 ++++++++++++++++++++++----- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/docs-xml/manpages/vfs_fruit.8.xml b/docs-xml/manpages/vfs_fruit.8.xml index 9e27030b6601..21c2e76de8d3 100644 --- a/docs-xml/manpages/vfs_fruit.8.xml +++ b/docs-xml/manpages/vfs_fruit.8.xml @@ -426,6 +426,21 @@ + + fruit:posix_opens = yes | no + + + When fruit:posix_opens is set to + yes, vfs_fruit will internally translate + all filesystem semantics to use POSIX behaviour instead of Windows + behaviour. As Macs are closer to POSIX than Windows with regard + to filesystem semantics, this improves access semantics for + a lot of corner cases. + The default is yes. + + + + diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit index 6307e2b34043..b774b0503e77 100644 --- a/selftest/knownfail.d/samba3.vfs.fruit +++ b/selftest/knownfail.d/samba3.vfs.fruit @@ -1,2 +1,4 @@ ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) +^samba3.vfs.fruit.*readonly-exclusive-lock\(.*\) +^samba3.vfs.fruit.*case_insensitive_find\(.*\) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 75b816481088..e87a0d923e50 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -462,6 +462,15 @@ typedef struct files_struct { bool lock_failure_seen : 1; bool encryption_required : 1; bool fstat_before_close : 1; + /* + * For POSIX clients struct files_struct.fsp_flags.posix_open + * and struct smb_filename.flags SMB_FILENAME_POSIX_PATH will + * always be set to the same value. + * + * For macOS clients vfs_fruit with fruit:posix_open=yes, we + * deliberately set both flags to fsp_flags.posix_open=true + * while SMB_FILENAME_POSIX_PATH will not be set. + */ bool posix_open : 1; bool posix_append : 1; bool ntcreatex_deny_dos : 1; @@ -889,6 +898,15 @@ struct smb_filename { struct fsp_smb_fname_link *fsp_link; }; +/* + * For POSIX clients struct files_struct.fsp_flags.posix_open + * and struct smb_filename.flags SMB_FILENAME_POSIX_PATH will + * always be set to the same value. + * + * For macOS clients vfs_fruit with fruit:posix_open=yes, we + * deliberately set both flags to fsp_flags.posix_open=true + * while SMB_FILENAME_POSIX_PATH will not be set. + */ #define SMB_FILENAME_POSIX_PATH 0x01 enum vfs_translate_direction { diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 1b72eeec534b..c056b10ee543 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -125,6 +125,7 @@ struct fruit_config_data { bool use_aapl; /* config from smb.conf */ bool use_copyfile; bool readdir_attr_enabled; + bool posix_opens; bool unix_info_enabled; bool copyfile_enabled; bool veto_appledouble; @@ -339,6 +340,9 @@ static int init_fruit_config(vfs_handle_struct *handle) config->use_copyfile = lp_parm_bool(-1, FRUIT_PARAM_TYPE_NAME, "copyfile", false); + config->posix_opens = lp_parm_bool( + SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME, "posix_opens", true); + config->aapl_zero_file_id = lp_parm_bool(SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME, "zero_file_id", true); @@ -1754,16 +1758,27 @@ static int fruit_openat(vfs_handle_struct *handle, files_struct *fsp, const struct vfs_open_how *how) { + struct fruit_config_data *config = NULL; int fd; + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, return -1); + DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname)); if (!is_named_stream(smb_fname)) { - return SMB_VFS_NEXT_OPENAT(handle, - dirfsp, - smb_fname, - fsp, - how); + fd = SMB_VFS_NEXT_OPENAT(handle, + dirfsp, + smb_fname, + fsp, + how); + if (fd == -1) { + return -1; + } + if (config->posix_opens && global_fruit_config.nego_aapl) { + fsp->fsp_flags.posix_open = true; + } + return fd; } if ((how->resolve & ~VFS_OPEN_HOW_WITH_BACKUP_INTENT) != 0) { @@ -1798,7 +1813,13 @@ static int fruit_openat(vfs_handle_struct *handle, DBG_DEBUG("Path [%s] fd [%d]\n", smb_fname_str_dbg(smb_fname), fd); /* Prevent reopen optimisation */ + if (fd == -1) { + return -1; + } fsp->fsp_flags.have_proc_fds = false; + if (config->posix_opens && global_fruit_config.nego_aapl) { + fsp->fsp_flags.posix_open = true; + } return fd; } -- 2.50.0 From 3f25b6ec503d97a3aa8836449ab0a66af3fddd4f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 18 Sep 2025 23:44:34 +0200 Subject: [PATCH 6/8] smbd: hang posix brl per-handle check on the pathname For the SMB3 POSIX client both posix_open=true and (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH) will always be the case, so this is no change in behaviour for that case. However, for the macOS client fruit will carefully setup both flags as posix_open=true but SMB_FILENAME_POSIX_PATH will not be set. This is a deliberate hack to give the macOS client POSIX behaviour for some operations, but not for others, while also allowing the POSIX-ified macOS client to continue to get case insensitive behavour. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit 75fa416f911f1f30aae8bdf14b423140874acaa0) --- selftest/knownfail.d/samba3.vfs.fruit | 1 - source3/smbd/smb2_lock.c | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit index b774b0503e77..b51c887c2129 100644 --- a/selftest/knownfail.d/samba3.vfs.fruit +++ b/selftest/knownfail.d/samba3.vfs.fruit @@ -1,4 +1,3 @@ ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) -^samba3.vfs.fruit.*readonly-exclusive-lock\(.*\) ^samba3.vfs.fruit.*case_insensitive_find\(.*\) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index be3f65e3f793..0a1383230771 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -381,8 +381,22 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, for (i=0; ifsp_flags.posix_open; + bool posix_handle = fsp->fsp_name->flags & + SMB_FILENAME_POSIX_PATH; + /* + * For POSIX clients struct files_struct.fsp_flags.posix_open + * and struct smb_filename.flags SMB_FILENAME_POSIX_PATH will + * always be set to the same value. + * + * For macOS clients vfs_fruit with fruit:posix_open=yes, we + * deliberately set both flags to fsp_flags.posix_open=true + * while SMB_FILENAME_POSIX_PATH will not be set. + * + * By deliberately checking the fsp_name flag here instead of + * the fsp flag, Byterange Lock processing uses Windows + * behaviour for macOS clients which is what we want. + */ switch (in_locks[i].flags) { case SMB2_LOCK_FLAG_SHARED: case SMB2_LOCK_FLAG_EXCLUSIVE: -- 2.50.0 From 9963f4031ff43e5d85c592aa0e06488bfb93a46e Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 18 Sep 2025 20:35:22 +0200 Subject: [PATCH 7/8] smbd: hang directory pattern matching case sensitivity on the pathname For the SMB3 POSIX client both posix_open=true and (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH) will always be the case, so this is no change in behaviour for that case. However, for the macOS client fruit will carefully setup both flags as posix_open=true but SMB_FILENAME_POSIX_PATH will not be set. This is a deliberate hack to give the macOS client POSIX behaviour for some operations, but not for others, while also allowing the POSIX-ified macOS client to continue to get case insensitive behavour. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (cherry picked from commit b3132202cf787cc9fb061e39eaf1509157f53953) --- selftest/knownfail.d/samba3.vfs.fruit | 1 - source3/smbd/dir.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit index b51c887c2129..6307e2b34043 100644 --- a/selftest/knownfail.d/samba3.vfs.fruit +++ b/selftest/knownfail.d/samba3.vfs.fruit @@ -1,3 +1,2 @@ ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) -^samba3.vfs.fruit.*case_insensitive_find\(.*\) diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 95869e054f31..21bcbe9e1c24 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1157,7 +1157,7 @@ static NTSTATUS OpenDir_fsp( goto fail; } dir_hnd->fsp = fsp; - if (fsp->fsp_flags.posix_open) { + if (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH) { dir_hnd->case_sensitive = true; } else { dir_hnd->case_sensitive = conn->case_sensitive; -- 2.50.0 From bc89d1777125477f9dddf0e04dc0805ab6ed9b2e Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sat, 6 Sep 2025 08:48:44 +0200 Subject: [PATCH 8/8] vfs_fruit: ignore Set-ACL requests with zero ACEs Workaround for a new behaviour in latest macOS versions. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15926 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke (backported from commit a112978ed1240c399eb90e4472d5c43d867c49d9) [slow@samba.org: conflict due to option veto_localized present only in master] --- docs-xml/manpages/vfs_fruit.8.xml | 18 ++++++++++++++++++ source3/modules/vfs_fruit.c | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/docs-xml/manpages/vfs_fruit.8.xml b/docs-xml/manpages/vfs_fruit.8.xml index 21c2e76de8d3..13748c110fb9 100644 --- a/docs-xml/manpages/vfs_fruit.8.xml +++ b/docs-xml/manpages/vfs_fruit.8.xml @@ -441,6 +441,24 @@ + + fruit:ignore_zero_aces = yes | no + + + When fruit:ignore_zero_aces is + enabled, attempts to modify filesystem permissions fail if the ACL + sent over the wire contains no ACEs. This is completely valid + client behaviour, but it means subsequently no further access is + possible to the file, unless permissions get fixed by an + administrator. + This problematic behaviour has been reported for latest + macOS versions and this new option allows to work around + it. + The default is yes. + + + + diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index c056b10ee543..302d90ce997a 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -137,6 +137,7 @@ struct fruit_config_data { bool wipe_intentionally_left_blank_rfork; bool delete_empty_adfiles; bool validate_afpinfo; + bool ignore_zero_aces; /* * Additional options, all enabled by default, @@ -343,6 +344,11 @@ static int init_fruit_config(vfs_handle_struct *handle) config->posix_opens = lp_parm_bool( SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME, "posix_opens", true); + config->ignore_zero_aces = lp_parm_bool(SNUM(handle->conn), + FRUIT_PARAM_TYPE_NAME, + "ignore_zero_aces", + true); + config->aapl_zero_file_id = lp_parm_bool(SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME, "zero_file_id", true); @@ -4626,6 +4632,7 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle, uint32_t security_info_sent, const struct security_descriptor *orig_psd) { + struct fruit_config_data *config = NULL; NTSTATUS status; bool do_chmod; mode_t ms_nfs_mode = 0; @@ -4633,6 +4640,10 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle, struct security_descriptor *psd = NULL; uint32_t orig_num_aces = 0; + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, + return NT_STATUS_UNSUCCESSFUL); + if (orig_psd->dacl != NULL) { orig_num_aces = orig_psd->dacl->num_aces; } @@ -4644,6 +4655,13 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle, DBG_DEBUG("%s\n", fsp_str_dbg(fsp)); + if (config->ignore_zero_aces && (psd->dacl->num_aces == 0)) { + /* + * Just ignore Set-ACL requests with zero ACEs. + */ + return NT_STATUS_OK; + } + status = check_ms_nfs(handle, fsp, psd, &ms_nfs_mode, &do_chmod); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("fruit_fset_nt_acl: check_ms_nfs failed%s\n", fsp_str_dbg(fsp))); -- 2.50.0