]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: ignore FILE_ATTRIBUTE_READONLY for the "MxAC" create context
authorRalph Boehme <slow@samba.org>
Wed, 1 Apr 2026 12:04:40 +0000 (14:04 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 29 Apr 2026 10:56:35 +0000 (10:56 +0000)
As much as I dislike adding a boolean parameter to control this behaviour, I
don't see a different clean way to do it.

Note that I'm not touching the case where the share is realy-only, I just don't
want to open that additional can of worms now and instead focus on fixing the
FILE_ATTRIBUTE_READONLY case.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=16030

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source3/modules/vfs_fruit.c
source3/smbd/fake_file.c
source3/smbd/globals.h
source3/smbd/open.c
source3/smbd/smb2_create.c

index 9ffece1fb0c67510fb477fab5f991e8bbfaa5e40..e6c244cc6c8db289656dc84d40e857c4e6450646 100644 (file)
@@ -4552,6 +4552,7 @@ static NTSTATUS fruit_freaddir_attr(struct vfs_handle_struct *handle,
                status = smbd_calculate_access_mask_fsp(fsp->conn->cwd_fsp,
                        fsp,
                        false,
+                       false,
                        SEC_FLAG_MAXIMUM_ALLOWED,
                        &attr_data->attr_data.aapl.max_access);
                if (!NT_STATUS_IS_OK(status)) {
index 7e56181476963ed2d22c5747d08a599b3f31440b..9a3da37050a55995ad411420a850be548aadb7b1 100644 (file)
@@ -189,6 +189,7 @@ NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn,
        status = smbd_calculate_access_mask_fsp(conn->cwd_fsp,
                                        fsp,
                                        false,
+                                       false,
                                        access_mask,
                                        &access_mask);
        if (!NT_STATUS_IS_OK(status)) {
index adc30a940f13103f43f2395448d92efb78803ae1..c7d67e2ed9d609b1988c50046ce6f479cfae6c86 100644 (file)
@@ -182,6 +182,7 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
 NTSTATUS smbd_calculate_access_mask_fsp(struct files_struct *dirsfp,
                        struct files_struct *fsp,
                        bool use_privs,
+                       bool ignore_readonly,
                        uint32_t access_mask,
                        uint32_t *access_mask_out);
 
index 594ffadfeb8f94db7eedfa1231f40243bec48f7f..dcaf208f10544fff2e1a1c25411436e8e999d8b4 100644 (file)
@@ -432,6 +432,7 @@ static NTSTATUS check_base_file_access(struct files_struct *fsp,
        status = smbd_calculate_access_mask_fsp(fsp->conn->cwd_fsp,
                                        fsp,
                                        false,
+                                       false,
                                        access_mask,
                                        &access_mask);
        if (!NT_STATUS_IS_OK(status)) {
@@ -3304,6 +3305,7 @@ static NTSTATUS smbd_calculate_maximum_allowed_access_fsp(
                        struct files_struct *dirfsp,
                        struct files_struct *fsp,
                        bool use_privs,
+                       bool ignore_readonly,
                        uint32_t *p_access_mask)
 {
        struct security_descriptor *sd = NULL;
@@ -3389,17 +3391,30 @@ static NTSTATUS smbd_calculate_maximum_allowed_access_fsp(
                *p_access_mask &= ~(FILE_GENERIC_WRITE | DELETE_ACCESS);
        }
 
+       if (ignore_readonly) {
+               /*
+                * We end up here when the maximum access mask for the "MxAC"
+                * create context response is needed. That ignores the read-only
+                * attribute, cf smbtorture tests
+                * "smb2.maximum_allowed.read_only_file" and
+                * "smb2.maximum_allowed.read_only_dir".
+                */
+               goto done;
+       }
+
        dosattrs = fdos_mode(fsp);
        if (dosattrs & FILE_ATTRIBUTE_READONLY) {
                *p_access_mask &= ~(FILE_GENERIC_WRITE | DELETE_ACCESS);
        }
 
+done:
        return NT_STATUS_OK;
 }
 
 NTSTATUS smbd_calculate_access_mask_fsp(struct files_struct *dirfsp,
                        struct files_struct *fsp,
                        bool use_privs,
+                       bool ignore_readonly,
                        uint32_t access_mask,
                        uint32_t *access_mask_out)
 {
@@ -3426,6 +3441,7 @@ NTSTATUS smbd_calculate_access_mask_fsp(struct files_struct *dirfsp,
                                                   dirfsp,
                                                   fsp,
                                                   use_privs,
+                                                  ignore_readonly,
                                                   &access_mask);
 
                if (!NT_STATUS_IS_OK(status)) {
@@ -3944,7 +3960,7 @@ static NTSTATUS open_file_ntcreate(
        }
 
        status = smbd_calculate_access_mask_fsp(
-               dirfsp, smb_fname->fsp, false, access_mask, &access_mask);
+               dirfsp, smb_fname->fsp, false, false, access_mask, &access_mask);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_DEBUG("smbd_calculate_access_mask_fsp "
                        "on file %s returned %s\n",
@@ -5031,7 +5047,7 @@ static NTSTATUS open_directory(connection_struct *conn,
        }
 
        status = smbd_calculate_access_mask_fsp(
-               dirfsp, smb_dname->fsp, false, access_mask, &access_mask);
+               dirfsp, smb_dname->fsp, false, false, access_mask, &access_mask);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_DEBUG("smbd_calculate_access_mask_fsp "
                        "on file %s returned %s\n",
index 228433eb3e99950396f30fe0617e52a31457d730..7f61514defc0d851af271d7a66fbbc7291131ee1 100644 (file)
@@ -1795,6 +1795,7 @@ static void smbd_smb2_create_after_exec(struct tevent_req *req)
                                        conn->cwd_fsp,
                                        state->result,
                                        false,
+                                       true,
                                        SEC_FLAG_MAXIMUM_ALLOWED,
                                        &max_access_granted);