summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix
diff options
context:
space:
mode:
authorbubulle <bubulle@alioth.debian.org>2010-09-06 17:45:31 +0000
committerbubulle <bubulle@alioth.debian.org>2010-09-06 17:45:31 +0000
commit647b5024ebe9599e153c948b61fe7a339756b1f9 (patch)
tree882eca1ca1276029e02e757658cb73106493dc95 /source4/ntvfs/posix
parentd63d5b7793d30d6f18ab736b3aad1bface02f1e6 (diff)
downloadsamba-647b5024ebe9599e153c948b61fe7a339756b1f9.tar.gz
Merge upstream 3.5.4~dfsg
git-svn-id: svn://svn.debian.org/svn/pkg-samba/trunk/samba@3571 fc4039ab-9d04-0410-8cac-899223bdd6b0
Diffstat (limited to 'source4/ntvfs/posix')
-rw-r--r--source4/ntvfs/posix/config.mk2
-rw-r--r--source4/ntvfs/posix/pvfs_acl.c45
-rw-r--r--source4/ntvfs/posix/pvfs_notify.c11
-rw-r--r--source4/ntvfs/posix/pvfs_open.c10
-rw-r--r--source4/ntvfs/posix/pvfs_oplock.c2
-rw-r--r--source4/ntvfs/posix/pvfs_read.c4
-rw-r--r--source4/ntvfs/posix/pvfs_rename.c4
-rw-r--r--source4/ntvfs/posix/pvfs_resolve.c5
-rw-r--r--source4/ntvfs/posix/pvfs_util.c5
-rw-r--r--source4/ntvfs/posix/vfs_posix.c30
10 files changed, 104 insertions, 14 deletions
diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk
index 1d7949214a..1aaef3f1d4 100644
--- a/source4/ntvfs/posix/config.mk
+++ b/source4/ntvfs/posix/config.mk
@@ -42,7 +42,7 @@ OUTPUT_TYPE = MERGED_OBJ
INIT_FUNCTION = ntvfs_posix_init
#PRIVATE_DEPENDENCIES = pvfs_acl_xattr pvfs_acl_nfs4
PRIVATE_DEPENDENCIES = NDR_XATTR WRAP_XATTR BLKID ntvfs_common MESSAGING \
- LIBWBCLIENT pvfs_acl pvfs_aio
+ LIBWBCLIENT_OLD pvfs_acl pvfs_aio
# End MODULE ntvfs_posix
################################################
diff --git a/source4/ntvfs/posix/pvfs_acl.c b/source4/ntvfs/posix/pvfs_acl.c
index 1adced44aa..ad7ac5a749 100644
--- a/source4/ntvfs/posix/pvfs_acl.c
+++ b/source4/ntvfs/posix/pvfs_acl.c
@@ -449,6 +449,35 @@ static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
}
/*
+ see if we are a member of the appropriate unix group
+ */
+static bool pvfs_group_member(struct pvfs_state *pvfs, gid_t gid)
+{
+ int i, ngroups;
+ gid_t *groups;
+ if (getegid() == gid) {
+ return true;
+ }
+ ngroups = getgroups(0, NULL);
+ if (ngroups == 0) {
+ return false;
+ }
+ groups = talloc_array(pvfs, gid_t, ngroups);
+ if (groups == NULL) {
+ return false;
+ }
+ if (getgroups(ngroups, groups) != ngroups) {
+ talloc_free(groups);
+ return false;
+ }
+ for (i=0; i<ngroups; i++) {
+ if (groups[i] == gid) break;
+ }
+ talloc_free(groups);
+ return i < ngroups;
+}
+
+/*
default access check function based on unix permissions
doing this saves on building a full security descriptor
for the common case of access check on files with no
@@ -473,6 +502,20 @@ NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
max_bits |= SEC_STD_ALL;
}
+ if ((name->st.st_mode & S_IWOTH) ||
+ ((name->st.st_mode & S_IWGRP) &&
+ pvfs_group_member(pvfs, name->st.st_gid))) {
+ max_bits |= SEC_STD_ALL;
+ }
+
+ if (uwrap_enabled()) {
+ /* when running with the uid wrapper, files will be created
+ owned by the ruid, but we may have a different simulated
+ euid. We need to force the permission bits as though the
+ files owner matches the euid */
+ max_bits |= SEC_STD_ALL;
+ }
+
if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
*access_mask = max_bits;
return NT_STATUS_OK;
@@ -483,6 +526,8 @@ NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
}
if (*access_mask & ~max_bits) {
+ DEBUG(0,(__location__ " denied access to '%s' - wanted 0x%08x but got 0x%08x (missing 0x%08x)\n",
+ name->full_name, *access_mask, max_bits, *access_mask & ~max_bits));
return NT_STATUS_ACCESS_DENIED;
}
diff --git a/source4/ntvfs/posix/pvfs_notify.c b/source4/ntvfs/posix/pvfs_notify.c
index 09aa0f64e6..3e6f442d61 100644
--- a/source4/ntvfs/posix/pvfs_notify.c
+++ b/source4/ntvfs/posix/pvfs_notify.c
@@ -34,6 +34,7 @@ struct pvfs_notify_buffer {
struct notify_changes *changes;
uint32_t max_buffer_size;
uint32_t current_buffer_size;
+ bool overflowed;
/* a list of requests waiting for events on this handle */
struct notify_pending {
@@ -71,7 +72,7 @@ static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer,
while (notify_buffer->pending) {
pvfs_notify_send(notify_buffer, NT_STATUS_OK, immediate);
}
- talloc_free(notify_buffer);
+ notify_buffer->overflowed = true;
return;
}
@@ -88,6 +89,7 @@ static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer,
info->nttrans.out.num_changes = notify_buffer->num_changes;
info->nttrans.out.changes = talloc_steal(req, notify_buffer->changes);
notify_buffer->num_changes = 0;
+ notify_buffer->overflowed = false;
notify_buffer->changes = NULL;
notify_buffer->current_buffer_size = 0;
@@ -133,6 +135,10 @@ static void pvfs_notify_callback(void *private_data, const struct notify_event *
struct notify_changes *n2;
char *new_path;
+ if (n->overflowed) {
+ return;
+ }
+
n2 = talloc_realloc(n, n->changes, struct notify_changes, n->num_changes+1);
if (n2 == NULL) {
/* nothing much we can do for this */
@@ -267,7 +273,8 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
DLIST_ADD_END(f->notify_buffer->pending, pending, struct notify_pending *);
/* if the buffer is empty then start waiting */
- if (f->notify_buffer->num_changes == 0) {
+ if (f->notify_buffer->num_changes == 0 &&
+ !f->notify_buffer->overflowed) {
struct pvfs_wait *wait_handle;
wait_handle = pvfs_wait_message(pvfs, req, -1,
timeval_zero(),
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 12f50fcc97..46e39a00dd 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -534,7 +534,7 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h)
if (!timeval_is_zero(&tv[0]) || !timeval_is_zero(&tv[1])) {
if (utimes(h->name->full_name, tv) == -1) {
- DEBUG(0,("pvfs_handle_destructor: utimes() failed '%s' - %s\n",
+ DEBUG(3,("pvfs_handle_destructor: utimes() failed '%s' - %s\n",
h->name->full_name, strerror(errno)));
}
}
@@ -1516,6 +1516,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
if (fd == -1) {
status = pvfs_map_errno(f->pvfs, errno);
+ DEBUG(0,(__location__ " mapped errno %s for %s (was %d)\n",
+ nt_errstr(status), f->handle->name->full_name, errno));
/*
* STATUS_MORE_ENTRIES is EAGAIN or EWOULDBLOCK
*/
@@ -1581,10 +1583,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
if (f->handle->name->stream_id == 0 &&
(io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE ||
io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF)) {
- /* for overwrite we need to replace file permissions */
+ /* for overwrite we may need to replace file permissions */
uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE;
mode_t mode = pvfs_fileperms(pvfs, attrib);
- if (fchmod(fd, mode) == -1) {
+ if (f->handle->name->st.st_mode != mode &&
+ f->handle->name->dos.attrib != attrib &&
+ fchmod(fd, mode) == -1) {
talloc_free(lck);
return pvfs_map_errno(pvfs, errno);
}
diff --git a/source4/ntvfs/posix/pvfs_oplock.c b/source4/ntvfs/posix/pvfs_oplock.c
index e5a069addc..a10188f3eb 100644
--- a/source4/ntvfs/posix/pvfs_oplock.c
+++ b/source4/ntvfs/posix/pvfs_oplock.c
@@ -122,7 +122,7 @@ static void pvfs_oplock_break(struct pvfs_oplock *opl, uint8_t level)
*/
*last = cur;
- DEBUG(0,("%s: sending oplock break level %d for '%s' %p\n",
+ DEBUG(5,("%s: sending oplock break level %d for '%s' %p\n",
__FUNCTION__, level, h->name->original_name, h));
status = ntvfs_send_oplock_break(pvfs->ntvfs, f->ntvfs, level);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/ntvfs/posix/pvfs_read.c b/source4/ntvfs/posix/pvfs_read.c
index d9080d632d..75fba3c90d 100644
--- a/source4/ntvfs/posix/pvfs_read.c
+++ b/source4/ntvfs/posix/pvfs_read.c
@@ -59,8 +59,8 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs,
}
maxcnt = rd->readx.in.maxcnt;
- if (maxcnt > UINT16_MAX && req->ctx->protocol < PROTOCOL_SMB2) {
- maxcnt = 0;
+ if (maxcnt > 2*UINT16_MAX && req->ctx->protocol < PROTOCOL_SMB2) {
+ return NT_STATUS_INVALID_PARAMETER;
}
status = pvfs_check_lock(pvfs, f, req->smbpid,
diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c
index 7f8eab5aa0..0616d38bee 100644
--- a/source4/ntvfs/posix/pvfs_rename.c
+++ b/source4/ntvfs/posix/pvfs_rename.c
@@ -118,13 +118,13 @@ static const char *pvfs_resolve_wildcard_component(TALLOC_CTX *mem_ctx,
c1 = next_codepoint_convenience(iconv_convenience, p1, &c_size1);
c2 = next_codepoint_convenience(iconv_convenience, p2, &c_size2);
if (c2 == '?') {
- d += push_codepoint(iconv_convenience, d, c1);
+ d += push_codepoint_convenience(iconv_convenience, d, c1);
} else if (c2 == '*') {
memcpy(d, p1, strlen(p1));
d += strlen(p1);
break;
} else {
- d += push_codepoint(iconv_convenience, d, c2);
+ d += push_codepoint_convenience(iconv_convenience, d, c2);
}
p1 += c_size1;
diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c
index c33323350e..8e8da72e1f 100644
--- a/source4/ntvfs/posix/pvfs_resolve.c
+++ b/source4/ntvfs/posix/pvfs_resolve.c
@@ -796,7 +796,10 @@ NTSTATUS pvfs_resolve_parent(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
(*name)->has_wildcard = false;
/* we can't get the correct 'original_name', but for the purposes
of this call this is close enough */
- (*name)->original_name = talloc_reference(*name, child->original_name);
+ (*name)->original_name = talloc_strdup(*name, child->original_name);
+ if ((*name)->original_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
(*name)->stream_name = NULL;
(*name)->stream_id = 0;
diff --git a/source4/ntvfs/posix/pvfs_util.c b/source4/ntvfs/posix/pvfs_util.c
index 81ff20a608..b1b0a64789 100644
--- a/source4/ntvfs/posix/pvfs_util.c
+++ b/source4/ntvfs/posix/pvfs_util.c
@@ -39,7 +39,10 @@ bool pvfs_has_wildcard(const char *str)
*/
NTSTATUS pvfs_map_errno(struct pvfs_state *pvfs, int unix_errno)
{
- return map_nt_error_from_unix(unix_errno);
+ NTSTATUS status;
+ status = map_nt_error_from_unix(unix_errno);
+ DEBUG(10,(__location__ " mapped unix errno %d -> %s\n", unix_errno, nt_errstr(status)));
+ return status;
}
diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c
index 29ef701dee..5134c0a608 100644
--- a/source4/ntvfs/posix/vfs_posix.c
+++ b/source4/ntvfs/posix/vfs_posix.c
@@ -168,12 +168,35 @@ static int pvfs_state_destructor(struct pvfs_state *pvfs)
that comes later)
*/
static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
- struct ntvfs_request *req, const char *sharename)
+ struct ntvfs_request *req,
+ union smb_tcon* tcon)
{
struct pvfs_state *pvfs;
struct stat st;
char *base_directory;
NTSTATUS status;
+ const char *sharename;
+
+ switch (tcon->generic.level) {
+ case RAW_TCON_TCON:
+ sharename = tcon->tcon.in.service;
+ break;
+ case RAW_TCON_TCONX:
+ sharename = tcon->tconx.in.path;
+ break;
+ case RAW_TCON_SMB2:
+ sharename = tcon->smb2.in.path;
+ break;
+ default:
+ return NT_STATUS_INVALID_LEVEL;
+ }
+
+ if (strncmp(sharename, "\\\\", 2) == 0) {
+ char *p = strchr(sharename+2, '\\');
+ if (p) {
+ sharename = p + 1;
+ }
+ }
/*
* TODO: call this from ntvfs_posix_init()
@@ -209,6 +232,11 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
+ if (tcon->generic.level == RAW_TCON_TCONX) {
+ tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
+ tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
+ }
+
ntvfs->private_data = pvfs;
pvfs->brl_context = brl_init(pvfs,