diff options
author | bubulle <bubulle@alioth.debian.org> | 2010-09-06 17:45:31 +0000 |
---|---|---|
committer | bubulle <bubulle@alioth.debian.org> | 2010-09-06 17:45:31 +0000 |
commit | 647b5024ebe9599e153c948b61fe7a339756b1f9 (patch) | |
tree | 882eca1ca1276029e02e757658cb73106493dc95 /source4/ntvfs/posix | |
parent | d63d5b7793d30d6f18ab736b3aad1bface02f1e6 (diff) | |
download | samba-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.mk | 2 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_acl.c | 45 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_notify.c | 11 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_open.c | 10 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_oplock.c | 2 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_read.c | 4 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_rename.c | 4 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_resolve.c | 5 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_util.c | 5 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.c | 30 |
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, |