]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_fruit: fix fruit_check_access()
authorRalph Boehme <slow@samba.org>
Thu, 8 Dec 2016 10:08:53 +0000 (11:08 +0100)
committerUri Simchoni <uri@samba.org>
Wed, 1 Mar 2017 23:32:22 +0000 (00:32 +0100)
Applying fcntl read locks requires an fd opened for reading. This means
we have to check the open flags of an fd and if the fd is not opened for
reading, we can't use it to set shared fctnl locks.

Iow we won't be applying interop locks with Netatalk for files openend
write-only.

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

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Uri Simchoni <uri@samba.org>
source3/modules/vfs_fruit.c

index 15b3da2999d8a44fdb3451aa6f524524c4fd0edc..0636ce94fd0281c4883de10ab798c7bc55c7c035 100644 (file)
@@ -1805,6 +1805,8 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle,
        struct byte_range_lock *br_lck = NULL;
        bool open_for_reading, open_for_writing, deny_read, deny_write;
        off_t off;
+       bool have_read = false;
+       int flags;
 
        /* FIXME: hardcoded data fork, add resource fork */
        enum apple_fork fork_type = APPLE_FORK_DATA;
@@ -1816,6 +1818,26 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle,
                  deny_mode & DENY_READ ? "DENY_READ" : "-",
                  deny_mode & DENY_WRITE ? "DENY_WRITE" : "-"));
 
+       if (fsp->fh->fd == -1) {
+               return NT_STATUS_OK;
+       }
+
+       flags = fcntl(fsp->fh->fd, F_GETFL);
+       if (flags == -1) {
+               DBG_ERR("fcntl get flags [%s] fd [%d] failed [%s]\n",
+                       fsp_str_dbg(fsp), fsp->fh->fd, strerror(errno));
+               return map_nt_error_from_unix(errno);
+       }
+
+       if (flags & (O_RDONLY|O_RDWR)) {
+               /*
+                * Applying fcntl read locks requires an fd opened for
+                * reading. This means we won't be applying locks for
+                * files openend write-only, but what can we do...
+                */
+               have_read = true;
+       }
+
        /*
         * Check read access and deny read mode
         */
@@ -1837,7 +1859,7 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle,
                }
 
                /* Set locks */
-               if (access_mask & FILE_READ_DATA) {
+               if ((access_mask & FILE_READ_DATA) && have_read) {
                        off = access_to_netatalk_brl(fork_type, FILE_READ_DATA);
                        br_lck = do_lock(
                                handle->conn->sconn->msg_ctx, fsp,
@@ -1851,7 +1873,7 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle,
                        TALLOC_FREE(br_lck);
                }
 
-               if (deny_mode & DENY_READ) {
+               if ((deny_mode & DENY_READ) && have_read) {
                        off = denymode_to_netatalk_brl(fork_type, DENY_READ);
                        br_lck = do_lock(
                                handle->conn->sconn->msg_ctx, fsp,
@@ -1887,7 +1909,7 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle,
                }
 
                /* Set locks */
-               if (access_mask & FILE_WRITE_DATA) {
+               if ((access_mask & FILE_WRITE_DATA) && have_read) {
                        off = access_to_netatalk_brl(fork_type, FILE_WRITE_DATA);
                        br_lck = do_lock(
                                handle->conn->sconn->msg_ctx, fsp,
@@ -1901,7 +1923,7 @@ static NTSTATUS fruit_check_access(vfs_handle_struct *handle,
                        TALLOC_FREE(br_lck);
 
                }
-               if (deny_mode & DENY_WRITE) {
+               if ((deny_mode & DENY_WRITE) && have_read) {
                        off = denymode_to_netatalk_brl(fork_type, DENY_WRITE);
                        br_lck = do_lock(
                                handle->conn->sconn->msg_ctx, fsp,