/*
- * Copyright (c) 2007-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/errno.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
+#include <bsm/libbsm.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/event.h>
#include <sys/time.h>
#include <asl.h>
#include <asl_ipc.h>
+#include <asl_ipc_server.h>
#include <asl_core.h>
#include "daemon.h"
#define SEARCH_BACKWARD -1
static pthread_mutex_t db_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t queue_cond = PTHREAD_COND_INITIALIZER;
extern char *asl_list_to_string(asl_search_result_t *list, uint32_t *outlen);
extern asl_search_result_t *asl_list_from_string(const char *buf);
extern boolean_t asl_ipc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
+extern uint32_t bb_convert(const char *name);
-static asl_search_result_t work_queue = {0, 0, NULL};
-
-static time_t file_sweep_last = 0;
+static task_name_t *client_tasks = NULL;
+static uint32_t client_tasks_count = 0;
typedef union
{
} asl_reply_msg;
void
-list_append_msg(asl_search_result_t *list, asl_msg_t *msg, uint32_t retain)
-{
- if (list == NULL) return;
- if (msg == NULL) return;
-
- /*
- * NB: curr is the list size
- * grow list if necessary
- */
- if (list->count == list->curr)
- {
- if (list->curr == 0)
- {
- list->msg = (asl_msg_t **)calloc(LIST_SIZE_DELTA, sizeof(asl_msg_t *));
- }
- else
- {
- list->msg = (asl_msg_t **)reallocf(list->msg, (list->curr + LIST_SIZE_DELTA) * sizeof(asl_msg_t *));
- }
-
- if (list->msg == NULL)
- {
- list->curr = 0;
- list->count = 0;
- return;
- }
-
- list->curr += LIST_SIZE_DELTA;
- }
-
- if (retain != 0) asl_msg_retain(msg);
- list->msg[list->count] = msg;
- list->count++;
-}
-
-void
-db_ping_store(time_t now)
+db_ping_store(void)
{
- time_t delta;
-
if ((global.dbtype & DB_TYPE_FILE) && (global.file_db != NULL))
{
- delta = now - file_sweep_last;
- if (delta >= global.asl_store_ping_time)
- {
- asl_store_sweep_file_cache(global.file_db);
- file_sweep_last = now;
- }
- }
-}
-
-void
-db_enqueue(asl_msg_t *m)
-{
- if (m == NULL) return;
-
- pthread_mutex_lock(&queue_lock);
- list_append_msg(&work_queue, m, 1);
- pthread_mutex_unlock(&queue_lock);
- pthread_cond_signal(&queue_cond);
-}
-
-asl_msg_t **
-db_dequeue(uint32_t *count)
-{
- asl_msg_t **work;
-
- pthread_mutex_lock(&queue_lock);
- pthread_cond_wait(&queue_cond, &queue_lock);
-
- work = NULL;
- *count = 0;
+ global.store_flags |= STORE_FLAGS_FILE_CACHE_SWEEP_REQUESTED;
- if (work_queue.count == 0)
- {
- pthread_mutex_unlock(&queue_lock);
- return NULL;
+ /* wake up the output worker thread */
+ pthread_cond_signal(&global.work_queue_cond);
}
-
- work = work_queue.msg;
- *count = work_queue.count;
-
- work_queue.count = 0;
- work_queue.curr = 0;
- work_queue.msg = NULL;
-
- pthread_mutex_unlock(&queue_lock);
- return work;
}
void
{
asldebug("error: can't create data store %s: %s\n", PATH_ASL_STORE, strerror(errno));
return;
- }
+ }
}
else
{
}
}
+ /*
+ * One-time store conversion from the old "LongTTL" style to the new "Best Before" style.
+ * bb_convert returns quickly if the store has already been converted.
+ */
+ status = bb_convert(PATH_ASL_STORE);
+ if (status != ASL_STATUS_OK)
+ {
+ asldebug("ASL data store conversion failed!: %s\n", asl_core_error(status));
+ }
+
status = asl_store_open_write(NULL, &(global.file_db));
if (status != ASL_STATUS_OK)
{
else
{
if (global.db_file_max != 0) asl_store_max_file_size(global.file_db, global.db_file_max);
- }
-
- if (global.did_store_sweep == 0)
- {
- status = asl_store_signal_sweep(global.file_db);
- if (status == ASL_STATUS_OK) global.did_store_sweep = 1;
+ asl_store_signal_sweep(global.file_db);
}
}
}
/*
- * Takes messages off the work queue and saves them in the database.
+ * Takes messages off the work queue and saves them.
* Runs in it's own thread.
*/
void
-db_worker()
+output_worker()
{
asl_msg_t **work;
- uint64_t msgid;
- uint32_t i, count, status;
- mach_msg_empty_send_t *msg;
+ uint32_t i, count;
+ mach_msg_empty_send_t *empty;
kern_return_t kstatus;
- msg = (mach_msg_empty_send_t *)calloc(1, sizeof(mach_msg_empty_send_t));
- if (msg == NULL) return;
-
- msg->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSGH_BITS_ZERO);
- msg->header.msgh_remote_port = global.server_port;
- msg->header.msgh_local_port = MACH_PORT_NULL;
- msg->header.msgh_size = sizeof(mach_msg_empty_send_t);
- msg->header.msgh_id = SEND_NOTIFICATION;
+ empty = (mach_msg_empty_send_t *)calloc(1, sizeof(mach_msg_empty_send_t));
+ if (empty == NULL) return;
forever
{
count = 0;
- work = db_dequeue(&count);
- if (work == NULL) continue;
+ /* blocks until work is available */
+ work = asl_work_dequeue(&count);
- pthread_mutex_lock(&db_lock);
+ if (work == NULL)
+ {
+ if ((global.dbtype & DB_TYPE_FILE) && (global.store_flags & STORE_FLAGS_FILE_CACHE_SWEEP_REQUESTED))
+ {
+ asl_store_sweep_file_cache(global.file_db);
+ global.store_flags &= ~STORE_FLAGS_FILE_CACHE_SWEEP_REQUESTED;
+ }
- db_asl_open();
+ continue;
+ }
for (i = 0; i < count; i++)
{
- if (global.dbtype & DB_TYPE_FILE)
- {
- status = asl_store_save(global.file_db, work[i]);
- if (status != ASL_STATUS_OK)
- {
- /* write failed - reopen & retry */
- asldebug("asl_store_save: %s\n", asl_core_error(status));
- asl_store_close(global.file_db);
- global.file_db = NULL;
+ asl_message_match_and_log(work[i]);
+ asl_msg_release(work[i]);
+ }
- db_asl_open();
- status = asl_store_save(global.file_db, work[i]);
- if (status != ASL_STATUS_OK)
- {
- asldebug("(retry) asl_store_save: %s\n", asl_core_error(status));
- asl_store_close(global.file_db);
- global.file_db = NULL;
-
- global.dbtype |= DB_TYPE_MEMORY;
- if (global.memory_db == NULL)
- {
- status = asl_memory_open(global.db_memory_max, &(global.memory_db));
- if (status != ASL_STATUS_OK)
- {
- asldebug("asl_memory_open: %s\n", asl_core_error(status));
- }
- }
- }
- }
- }
+ free(work);
+
+ if (global.store_flags & STORE_FLAGS_FILE_CACHE_SWEEP_REQUESTED)
+ {
+ asl_store_sweep_file_cache(global.file_db);
+ global.store_flags &= ~STORE_FLAGS_FILE_CACHE_SWEEP_REQUESTED;
+ }
+
+ empty->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSGH_BITS_ZERO);
+ empty->header.msgh_remote_port = global.self_port;
+ empty->header.msgh_local_port = MACH_PORT_NULL;
+ empty->header.msgh_size = sizeof(mach_msg_empty_send_t);
+ empty->header.msgh_id = SEND_NOTIFICATION;
+
+ kstatus = mach_msg(&(empty->header), MACH_SEND_MSG | MACH_SEND_TIMEOUT, empty->header.msgh_size, 0, MACH_PORT_NULL, 2, MACH_PORT_NULL);
+ }
+}
+
+/*
+ * Called from asl_action.c to save messgaes to the ASL data store
+ */
+void
+db_save_message(asl_msg_t *msg)
+{
+ uint64_t msgid;
+ uint32_t status;
+
+ pthread_mutex_lock(&db_lock);
+
+ db_asl_open();
- if (global.dbtype & DB_TYPE_MEMORY)
+ if (global.dbtype & DB_TYPE_FILE)
+ {
+ status = asl_store_save(global.file_db, msg);
+ if (status != ASL_STATUS_OK)
+ {
+ /* write failed - reopen & retry */
+ asldebug("asl_store_save: %s\n", asl_core_error(status));
+ asl_store_close(global.file_db);
+ global.file_db = NULL;
+
+ db_asl_open();
+ status = asl_store_save(global.file_db, msg);
+ if (status != ASL_STATUS_OK)
{
- msgid = 0;
- status = asl_memory_save(global.memory_db, work[i], &msgid);
- if (status != ASL_STATUS_OK)
+ asldebug("(retry) asl_store_save: %s\n", asl_core_error(status));
+ asl_store_close(global.file_db);
+ global.file_db = NULL;
+
+ global.dbtype |= DB_TYPE_MEMORY;
+ if (global.memory_db == NULL)
{
- /* save failed - reopen & retry*/
- asldebug("asl_memory_save: %s\n", asl_core_error(status));
- asl_memory_close(global.memory_db);
- global.memory_db = NULL;
-
- db_asl_open();
- msgid = 0;
- status = asl_memory_save(global.memory_db, work[i], &msgid);
+ status = asl_memory_open(global.db_memory_max, &(global.memory_db));
if (status != ASL_STATUS_OK)
{
- asldebug("(retry) asl_memory_save: %s\n", asl_core_error(status));
- asl_memory_close(global.memory_db);
- global.memory_db = NULL;
+ asldebug("asl_memory_open: %s\n", asl_core_error(status));
}
}
}
+ }
+ }
- if (global.dbtype & DB_TYPE_MINI)
+ if (global.dbtype & DB_TYPE_MEMORY)
+ {
+ msgid = 0;
+ status = asl_memory_save(global.memory_db, msg, &msgid);
+ if (status != ASL_STATUS_OK)
+ {
+ /* save failed - reopen & retry*/
+ asldebug("asl_memory_save: %s\n", asl_core_error(status));
+ asl_memory_close(global.memory_db);
+ global.memory_db = NULL;
+
+ db_asl_open();
+ msgid = 0;
+ status = asl_memory_save(global.memory_db, msg, &msgid);
+ if (status != ASL_STATUS_OK)
{
- status = asl_mini_memory_save(global.mini_db, work[i], &msgid);
- if (status != ASL_STATUS_OK)
- {
- /* save failed - reopen & retry*/
- asldebug("asl_mini_memory_save: %s\n", asl_core_error(status));
- asl_mini_memory_close(global.mini_db);
- global.mini_db = NULL;
-
- db_asl_open();
- status = asl_mini_memory_save(global.mini_db, work[i], &msgid);
- if (status != ASL_STATUS_OK)
- {
- asldebug("(retry) asl_memory_save: %s\n", asl_core_error(status));
- asl_mini_memory_close(global.mini_db);
- global.mini_db = NULL;
- }
- }
+ asldebug("(retry) asl_memory_save: %s\n", asl_core_error(status));
+ asl_memory_close(global.memory_db);
+ global.memory_db = NULL;
}
+ }
+ }
- if ((i % 500) == 499)
+ if (global.dbtype & DB_TYPE_MINI)
+ {
+ status = asl_mini_memory_save(global.mini_db, msg, &msgid);
+ if (status != ASL_STATUS_OK)
+ {
+ /* save failed - reopen & retry*/
+ asldebug("asl_mini_memory_save: %s\n", asl_core_error(status));
+ asl_mini_memory_close(global.mini_db);
+ global.mini_db = NULL;
+
+ db_asl_open();
+ status = asl_mini_memory_save(global.mini_db, msg, &msgid);
+ if (status != ASL_STATUS_OK)
{
- pthread_mutex_unlock(&db_lock);
- pthread_mutex_lock(&db_lock);
+ asldebug("(retry) asl_memory_save: %s\n", asl_core_error(status));
+ asl_mini_memory_close(global.mini_db);
+ global.mini_db = NULL;
}
}
+ }
- pthread_mutex_unlock(&db_lock);
- for (i = 0; i < count; i++) asl_msg_release(work[i]);
- free(work);
+ pthread_mutex_unlock(&db_lock);
- kstatus = mach_msg(&(msg->header), MACH_SEND_MSG, msg->header.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- }
}
void
return status;
}
+static void
+register_session(task_name_t task_name, pid_t pid)
+{
+ mach_port_t previous;
+ uint32_t i;
+
+ if (task_name == MACH_PORT_NULL) return;
+ if (global.dead_session_port == MACH_PORT_NULL) return;
+
+ for (i = 0; i < client_tasks_count; i++) if (task_name == client_tasks[i]) return;
+
+ if (client_tasks_count == 0) client_tasks = (task_name_t *)calloc(1, sizeof(task_name_t));
+ else client_tasks = (task_name_t *)reallocf(client_tasks, (client_tasks_count + 1) * sizeof(task_name_t));
+
+ if (client_tasks == NULL) return;
+ client_tasks[client_tasks_count] = task_name;
+ client_tasks_count++;
+
+ asldebug("register_session: %u PID %d\n", (unsigned int)task_name, (int)pid);
+
+ /* register for port death notification */
+ mach_port_request_notification(mach_task_self(), task_name, MACH_NOTIFY_DEAD_NAME, 0, global.dead_session_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
+ mach_port_deallocate(mach_task_self(), previous);
+
+ asl_client_count_increment();
+}
+
+static void
+cancel_session(task_name_t task_name)
+{
+ uint32_t i;
+
+ for (i = 0; (i < client_tasks_count) && (task_name != client_tasks[i]); i++);
+
+ if (i >= client_tasks_count) return;
+
+ if (client_tasks_count == 1)
+ {
+ free(client_tasks);
+ client_tasks = NULL;
+ client_tasks_count = 0;
+ }
+ else
+ {
+ for (i++; i < client_tasks_count; i++) client_tasks[i-1] = client_tasks[i];
+ client_tasks_count--;
+ client_tasks = (task_name_t *)reallocf(client_tasks, client_tasks_count * sizeof(task_name_t));
+ }
+
+ asldebug("cancel_session: %u\n", (unsigned int)task_name);
+ mach_port_destroy(mach_task_self(), task_name);
+ asl_client_count_decrement();
+}
+
/*
* Receives messages on the "com.apple.system.logger" mach port.
* Services database search requests.
uint32_t rbits, sbits;
uint32_t flags, snooze;
struct timeval now, send_time;
+ mach_dead_name_notification_t *deadname;
send_time.tv_sec = 0;
send_time.tv_usec = 0;
reply = (asl_reply_msg *)calloc(1, rps);
if (reply == NULL) return;
- rbits = MACH_RCV_MSG | MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0);
+ rbits = MACH_RCV_MSG | MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0);
sbits = MACH_SEND_MSG | MACH_SEND_TIMEOUT;
forever
if ((now.tv_sec > send_time.tv_sec) || ((now.tv_sec == send_time.tv_sec) && (now.tv_usec > send_time.tv_usec)))
{
notify_post(ASL_DB_NOTIFICATION);
- notify_post(SELF_DB_NOTIFICATION);
send_time.tv_sec = 0;
send_time.tv_usec = 0;
snooze = 0;
flags = rbits;
if (snooze != 0) flags |= MACH_RCV_TIMEOUT;
- kstatus = mach_msg(&(request->head), flags, 0, rqs, global.server_port, snooze, MACH_PORT_NULL);
+ kstatus = mach_msg(&(request->head), flags, 0, rqs, global.listen_set, snooze, MACH_PORT_NULL);
if (request->head.msgh_id == SEND_NOTIFICATION)
{
if (send_time.tv_sec == 0)
continue;
}
+ if (request->head.msgh_id == MACH_NOTIFY_DEAD_NAME)
+ {
+ deadname = (mach_dead_name_notification_t *)request;
+ cancel_session(deadname->not_port);
+ free(request);
+ continue;
+ }
+
kstatus = asl_ipc_server(&(request->head), &(reply->head));
kstatus = mach_msg(&(reply->head), sbits, reply->head.msgh_size, 0, MACH_PORT_NULL, 10, MACH_PORT_NULL);
if (kstatus == MACH_SEND_INVALID_DEST)
kern_return_t
__asl_server_query
(
- mach_port_t server,
- caddr_t request,
- mach_msg_type_number_t requestCnt,
- uint64_t startid,
- int count,
- int flags,
- caddr_t *reply,
- mach_msg_type_number_t *replyCnt,
- uint64_t *lastid,
- int *status,
- security_token_t *token
+ mach_port_t server,
+ caddr_t request,
+ mach_msg_type_number_t requestCnt,
+ uint64_t startid,
+ int count,
+ int flags,
+ caddr_t *reply,
+ mach_msg_type_number_t *replyCnt,
+ uint64_t *lastid,
+ int *status,
+ security_token_t *token
)
{
aslresponse query;
kern_return_t
__asl_server_query_timeout
(
- mach_port_t server,
- caddr_t request,
- mach_msg_type_number_t requestCnt,
- uint64_t startid,
- int count,
- int flags,
- caddr_t *reply,
- mach_msg_type_number_t *replyCnt,
- uint64_t *lastid,
- int *status,
- security_token_t *token
+ mach_port_t server,
+ caddr_t request,
+ mach_msg_type_number_t requestCnt,
+ uint64_t startid,
+ int count,
+ int flags,
+ caddr_t *reply,
+ mach_msg_type_number_t *replyCnt,
+ uint64_t *lastid,
+ int *status,
+ security_token_t *token
)
{
return __asl_server_query(server, request, requestCnt, startid, count, flags, reply, replyCnt, lastid, status, token);
{
return KERN_SUCCESS;
}
+
+kern_return_t
+__asl_server_message
+(
+ mach_port_t server,
+ caddr_t message,
+ mach_msg_type_number_t messageCnt,
+ audit_token_t token
+)
+{
+ asl_msg_t *m;
+ char tmp[64];
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
+ kern_return_t kstatus;
+ mach_port_name_t client;
+
+ asldebug("__asl_server_message: %s\n", (message == NULL) ? "NULL" : message);
+
+ m = asl_msg_from_string(message);
+ vm_deallocate(mach_task_self(), (vm_address_t)message, messageCnt);
+
+ uid = (uid_t)-1;
+ gid = (gid_t)-1;
+ pid = (gid_t)-1;
+ audit_token_to_au32(token, NULL, &uid, &gid, NULL, NULL, &pid, NULL, NULL);
+
+ client = MACH_PORT_NULL;
+ kstatus = task_name_for_pid(mach_task_self(), pid, &client);
+ if (kstatus == KERN_SUCCESS) register_session(client, pid);
+
+ if (m == NULL) return KERN_SUCCESS;
+
+ snprintf(tmp, sizeof(tmp), "%d", uid);
+ asl_set(m, ASL_KEY_UID, tmp);
+
+ snprintf(tmp, sizeof(tmp), "%d", gid);
+ asl_set(m, ASL_KEY_GID, tmp);
+
+ snprintf(tmp, sizeof(tmp), "%d", pid);
+ asl_set(m, ASL_KEY_PID, tmp);
+
+ /* verify and enqueue for processing */
+ asl_enqueue_message(SOURCE_ASL_MESSAGE, NULL, m);
+
+ return KERN_SUCCESS;
+}