summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2016-12-08 11:08:53 +0100
committerStefan Metzmacher <metze@samba.org>2017-03-07 08:28:14 +0100
commitbc54aa8e96a60dd8d5ef202577da3eeb62427ffe (patch)
tree447e6b1fe38ab77361b0025916ca9a4904c45c5f
parent5452d23372c98231e0d07a29f2a7c6d374d29dfd (diff)
downloadsamba-bc54aa8e96a60dd8d5ef202577da3eeb62427ffe.tar.gz
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 <slow@samba.org> Reviewed-by: Uri Simchoni <uri@samba.org> (cherry picked from commit 41a2b2f5cdf751e17bde60e5cfbe395450e67485)
-rw-r--r--source3/modules/vfs_fruit.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 2b34cd980b1..e91c49c592e 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -1790,6 +1790,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;
@@ -1801,6 +1803,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
*/
@@ -1822,7 +1844,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,
@@ -1836,7 +1858,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,
@@ -1872,7 +1894,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,
@@ -1886,7 +1908,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,