From 41a2b2f5cdf751e17bde60e5cfbe395450e67485 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 8 Dec 2016 11:08:53 +0100 Subject: [PATCH] vfs_fruit: fix fruit_check_access() 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 Reviewed-by: Uri Simchoni --- source3/modules/vfs_fruit.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 15b3da2999d..0636ce94fd0 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -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,