diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/close.c | 22 | ||||
-rw-r--r-- | source3/smbd/fileio.c | 3 | ||||
-rw-r--r-- | source3/smbd/files.c | 43 | ||||
-rw-r--r-- | source3/smbd/globals.c | 3 | ||||
-rw-r--r-- | source3/smbd/negprot.c | 5 | ||||
-rw-r--r-- | source3/smbd/notify.c | 17 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 2 | ||||
-rw-r--r-- | source3/smbd/open.c | 37 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 28 | ||||
-rw-r--r-- | source3/smbd/oplock_irix.c | 18 | ||||
-rw-r--r-- | source3/smbd/oplock_onefs.c | 5 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 52 | ||||
-rw-r--r-- | source3/smbd/reply.c | 36 | ||||
-rw-r--r-- | source3/smbd/server.c | 12 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 11 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 14 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 15 |
17 files changed, 235 insertions, 88 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 78b8123680..d23b509af2 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -471,6 +471,7 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp) SMB_STRUCT_STAT sbuf; struct smb_file_time ft; NTSTATUS status; + int ret = -1; ZERO_STRUCT(sbuf); ZERO_STRUCT(ft); @@ -485,15 +486,19 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp) /* Ensure we have a valid stat struct for the source. */ if (fsp->fh->fd != -1) { - if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { - return map_nt_error_from_unix(errno); - } + ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { - if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf) == -1) { - return map_nt_error_from_unix(errno); + if (fsp->posix_open) { + ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name,&sbuf); + } else { + ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf); } } + if (ret == -1) { + return map_nt_error_from_unix(errno); + } + if (!VALID_STAT(sbuf)) { /* if it doesn't seem to be a real file */ return NT_STATUS_OK; @@ -581,6 +586,13 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, */ saved_status4 = update_write_time_on_close(fsp); + if (NT_STATUS_EQUAL(saved_status4, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + /* Someone renamed the file or a parent directory containing + * this file. We can't do anything about this, we don't have + * an "update timestamp by fd" call in POSIX. Eat the error. */ + + saved_status4 = NT_STATUS_OK; + } if (NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(saved_status1)) { diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index a9a97a2d14..adf664b396 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -256,10 +256,9 @@ ssize_t write_file(struct smb_request *req, int write_path = -1; if (fsp->print_file) { - fstring sharename; uint32 jobid; - if (!rap_to_pjobid(fsp->rap_print_jobid, sharename, &jobid)) { + if (!rap_to_pjobid(fsp->rap_print_jobid, NULL, &jobid)) { DEBUG(3,("write_file: Unable to map RAP jobid %u to jobid.\n", (unsigned int)fsp->rap_print_jobid )); errno = EBADF; diff --git a/source3/smbd/files.c b/source3/smbd/files.c index efaadffc06..36e80a086a 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -356,6 +356,49 @@ files_struct *file_find_print(void) } /**************************************************************************** + Find any fsp open with a pathname below that of an already open path. +****************************************************************************/ + +bool file_find_subpath(files_struct *dir_fsp) +{ + files_struct *fsp; + size_t dlen; + char *d_fullname = talloc_asprintf(talloc_tos(), + "%s/%s", + dir_fsp->conn->connectpath, + dir_fsp->fsp_name); + + if (!d_fullname) { + return false; + } + + dlen = strlen(d_fullname); + + for (fsp=Files;fsp;fsp=fsp->next) { + char *d1_fullname; + + if (fsp == dir_fsp) { + continue; + } + + d1_fullname = talloc_asprintf(talloc_tos(), + "%s/%s", + fsp->conn->connectpath, + fsp->fsp_name); + + if (strnequal(d_fullname, d1_fullname, dlen)) { + TALLOC_FREE(d_fullname); + TALLOC_FREE(d1_fullname); + return true; + } + TALLOC_FREE(d1_fullname); + } + + TALLOC_FREE(d_fullname); + return false; +} + +/**************************************************************************** Sync open files on a connection. ****************************************************************************/ diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 3f8cb411e5..9e7d103562 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -66,7 +66,8 @@ struct fsp_singleton_cache fsp_fi_cache = { .fsp = NULL, .id = { .devid = 0, - .inode = 0 + .inode = 0, + .extid = 0 } }; unsigned long file_gen_counter = 0; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 57608a9b40..a921954c49 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -27,7 +27,6 @@ extern enum protocol_types Protocol; static void get_challenge(uint8 buff[8]) { NTSTATUS nt_status; - const uint8 *cryptkey; /* We might be called more than once, multiple negprots are * permitted */ @@ -42,8 +41,8 @@ static void get_challenge(uint8 buff[8]) smb_panic("cannot make_negprot_global_auth_context!"); } DEBUG(10, ("get challenge: getting challenge\n")); - cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context); - memcpy(buff, cryptkey, 8); + negprot_global_auth_context->get_ntlm_challenge( + negprot_global_auth_context, buff); } /**************************************************************************** diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 1d4f5e8c5b..8ceeaf5f55 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -214,6 +214,8 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, ZERO_STRUCT(e); e.path = fullpath; + e.dir_fd = fsp->fh->fd; + e.dir_id = fsp->file_id; e.filter = filter; e.subdir_filter = 0; if (recursive) { @@ -370,13 +372,26 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) if ((fsp->notify->num_changes > 1000) || (name == NULL)) { /* * The real number depends on the client buf, just provide a - * guard against a DoS here. + * guard against a DoS here. If name == NULL the CN backend is + * alerting us to a problem. Possibly dropped events. Clear + * queued changes and send the catch-all response to the client + * if a request is pending. */ TALLOC_FREE(fsp->notify->changes); fsp->notify->num_changes = -1; + if (fsp->notify->requests != NULL) { + change_notify_reply(fsp->conn, + fsp->notify->requests->req, + fsp->notify->requests->max_param, + fsp->notify); + change_notify_remove_request(fsp->notify->requests); + } return; } + /* If we've exceeded the server side queue or received a NULL name + * from the underlying CN implementation, don't queue up any more + * requests until we can send a catch-all response to the client */ if (fsp->notify->num_changes == -1) { return; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index ad2366efae..86a46505a2 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1856,6 +1856,8 @@ static void call_nt_transact_ioctl(connection_struct *conn, reply_nterror(req, NT_STATUS_NO_MEMORY); return; } + + /* For backwards compatibility only store the dev/inode. */ push_file_id_16(pdata, &fsp->file_id); memcpy(pdata+16,create_volume_objectid(conn,objid),16); push_file_id_16(pdata+32, &fsp->file_id); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9971ffa679..569c260319 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -132,6 +132,18 @@ static NTSTATUS fd_open(struct connection_struct *conn, fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode); if (fsp->fh->fd == -1) { status = map_nt_error_from_unix(errno); + if (errno == EMFILE) { + static time_t last_warned = 0L; + + if (time((time_t *) NULL) > last_warned) { + DEBUG(0,("Too many open files, unable " + "to open more! smbd's max " + "open files = %d\n", + lp_max_open_files())); + last_warned = time((time_t *) NULL); + } + } + } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", @@ -1428,7 +1440,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, "create_disposition = 0x%x create_options=0x%x " "unix mode=0%o oplock_request=%d\n", fname, new_dos_attributes, access_mask, share_access, - create_disposition, create_options, unx_mode, + create_disposition, create_options, (unsigned int)unx_mode, oplock_request)); if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) { @@ -2445,6 +2457,25 @@ static NTSTATUS open_directory(connection_struct *conn, fname, access_mask, &access_granted); + + /* Were we trying to do a directory open + * for delete and didn't get DELETE + * access (only) ? Check if the + * directory allows DELETE_CHILD. + * See here: + * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx + * for details. */ + + if ((NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && + (access_mask & DELETE_ACCESS) && + (access_granted == DELETE_ACCESS) && + can_delete_file_in_directory(conn, fname))) { + DEBUG(10,("open_directory: overrode ACCESS_DENIED " + "on directory %s\n", + fname )); + status = NT_STATUS_OK; + } + if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("open_directory: check_open_rights on " "file %s failed with %s\n", @@ -2597,8 +2628,8 @@ void msg_file_was_renamed(struct messaging_context *msg, } /* Unpack the message. */ - pull_file_id_16(frm, &id); - sharepath = &frm[16]; + pull_file_id_24(frm, &id); + sharepath = &frm[24]; newname = sharepath + strlen(sharepath) + 1; sp_len = strlen(sharepath); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index b39e5bf634..22870283fa 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -40,8 +40,8 @@ void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp) uint8_t msg[MSG_SMB_KERNEL_BREAK_SIZE]; /* Put the kernel break info into the message. */ - push_file_id_16((char *)msg, &fsp->file_id); - SIVAL(msg,16,fsp->fh->gen_id); + push_file_id_24((char *)msg, &fsp->file_id); + SIVAL(msg,24,fsp->fh->gen_id); /* Don't need to be root here as we're only ever sending to ourselves. */ @@ -583,8 +583,8 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, } /* Pull the data from the message. */ - pull_file_id_16((char *)data->data, &id); - file_id = (unsigned long)IVAL(data->data, 16); + pull_file_id_24((char *)data->data, &id); + file_id = (unsigned long)IVAL(data->data, 24); DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n", (int)procid_to_pid(&src), file_id_string_tos(&id), @@ -865,12 +865,12 @@ void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e) SIVAL(msg,16,e->private_options); SIVAL(msg,20,(uint32)e->time.tv_sec); SIVAL(msg,24,(uint32)e->time.tv_usec); - push_file_id_16(msg+28, &e->id); - SIVAL(msg,44,e->share_file_id); - SIVAL(msg,48,e->uid); - SSVAL(msg,52,e->flags); + push_file_id_24(msg+28, &e->id); + SIVAL(msg,52,e->share_file_id); + SIVAL(msg,56,e->uid); + SSVAL(msg,60,e->flags); #ifdef CLUSTER_SUPPORT - SIVAL(msg,54,e->pid.vnn); + SIVAL(msg,62,e->pid.vnn); #endif } @@ -888,12 +888,12 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) e->private_options = IVAL(msg,16); e->time.tv_sec = (time_t)IVAL(msg,20); e->time.tv_usec = (int)IVAL(msg,24); - pull_file_id_16(msg+28, &e->id); - e->share_file_id = (unsigned long)IVAL(msg,44); - e->uid = (uint32)IVAL(msg,48); - e->flags = (uint16)SVAL(msg,52); + pull_file_id_24(msg+28, &e->id); + e->share_file_id = (unsigned long)IVAL(msg,52); + e->uid = (uint32)IVAL(msg,56); + e->flags = (uint16)SVAL(msg,60); #ifdef CLUSTER_SUPPORT - e->pid.vnn = IVAL(msg,54); + e->pid.vnn = IVAL(msg,62); #endif } diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index bbc9132a08..89b8e0f7b5 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -103,6 +103,24 @@ static bool irix_oplocks_available(void) return True; } +/* + * This is bad because the file_id should always be created through the vfs + * layer! Unfortunately, a conn struct isn't available here. + */ +static struct file_id file_id_create_dev(SMB_DEV_T dev, SMB_INO_T inode) +{ + struct file_id key; + + /* the ZERO_STRUCT ensures padding doesn't break using the key as a + * blob */ + ZERO_STRUCT(key); + + key.devid = dev; + key.inode = inode; + + return key; +} + /**************************************************************************** * Deal with the IRIX kernel <--> smbd * oplock break protocol. diff --git a/source3/smbd/oplock_onefs.c b/source3/smbd/oplock_onefs.c index 0908ce4386..d4f181fc47 100644 --- a/source3/smbd/oplock_onefs.c +++ b/source3/smbd/oplock_onefs.c @@ -744,13 +744,13 @@ struct kernel_oplocks *onefs_init_kernel_oplocks(TALLOC_CTX *mem_ctx) po.po_flags_on |= P_NON_BLOCKING_SEMLOCK; if (setprocoptions(&po) != 0) { DEBUG(0, ("setprocoptions failed: %s.\n", strerror(errno))); - goto err_out; + return NULL; } /* Setup the oplock contexts */ _ctx = talloc_zero(mem_ctx, struct kernel_oplocks); if (!_ctx) { - goto err_out; + return NULL; } ctx = talloc_zero(_ctx, struct onefs_oplocks_context); @@ -788,7 +788,6 @@ struct kernel_oplocks *onefs_init_kernel_oplocks(TALLOC_CTX *mem_ctx) err_out: talloc_free(_ctx); - talloc_free(ctx); return NULL; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index e9b581efe8..2f84a831c6 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -719,12 +719,12 @@ static struct pai_val *load_inherited_info(const struct connection_struct *conn, Count a linked list of canonical ACE entries. ****************************************************************************/ -static size_t count_canon_ace_list( canon_ace *list_head ) +static size_t count_canon_ace_list( canon_ace *l_head ) { size_t count = 0; canon_ace *ace; - for (ace = list_head; ace; ace = ace->next) + for (ace = l_head; ace; ace = ace->next) count++; return count; @@ -734,13 +734,13 @@ static size_t count_canon_ace_list( canon_ace *list_head ) Free a linked list of canonical ACE entries. ****************************************************************************/ -static void free_canon_ace_list( canon_ace *list_head ) +static void free_canon_ace_list( canon_ace *l_head ) { canon_ace *list, *next; - for (list = list_head; list; list = next) { + for (list = l_head; list; list = next) { next = list->next; - DLIST_REMOVE(list_head, list); + DLIST_REMOVE(l_head, list); SAFE_FREE(list); } } @@ -916,7 +916,7 @@ static bool identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2) static void merge_aces( canon_ace **pp_list_head ) { - canon_ace *list_head = *pp_list_head; + canon_ace *l_head = *pp_list_head; canon_ace *curr_ace_outer; canon_ace *curr_ace_outer_next; @@ -925,7 +925,7 @@ static void merge_aces( canon_ace **pp_list_head ) * with identical SIDs. */ - for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) { + for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) { canon_ace *curr_ace; canon_ace *curr_ace_next; @@ -947,7 +947,7 @@ static void merge_aces( canon_ace **pp_list_head ) /* Merge two allow or two deny ACE's. */ curr_ace_outer->perms |= curr_ace->perms; - DLIST_REMOVE(list_head, curr_ace); + DLIST_REMOVE(l_head, curr_ace); SAFE_FREE(curr_ace); curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */ } @@ -960,7 +960,7 @@ static void merge_aces( canon_ace **pp_list_head ) * appears only once in the list. */ - for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) { + for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) { canon_ace *curr_ace; canon_ace *curr_ace_next; @@ -992,7 +992,7 @@ static void merge_aces( canon_ace **pp_list_head ) * The deny overrides the allow. Remove the allow. */ - DLIST_REMOVE(list_head, curr_ace); + DLIST_REMOVE(l_head, curr_ace); SAFE_FREE(curr_ace); curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */ @@ -1008,7 +1008,7 @@ static void merge_aces( canon_ace **pp_list_head ) * before we can get to an allow ace. */ - DLIST_REMOVE(list_head, curr_ace_outer); + DLIST_REMOVE(l_head, curr_ace_outer); SAFE_FREE(curr_ace_outer); break; } @@ -1019,7 +1019,7 @@ static void merge_aces( canon_ace **pp_list_head ) /* We may have modified the list. */ - *pp_list_head = list_head; + *pp_list_head = l_head; } /**************************************************************************** @@ -2305,12 +2305,12 @@ static bool unpack_canon_ace(files_struct *fsp, static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head) { - canon_ace *list_head = *pp_list_head; + canon_ace *l_head = *pp_list_head; canon_ace *owner_ace = NULL; canon_ace *other_ace = NULL; canon_ace *ace = NULL; - for (ace = list_head; ace; ace = ace->next) { + for (ace = l_head; ace; ace = ace->next) { if (ace->type == SMB_ACL_USER_OBJ) owner_ace = ace; else if (ace->type == SMB_ACL_OTHER) { @@ -2331,16 +2331,16 @@ static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head) */ if (owner_ace) { - DLIST_PROMOTE(list_head, owner_ace); + DLIST_PROMOTE(l_head, owner_ace); } if (other_ace) { - DLIST_DEMOTE(list_head, other_ace, canon_ace *); + DLIST_DEMOTE(l_head, other_ace, canon_ace *); } /* We have probably changed the head of the list. */ - *pp_list_head = list_head; + *pp_list_head = l_head; } /**************************************************************************** @@ -2353,7 +2353,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) { mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); - canon_ace *list_head = NULL; + canon_ace *l_head = NULL; canon_ace *ace = NULL; canon_ace *next_ace = NULL; int entry_id = SMB_ACL_FIRST_ENTRY; @@ -2457,14 +2457,14 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, ace->owner_type = owner_type; ace->ace_flags = get_pai_flags(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT)); - DLIST_ADD(list_head, ace); + DLIST_ADD(l_head, ace); } /* * This next call will ensure we have at least a user/group/world set. */ - if (!ensure_canon_entry_valid(&list_head, conn->params, + if (!ensure_canon_entry_valid(&l_head, conn->params, S_ISDIR(psbuf->st_mode), powner, pgroup, psbuf, False)) goto fail; @@ -2476,7 +2476,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" )); - for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { + for ( ace_count = 0, ace = l_head; ace; ace = next_ace, ace_count++) { next_ace = ace->next; /* Masks are only applied to entries other than USER_OBJ and OTHER. */ @@ -2484,7 +2484,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, ace->perms &= acl_mask; if (ace->perms == 0) { - DLIST_PROMOTE(list_head, ace); + DLIST_PROMOTE(l_head, ace); } if( DEBUGLVL( 10 ) ) { @@ -2492,15 +2492,15 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, } } - arrange_posix_perms(fname,&list_head ); + arrange_posix_perms(fname,&l_head ); - print_canon_ace_list( "canonicalise_acl: ace entries after arrange", list_head ); + print_canon_ace_list( "canonicalise_acl: ace entries after arrange", l_head ); - return list_head; + return l_head; fail: - free_canon_ace_list(list_head); + free_canon_ace_list(l_head); return NULL; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 457f9412a9..22e4c1aad7 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2214,6 +2214,16 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, } if (S_ISDIR(pst->st_mode)) { + if (fsp->posix_open) { + return NT_STATUS_OK; + } + + /* If no pathnames are open below this + directory, allow the rename. */ + + if (file_find_subpath(fsp)) { + return NT_STATUS_ACCESS_DENIED; + } return NT_STATUS_OK; } @@ -2788,6 +2798,18 @@ static void send_file_readbraw(connection_struct *conn, DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n", fsp->fsp_name, strerror(errno) )); exit_server_cleanly("send_file_readbraw sendfile failed"); + } else if (sendfile_read == 0) { + /* + * Some sendfile implementations return 0 to indicate + * that there was a short read, but nothing was + * actually written to the socket. In this case, + * fallback to the normal read path so the header gets + * the correct byte count. + */ + DEBUG(3, ("send_file_readbraw: sendfile sent zero " + "bytes falling back to the normal read: " + "%s\n", fsp->fsp_name)); + goto normal_readbraw; } /* Deal with possible short send. */ @@ -2796,9 +2818,9 @@ static void send_file_readbraw(connection_struct *conn, } return; } -#endif normal_readbraw: +#endif outbuf = TALLOC_ARRAY(NULL, char, nread+4); if (!outbuf) { @@ -3284,6 +3306,18 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", fsp->fsp_name, strerror(errno) )); exit_server_cleanly("send_file_readX sendfile failed"); + } else if (nread == 0) { + /* + * Some sendfile implementations return 0 to indicate + * that there was a short read, but nothing was + * actually written to the socket. In this case, + * fallback to the normal read path so the header gets + * the correct byte count. + */ + DEBUG(3, ("send_file_readX: sendfile sent zero bytes " + "falling back to the normal read: %s\n", + fsp->fsp_name)); + goto normal_read; } DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n", diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e8ccba0873..538e04938e 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -212,7 +212,7 @@ static void remove_child_pid(pid_t pid, bool unclean_shutdown) /* a child terminated uncleanly so tickle all processes to see if they can grab any of the pending locks */ - DEBUG(3,(__location__ " Unclean shutdown of pid %u\n", pid)); + DEBUG(3,(__location__ " Unclean shutdown of pid %u\n", (unsigned int)pid)); messaging_send_buf(smbd_messaging_context(), procid_self(), MSG_SMB_BRL_VALIDATE, NULL, 0); message_send_all(smbd_messaging_context(), @@ -359,10 +359,6 @@ static void smbd_accept_connection(struct tevent_context *ev, /* Child code ... */ am_parent = 0; -#ifdef WITH_MADVISE_PROTECTED - madvise(NULL,0,MADV_PROTECT); -#endif - /* Stop zombies, the parent explicitly handles * them, counting worker smbds. */ CatchChild(); @@ -451,7 +447,6 @@ static bool smbd_open_one_socket(struct smbd_parent_context *parent, if (s->fd == -1) { DEBUG(0,("smbd_open_once_socket: open_socket_in: " "%s\n", strerror(errno))); - close(s->fd); TALLOC_FREE(s); /* * We ignore an error here, as we've done before @@ -735,7 +730,7 @@ void reload_printers(void) DEBUG(3, ("removing stale printer %s\n", pname)); if (is_printer_published(NULL, snum, NULL)) - nt_printer_publish(NULL, snum, SPOOL_DS_UNPUBLISH); + nt_printer_publish(NULL, snum, DSPRINT_UNPUBLISH); del_a_printer(pname); lp_killservice(snum); } @@ -1135,9 +1130,6 @@ extern void build_options(bool screen); if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); become_daemon(Fork, no_process_group); -#ifdef WITH_MADVISE_PROTECTED - madvise(NULL,0,MADV_PROTECT); -#endif } #if HAVE_SETPGID diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7a03ef7f3c..2c29192220 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1352,8 +1352,8 @@ static int shutdown_other_smbds(struct db_record *rec, return 0; } - DEBUG(0,("shutdown_other_smbds: shutting down pid %d " - "(IP %s)\n", procid_to_pid(&crec->pid), ip)); + DEBUG(0,("shutdown_other_smbds: shutting down pid %u " + "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip)); messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN, &data_blob_null); @@ -1691,14 +1691,15 @@ void reply_sesssetup_and_X(struct smb_request *req) } } else { struct auth_context *plaintext_auth_context = NULL; - const uint8 *chal; nt_status = make_auth_context_subsystem( &plaintext_auth_context); if (NT_STATUS_IS_OK(nt_status)) { - chal = plaintext_auth_context->get_ntlm_challenge( - plaintext_auth_context); + uint8_t chal[8]; + + plaintext_auth_context->get_ntlm_challenge( + plaintext_auth_context, chal); if (!make_user_info_for_reply(&user_info, user, domain, chal, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 759e520866..ee1dda98b2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4972,6 +4972,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, + files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 dosmode) @@ -4980,6 +4981,14 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } + if (fsp) { + if (fsp->base_fsp) { + fname = fsp->base_fsp->fsp_name; + } else { + fname = fsp->fsp_name; + } + } + if (dosmode) { if (S_ISDIR(psbuf->st_mode)) { dosmode |= aDIR; @@ -5723,12 +5732,11 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, /* Set the attributes */ dosmode = IVAL(pdata,32); - status = smb_set_file_dosmode(conn, fname, psbuf, dosmode); + status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode); if (!NT_STATUS_IS_OK(status)) { return status; } - /* access time */ ft.atime = interpret_long_date(pdata+8); @@ -6415,6 +6423,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn, create_disp = FILE_OVERWRITE_IF; } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) { create_disp = FILE_OPEN_IF; + } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) { + create_disp = FILE_OPEN; } else { DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n", (unsigned int)wire_open_mode )); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 9580247368..426772889c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -766,18 +766,13 @@ int vfs_ChDir(connection_struct *conn, const char *path) format. Note this can be called with conn == NULL. ********************************************************************/ -struct getwd_cache_key { - SMB_DEV_T dev; - SMB_INO_T ino; -}; - char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) { char s[PATH_MAX+1]; SMB_STRUCT_STAT st, st2; char *result; DATA_BLOB cache_value; - struct getwd_cache_key key; + struct file_id key; *s = 0; @@ -797,9 +792,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) goto nocache; } - ZERO_STRUCT(key); /* unlikely, but possible padding */ - key.dev = st.st_dev; - key.ino = st.st_ino; + key = vfs_file_id_from_sbuf(conn, &st); if (!memcache_lookup(smbd_memcache(), GETWD_CACHE, data_blob_const(&key, sizeof(key)), @@ -838,9 +831,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) } if (lp_getwd_cache() && VALID_STAT(st)) { - ZERO_STRUCT(key); /* unlikely, but possible padding */ - key.dev = st.st_dev; - key.ino = st.st_ino; + key = vfs_file_id_from_sbuf(conn, &st); memcache_add(smbd_memcache(), GETWD_CACHE, data_blob_const(&key, sizeof(key)), |