The branch, v4-0-test has been updated via e6ff129 s3: messages: Implement cleanup of dead records. via b649fdb s3: smbd: Ensure we always go via getgroups_unix_user() when creating an NT token. from fc185a5 tevent: fix crash bug in tevent_queue_immediate_trigger()
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test - Log ----------------------------------------------------------------- commit e6ff1291fa940294689d46bd2795281d45fbc07e Author: Jeremy Allison <j...@samba.org> Date: Wed Apr 2 16:45:25 2014 -0700 s3: messages: Implement cleanup of dead records. When a smbd process dies, pending messages.tdb records for this process might not get cleaned up. Implement a cleanup for dead records that is triggered after a smbd dies uncleanly; the records for that PID are deleted. Based on a patchset from Christof Schmitt <c...@samba.org>. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Christof Schmitt <c...@samba.org> (cherry picked from commit 837671f47670b16726aa96ba7a0902974a1037eb) Bug: https://bugzilla.samba.org/show_bug.cgi?id=10534 Cleanup messages.tdb record after unclean smbd shutdown Autobuild-User(v4-0-test): Karolin Seeger <ksee...@samba.org> Autobuild-Date(v4-0-test): Mon Apr 7 11:55:50 CEST 2014 on sn-devel-104 commit b649fdb8d63a5b14bb9dc567de1ddd640ae165f3 Author: Jeremy Allison <j...@samba.org> Date: Tue Mar 25 08:47:39 2014 -0700 s3: smbd: Ensure we always go via getgroups_unix_user() when creating an NT token. This has to be done in every code path that creates an NT token, as remote users may have been added to the local /etc/group database. Tokens created merely from the info3 structs (via the DC or via the krb5 PAC) won't have these local groups. This code needs to special-case the guest user, as this token can have the token_sid[0] set to the Guest SID, not the mapping of UNIX uid -> SID. Other users that may have a well-known SID set in token_sid[0] (like SYSTEM) are usually not mappable to UNIX users and can be ignored when adding local groups from /etc/group. Combined back-port of fixes 6034ab521c47fc5f4732398652c9c6847ff92035 and a9fa09723bee3588db2168ac13f7ad0334452c11 from master. https://bugzilla.samba.org/show_bug.cgi?id=10508 Signed-off-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/auth/token_util.c | 101 ++++++++++++++++++++++++++++++++++++++++++ source3/include/messages.h | 6 +++ source3/lib/messages.c | 17 +++++++ source3/lib/messages_local.c | 38 ++++++++++++++++ source3/smbd/server.c | 7 +++ 5 files changed, 169 insertions(+), 0 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/auth/token_util.c b/source3/auth/token_util.c index 841bc52..09959f4 100644 --- a/source3/auth/token_util.c +++ b/source3/auth/token_util.c @@ -389,6 +389,100 @@ struct security_token *create_local_nt_token(TALLOC_CTX *mem_ctx, return result; } +/*************************************************** + Merge in any groups from /etc/group. +***************************************************/ + +static NTSTATUS add_local_groups(struct security_token *result, + bool is_guest) +{ + gid_t *gids = NULL; + uint32_t getgroups_num_group_sids = 0; + struct passwd *pass = NULL; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + int i; + + if (is_guest) { + /* + * Guest is a special case. It's always + * a user that can be looked up, but + * result->sids[0] is set to DOMAIN\Guest. + * Lookup by account name instead. + */ + pass = Get_Pwnam_alloc(tmp_ctx, lp_guestaccount()); + } else { + uid_t uid; + + /* For non-guest result->sids[0] is always the user sid. */ + if (!sid_to_uid(&result->sids[0], &uid)) { + /* + * Non-mappable SID like SYSTEM. + * Can't be in any /etc/group groups. + */ + TALLOC_FREE(tmp_ctx); + return NT_STATUS_OK; + } + + pass = getpwuid_alloc(tmp_ctx, uid); + if (pass == NULL) { + DEBUG(1, ("SID %s -> getpwuid(%u) failed\n", + sid_string_dbg(&result->sids[0]), + (unsigned int)uid)); + } + } + + if (!pass) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_UNSUCCESSFUL; + } + + /* + * Now we must get any groups this user has been + * added to in /etc/group and merge them in. + * This has to be done in every code path + * that creates an NT token, as remote users + * may have been added to the local /etc/group + * database. Tokens created merely from the + * info3 structs (via the DC or via the krb5 PAC) + * won't have these local groups. Note the + * groups added here will only be UNIX groups + * (S-1-22-2-XXXX groups) as getgroups_unix_user() + * turns off winbindd before calling getgroups(). + * + * NB. This is duplicating work already + * done in the 'unix_user:' case of + * create_token_from_sid() but won't + * do anything other than be inefficient + * in that case. + */ + + if (!getgroups_unix_user(tmp_ctx, pass->pw_name, pass->pw_gid, + &gids, &getgroups_num_group_sids)) { + DEBUG(1, ("getgroups_unix_user for user %s failed\n", + pass->pw_name)); + TALLOC_FREE(tmp_ctx); + return NT_STATUS_UNSUCCESSFUL; + } + + for (i=0; i<getgroups_num_group_sids; i++) { + NTSTATUS status; + struct dom_sid grp_sid; + gid_to_sid(&grp_sid, gids[i]); + + status = add_sid_to_array_unique(result, + &grp_sid, + &result->sids, + &result->num_sids); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Failed to add UNIX SID to nt token\n")); + TALLOC_FREE(tmp_ctx); + return status; + } + } + TALLOC_FREE(tmp_ctx); + return NT_STATUS_OK; +} + static NTSTATUS finalize_local_nt_token(struct security_token *result, bool is_guest) { @@ -396,6 +490,13 @@ static NTSTATUS finalize_local_nt_token(struct security_token *result, gid_t gid; NTSTATUS status; + /* Add any local groups. */ + + status = add_local_groups(result, is_guest); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* Add in BUILTIN sids */ status = add_sid_to_array(result, &global_sid_World, diff --git a/source3/include/messages.h b/source3/include/messages.h index 4b45901..a45f5a5 100644 --- a/source3/include/messages.h +++ b/source3/include/messages.h @@ -101,6 +101,9 @@ bool messaging_tdb_parent_init(TALLOC_CTX *mem_ctx); void *messaging_tdb_event(TALLOC_CTX *mem_ctx, struct messaging_context *msg, struct tevent_context *ev); +NTSTATUS messaging_tdb_cleanup(struct messaging_context *msg_ctx, + struct server_id pid); + NTSTATUS messaging_ctdbd_init(struct messaging_context *msg_ctx, TALLOC_CTX *mem_ctx, struct messaging_backend **presult); @@ -140,6 +143,9 @@ NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx, void messaging_dispatch_rec(struct messaging_context *msg_ctx, struct messaging_rec *rec); +void messaging_cleanup_server(struct messaging_context *msg_ctx, + struct server_id pid); + #include "librpc/gen_ndr/ndr_messaging.h" #endif diff --git a/source3/lib/messages.c b/source3/lib/messages.c index cd763e7..5e738c7 100644 --- a/source3/lib/messages.c +++ b/source3/lib/messages.c @@ -397,4 +397,21 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx, return; } +/* + Call when a process has terminated abnormally. +*/ +void messaging_cleanup_server(struct messaging_context *msg_ctx, + struct server_id server) +{ + if (server_id_is_disconnected(&server)) { + return; + } + + if (!procid_is_local(&server)) { + return; + } + + (void)messaging_tdb_cleanup(msg_ctx, server); + +} /** @} **/ diff --git a/source3/lib/messages_local.c b/source3/lib/messages_local.c index 6b63d72..859eeb8 100644 --- a/source3/lib/messages_local.c +++ b/source3/lib/messages_local.c @@ -45,6 +45,7 @@ #include "includes.h" #include "system/filesys.h" #include "messages.h" +#include "serverid.h" #include "lib/tdb_wrap/tdb_wrap.h" #include "lib/param/param.h" @@ -200,6 +201,43 @@ static TDB_DATA message_key_pid(TALLOC_CTX *mem_ctx, struct server_id pid) return kbuf; } +/******************************************************************* + Called when a process has terminated abnormally. Remove all messages + pending for it. +******************************************************************/ + +NTSTATUS messaging_tdb_cleanup(struct messaging_context *msg_ctx, + struct server_id pid) +{ + struct messaging_tdb_context *ctx = talloc_get_type( + msg_ctx->local->private_data, + struct messaging_tdb_context); + struct tdb_wrap *tdb = ctx->tdb; + TDB_DATA key; + TALLOC_CTX *frame = talloc_stackframe(); + + key = message_key_pid(frame, pid); + /* + * We have to lock the key to avoid + * races in case the server_id was + * re-used and is active (a remote + * possibility, true). We only + * clean up the database if we + * know server_id doesn't exist + * while checked under the chainlock. + */ + if (tdb_chainlock(tdb->tdb, key) != 0) { + TALLOC_FREE(frame); + return NT_STATUS_LOCK_NOT_GRANTED; + } + if (!serverid_exists(&pid)) { + (void)tdb_delete(tdb->tdb, key); + } + tdb_chainunlock(tdb->tdb, key); + TALLOC_FREE(frame); + return NT_STATUS_OK; +} + /* Fetch the messaging array for a process */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a86fa48..86c20ba 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -455,6 +455,13 @@ static void remove_child_pid(struct smbd_parent_context *parent, parent); DEBUG(1,("Scheduled cleanup of brl and lock database after unclean shutdown\n")); } + + /* + * Ensure we flush any stored messages + * queued for the child process that + * terminated uncleanly. + */ + messaging_cleanup_server(parent->msg_ctx, child_id); } if (!serverid_deregister(child_id)) { -- Samba Shared Repository