2 * Copyright (c) 2007-2015 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <TargetConditionals.h>
26 #include <sys/types.h>
31 #include <sys/socket.h>
35 #include <sys/fcntl.h>
36 #include <sys/signal.h>
37 #include <sys/errno.h>
38 #include <mach/mach.h>
39 #include <mach/mach_error.h>
40 #include <mach/vm_param.h>
41 #include <bsm/libbsm.h>
43 #include <netinet/in.h>
44 #include <netinet/tcp.h>
45 #include <sys/event.h>
46 #include <servers/bootstrap.h>
51 #include <xpc/private.h>
53 #include <uuid/uuid.h>
56 #include "asl_ipcServer.h"
58 #define forever for(;;)
60 #define LIST_SIZE_DELTA 256
62 #define SEND_NOTIFICATION 0xfadefade
64 #define QUERY_FLAG_SEARCH_REVERSE 0x00000001
65 #define QUERY_DURATION_UNLIMITED 0
67 #define SEARCH_FORWARD 1
68 #define SEARCH_BACKWARD -1
72 #define ASL_ENTITLEMENT_KEY "com.apple.asl.access_as_root"
73 #define ASL_ENTITLEMENT_UID_KEY "com.apple.asl.access_as_uid"
74 #define ASL_ENTITLEMENT_GID_KEY "com.apple.asl.access_as_gid"
76 #define PAGE_ROUND_UP(x) ((((x)+PAGE_SIZE-1)/PAGE_SIZE)*PAGE_SIZE)
78 static dispatch_queue_t asl_server_queue
;
79 static dispatch_queue_t watch_queue
;
80 static dispatch_once_t watch_init_once
;
82 extern boolean_t
asl_ipc_server(mach_msg_header_t
*InHeadP
, mach_msg_header_t
*OutHeadP
);
84 static task_name_t
*client_tasks
= NULL
;
85 static uint32_t client_tasks_count
= 0;
87 static int *direct_watch
= NULL
;
88 /* N.B. ports are in network byte order */
89 static uint16_t *direct_watch_port
= NULL
;
90 static uint32_t direct_watch_count
= 0;
94 mach_msg_header_t head
;
95 union __RequestUnion__asl_ipc_subsystem request
;
100 mach_msg_header_t head
;
101 union __ReplyUnion__asl_ipc_subsystem reply
;
105 db_asl_open(uint32_t dbtype
)
110 if ((dbtype
& DB_TYPE_FILE
) && (global
.file_db
== NULL
))
112 memset(&sb
, 0, sizeof(struct stat
));
113 if (stat(PATH_ASL_STORE
, &sb
) == 0)
115 /* must be a directory */
116 if (!S_ISDIR(sb
.st_mode
))
118 asldebug("error: %s is not a directory", PATH_ASL_STORE
);
126 /* /var/log/asl doesn't exist - create it */
127 if (mkdir(PATH_ASL_STORE
, 0755) != 0)
129 asldebug("error: can't create data store %s: %s\n", PATH_ASL_STORE
, strerror(errno
));
135 /* stat failed for some other reason */
136 asldebug("error: can't stat data store %s: %s\n", PATH_ASL_STORE
, strerror(errno
));
141 status
= asl_store_open_write(NULL
, &(global
.file_db
));
142 if (status
!= ASL_STATUS_OK
)
144 asldebug("asl_store_open_write: %s\n", asl_core_error(status
));
148 if (global
.db_file_max
!= 0) asl_store_max_file_size(global
.file_db
, global
.db_file_max
);
149 asl_trigger_aslmanager();
153 if ((dbtype
& DB_TYPE_MEMORY
) && (global
.memory_db
== NULL
))
155 status
= asl_memory_open(global
.db_memory_max
, global
.db_memory_str_max
, &(global
.memory_db
));
156 if (status
!= ASL_STATUS_OK
)
158 asldebug("asl_memory_open: %s\n", asl_core_error(status
));
164 add_lockdown_session(int fd
)
166 dispatch_once(&watch_init_once
, ^{
167 watch_queue
= dispatch_queue_create("Direct Watch Queue", NULL
);
170 dispatch_async(watch_queue
, ^{
171 if (global
.lockdown_session_count
== 0) global
.lockdown_session_fds
= NULL
;
173 global
.lockdown_session_fds
= reallocf(global
.lockdown_session_fds
, (global
.lockdown_session_count
+ 1) * sizeof(int));
175 if (global
.lockdown_session_fds
== NULL
)
177 asldebug("add_lockdown_session: realloc failed\n");
178 global
.lockdown_session_count
= 0;
182 global
.lockdown_session_fds
[global
.lockdown_session_count
++] = fd
;
185 global
.watchers_active
= direct_watch_count
+ global
.lockdown_session_count
;
190 remove_lockdown_session(int fd
)
192 dispatch_once(&watch_init_once
, ^{
193 watch_queue
= dispatch_queue_create("Direct Watch Queue", NULL
);
196 dispatch_async(watch_queue
, ^{
199 for (i
= 0, n
= 0; i
< global
.lockdown_session_count
; i
++)
201 if (global
.lockdown_session_fds
[i
] == fd
)
206 if (i
!= n
) global
.lockdown_session_fds
[n
] = global
.lockdown_session_fds
[i
];
213 free(global
.lockdown_session_fds
);
214 global
.lockdown_session_fds
= NULL
;
215 global
.lockdown_session_count
= 0;
219 global
.lockdown_session_fds
= reallocf(global
.lockdown_session_fds
, n
* sizeof(int));
220 if (global
.lockdown_session_fds
== NULL
)
222 asldebug("remove_lockdown_session: realloc failed\n");
223 global
.lockdown_session_count
= 0;
227 global
.lockdown_session_count
= n
;
231 global
.watchers_active
= direct_watch_count
+ global
.lockdown_session_count
;
237 sweep_lockdown_session_fds()
241 for (i
= 0, n
= 0; i
< global
.lockdown_session_count
; i
++)
243 if (global
.lockdown_session_fds
[i
] >= 0)
245 if (i
!= n
) global
.lockdown_session_fds
[n
] = global
.lockdown_session_fds
[i
];
252 free(global
.lockdown_session_fds
);
253 global
.lockdown_session_fds
= NULL
;
254 global
.lockdown_session_count
= 0;
258 global
.lockdown_session_fds
= reallocf(global
.lockdown_session_fds
, n
* sizeof(int));
259 if (global
.lockdown_session_fds
== NULL
)
261 asldebug("sweep_lockdown_session_fds: realloc failed\n");
262 global
.lockdown_session_count
= 0;
266 global
.lockdown_session_count
= n
;
270 global
.watchers_active
= direct_watch_count
+ global
.lockdown_session_count
;
275 _internal_send_to_direct_watchers(asl_msg_t
*msg
)
277 uint32_t i
, j
, nlen
, outlen
, cleanup
, total_sent
, again
;
282 static struct timeval last_time
;
286 if (global
.lockdown_session_count
> 0)
288 if (global
.remote_delay_time
> 0)
293 if (gettimeofday(&now
, NULL
) == 0)
295 if (last_time
.tv_sec
!= 0)
297 if (now
.tv_sec
> last_time
.tv_sec
)
300 now
.tv_usec
+= 1000000;
303 delta
= now
.tv_sec
- last_time
.tv_sec
;
305 delta
+= (now
.tv_usec
- last_time
.tv_usec
);
306 if (delta
< global
.remote_delay_time
)
312 if (now
.tv_usec
>= 1000000)
315 now
.tv_usec
-= 1000000;
322 out
= asl_format_message(msg
, ASL_MSG_FMT_STD
, ASL_TIME_FMT_LCL
, ASL_ENCODE_SAFE
, &outlen
);
324 for (i
= 0; i
< global
.lockdown_session_count
; i
++)
326 if (write(global
.lockdown_session_fds
[i
], out
, outlen
) < 0)
328 asldebug("send_to_direct_watchers: lockdown %d write error: %d %s\n", global
.lockdown_session_fds
[i
], errno
, strerror(errno
));
329 close(global
.lockdown_session_fds
[i
]);
330 global
.lockdown_session_fds
[i
] = -1;
338 if (cleanup
!= 0) sweep_lockdown_session_fds();
341 if (direct_watch_count
== 0)
347 if (direct_watch
== NULL
)
349 direct_watch_count
= 0;
354 out
= asl_msg_to_string(msg
, &outlen
);
356 if (out
== NULL
) return;
358 nlen
= htonl(outlen
);
359 for (i
= 0; i
< direct_watch_count
; i
++)
361 sent
= send(direct_watch
[i
], &nlen
, sizeof(nlen
), 0);
362 if (sent
< sizeof(nlen
))
364 /* bail out if we can't send 4 bytes */
365 close(direct_watch
[i
]);
366 direct_watch
[i
] = -1;
374 while (total_sent
< outlen
)
377 sent
= send(direct_watch
[i
], out
+ total_sent
, outlen
- total_sent
, 0);
380 asldebug("send_to_direct_watchers: send returned %d (errno %d)\n", sent
, errno
);
383 if (again
> MAX_AGAIN
)
385 asldebug("send_to_direct_watchers: exceeded EAGAIN limit - closing connection\n");
396 close(direct_watch
[i
]);
397 direct_watch
[i
] = -1;
409 if (cleanup
== 0) return;
412 for (i
= 0; i
< direct_watch_count
; i
++)
414 if (direct_watch
[i
] >= 0)
418 direct_watch
[j
] = direct_watch
[i
];
419 direct_watch_port
[j
] = direct_watch_port
[i
];
425 direct_watch_count
= j
;
426 if (direct_watch_count
== 0)
431 free(direct_watch_port
);
432 direct_watch_port
= NULL
;
436 direct_watch
= reallocf(direct_watch
, direct_watch_count
* sizeof(int));
437 direct_watch_port
= reallocf(direct_watch_port
, direct_watch_count
* sizeof(uint16_t));
438 if ((direct_watch
== NULL
) || (direct_watch_port
== NULL
))
443 free(direct_watch_port
);
444 direct_watch_port
= NULL
;
446 direct_watch_count
= 0;
452 send_to_direct_watchers(asl_msg_t
*msg
)
454 dispatch_once(&watch_init_once
, ^{
455 watch_queue
= dispatch_queue_create("Direct Watch Queue", NULL
);
460 dispatch_async(watch_queue
, ^{
461 _internal_send_to_direct_watchers(msg
);
462 asl_msg_release(msg
);
467 * Called from asl_action.c to save messgaes to the ASL data store
470 db_save_message(asl_msg_t
*msg
)
473 uint32_t status
, dbtype
;
475 static dispatch_source_t timer_src
;
476 static dispatch_once_t once
;
478 dispatch_once(&once
, ^{
479 timer_src
= dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER
, 0, 0, dispatch_get_main_queue());
480 dispatch_source_set_event_handler(timer_src
, ^{
481 notify_post(kNotifyASLDBUpdate
);
482 dispatch_suspend(timer_src
);
488 send_to_direct_watchers((asl_msg_t
*)msg
);
490 dbtype
= global
.dbtype
;
492 if (asl_check_option(msg
, ASL_OPT_DB_FILE
)) dbtype
|= DB_TYPE_FILE
;
493 if (asl_check_option(msg
, ASL_OPT_DB_MEMORY
)) dbtype
|= DB_TYPE_MEMORY
;
497 if (dbtype
& DB_TYPE_FILE
)
499 status
= asl_store_save(global
.file_db
, msg
);
500 if (status
!= ASL_STATUS_OK
)
502 /* write failed - reopen & retry */
503 asldebug("asl_store_save: %s\n", asl_core_error(status
));
504 asl_store_release(global
.file_db
);
505 global
.file_db
= NULL
;
508 status
= asl_store_save(global
.file_db
, msg
);
509 if (status
!= ASL_STATUS_OK
)
511 asldebug("(retry) asl_store_save: %s\n", asl_core_error(status
));
512 asl_store_release(global
.file_db
);
513 global
.file_db
= NULL
;
515 global
.dbtype
|= DB_TYPE_MEMORY
;
516 dbtype
|= DB_TYPE_MEMORY
;
517 if (global
.memory_db
== NULL
)
519 status
= asl_memory_open(global
.db_memory_max
, global
.db_memory_str_max
, &(global
.memory_db
));
520 if (status
!= ASL_STATUS_OK
)
522 asldebug("asl_memory_open: %s\n", asl_core_error(status
));
529 if (dbtype
& DB_TYPE_MEMORY
)
532 status
= asl_memory_save(global
.memory_db
, msg
, &msgid
);
533 if (status
!= ASL_STATUS_OK
)
535 /* save failed - reopen & retry*/
536 asldebug("asl_memory_save: %s\n", asl_core_error(status
));
537 asl_memory_close(global
.memory_db
);
538 global
.memory_db
= NULL
;
542 status
= asl_memory_save(global
.memory_db
, msg
, &msgid
);
543 if (status
!= ASL_STATUS_OK
)
545 asldebug("(retry) asl_memory_save: %s\n", asl_core_error(status
));
546 asl_memory_close(global
.memory_db
);
547 global
.memory_db
= NULL
;
555 dispatch_source_set_timer(timer_src
, dispatch_time(DISPATCH_TIME_NOW
, NSEC_PER_SEC
/ 2), DISPATCH_TIME_FOREVER
, 0);
556 dispatch_resume(timer_src
);
561 disaster_message(asl_msg_t
*msg
)
568 if ((global
.dbtype
& DB_TYPE_MEMORY
) == 0)
570 if (global
.memory_db
== NULL
)
572 status
= asl_memory_open(global
.db_memory_max
, global
.db_memory_str_max
, &(global
.memory_db
));
573 if (status
!= ASL_STATUS_OK
) asldebug("asl_memory_open: %s\n", asl_core_error(status
));
574 else asl_memory_save(global
.memory_db
, msg
, &msgid
);
580 * Do a database search.
583 db_query(asl_msg_list_t
*query
, asl_msg_list_t
**res
, uint64_t startid
, int count
, uint32_t duration
, int direction
, uint64_t *lastid
, int32_t ruid
, int32_t rgid
, int raccess
)
585 uint32_t status
, ucount
;
587 struct proc_uniqidentifierinfo pinfo
;
588 const char *str
= NULL
;
591 * Special case: if count is -1, we return ASL_STATUS_OK to indicate that the store is
592 * in memory, and ASL_STATUS_INVALID_STORE to indicate that the file store is in use.
596 if (global
.dbtype
& DB_TYPE_FILE
) return ASL_STATUS_INVALID_STORE
;
597 return ASL_STATUS_OK
;
603 uuid_clear(pinfo
.p_uuid
);
604 if (proc_pidinfo(raccess
, PROC_PIDUNIQIDENTIFIERINFO
, 1, &pinfo
, sizeof(pinfo
)) == sizeof(pinfo
))
606 uuid_unparse(pinfo
.p_uuid
, ustr
);
607 str
= (const char *)ustr
;
613 status
= ASL_STATUS_FAILED
;
615 if ((global
.dbtype
& DB_TYPE_MEMORY
) || (global
.disaster_occurred
!= 0))
617 status
= asl_memory_match_restricted_uuid(global
.memory_db
, query
, res
, lastid
, startid
, ucount
, duration
, direction
, ruid
, rgid
, str
);
624 register_session(task_name_t task_name
, pid_t pid
)
626 mach_port_t previous
;
629 if (task_name
== MACH_PORT_NULL
) return;
631 if (global
.dead_session_port
== MACH_PORT_NULL
)
633 mach_port_deallocate(mach_task_self(), task_name
);
637 for (i
= 0; i
< client_tasks_count
; i
++) if (task_name
== client_tasks
[i
])
639 mach_port_deallocate(mach_task_self(), task_name
);
643 if (client_tasks_count
== 0) client_tasks
= (task_name_t
*)calloc(1, sizeof(task_name_t
));
644 else client_tasks
= (task_name_t
*)reallocf(client_tasks
, (client_tasks_count
+ 1) * sizeof(task_name_t
));
646 if (client_tasks
== NULL
)
648 mach_port_deallocate(mach_task_self(), task_name
);
652 client_tasks
[client_tasks_count
] = task_name
;
653 client_tasks_count
++;
655 asldebug("register_session: %u PID %d\n", (unsigned int)task_name
, (int)pid
);
657 /* register for port death notification */
658 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
);
659 mach_port_deallocate(mach_task_self(), previous
);
661 asl_client_count_increment();
665 cancel_session(task_name_t task_name
)
669 for (i
= 0; (i
< client_tasks_count
) && (task_name
!= client_tasks
[i
]); i
++);
671 if (i
>= client_tasks_count
) return;
673 if (client_tasks_count
== 1)
677 client_tasks_count
= 0;
681 for (i
++; i
< client_tasks_count
; i
++) client_tasks
[i
-1] = client_tasks
[i
];
682 client_tasks_count
--;
683 client_tasks
= (task_name_t
*)reallocf(client_tasks
, client_tasks_count
* sizeof(task_name_t
));
686 asldebug("cancel_session: %u\n", (unsigned int)task_name
);
688 /* we hold a send right or dead name right for the task name port */
689 mach_port_deallocate(mach_task_self(), task_name
);
690 asl_client_count_decrement();
694 register_direct_watch(uint16_t port
)
696 #if TARGET_OS_EMBEDDED
699 struct sockaddr_in address
;
701 if (port
== 0) return ASL_STATUS_FAILED
;
703 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
704 if (sock
< 0) return ASL_STATUS_FAILED
;
706 address
.sin_family
= AF_INET
;
707 /* port must be sent in network byte order */
708 address
.sin_port
= port
;
709 address
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
711 if (connect(sock
, (struct sockaddr
*)&address
, sizeof(address
)) != 0) return ASL_STATUS_FAILED
;
714 setsockopt(sock
, SOL_SOCKET
, SO_NOSIGPIPE
, &i
, sizeof(i
));
717 setsockopt(sock
, IPPROTO_TCP
, TCP_NODELAY
, &i
, sizeof(i
));
719 /* make socket non-blocking */
720 flags
= fcntl(sock
, F_GETFL
, 0);
721 if (flags
== -1) flags
= 0;
722 fcntl(sock
, F_SETFL
, flags
| O_NONBLOCK
);
724 if (direct_watch_count
== 0)
726 direct_watch
= (int *)calloc(1, sizeof(int));
727 direct_watch_port
= (uint16_t *)calloc(1, sizeof(uint16_t));
731 direct_watch
= (int *)reallocf(direct_watch
, (direct_watch_count
+ 1) * sizeof(int));
732 direct_watch_port
= (uint16_t *)reallocf(direct_watch_port
, (direct_watch_count
+ 1) * sizeof(uint16_t));
735 if ((direct_watch
== NULL
) || (direct_watch_port
== NULL
))
742 free(direct_watch_port
);
743 direct_watch_port
= NULL
;
745 direct_watch_count
= 0;
746 global
.watchers_active
= 0;
747 if (global
.lockdown_session_count
> 0) global
.watchers_active
= 1;
749 return ASL_STATUS_FAILED
;
752 direct_watch
[direct_watch_count
] = sock
;
753 direct_watch_port
[direct_watch_count
] = port
;
754 direct_watch_count
++;
755 global
.watchers_active
= direct_watch_count
+ global
.lockdown_session_count
;
757 return ASL_STATUS_OK
;
759 return ASL_STATUS_FAILED
;
764 cancel_direct_watch(uint16_t port
)
766 #if TARGET_OS_EMBEDDED
769 for (i
= 0; (i
< direct_watch_count
) && (port
!= direct_watch_port
[i
]); i
++);
771 if (i
>= direct_watch_count
) return;
773 if (direct_watch_count
== 1)
778 free(direct_watch_port
);
779 direct_watch_port
= NULL
;
781 direct_watch_count
= 0;
782 global
.watchers_active
= 0;
783 if (global
.lockdown_session_count
> 0) global
.watchers_active
= 1;
787 for (i
++; i
< direct_watch_count
; i
++)
789 direct_watch
[i
-1] = direct_watch
[i
];
790 direct_watch_port
[i
-1] = direct_watch_port
[i
];
793 direct_watch_count
--;
794 global
.watchers_active
= direct_watch_count
+ global
.lockdown_session_count
;
796 direct_watch
= (int *)reallocf(direct_watch
, direct_watch_count
* sizeof(int));
797 direct_watch_port
= (uint16_t *)reallocf(direct_watch_port
, direct_watch_count
* sizeof(uint16_t));
799 if ((direct_watch
== NULL
) || (direct_watch_port
== NULL
))
804 free(direct_watch_port
);
805 direct_watch_port
= NULL
;
807 direct_watch_count
= 0;
808 global
.watchers_active
= 0;
809 if (global
.lockdown_session_count
> 0) global
.watchers_active
= 1;
816 syslogd_state_query(asl_msg_t
*q
, asl_msg_list_t
**res
, uid_t uid
)
825 if (res
== NULL
) return ASL_STATUS_INVALID_ARG
;
828 out
= asl_msg_list_new();
829 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
831 m
= asl_msg_new(ASL_TYPE_MSG
);
834 asl_msg_list_release(out
);
835 return ASL_STATUS_NO_MEMORY
;
838 asl_msg_list_append(out
, m
);
840 /* q must have [ASLOption control], so a "null" query really has count == 1 */
841 if (asl_msg_count(q
) == 1) all
= true;
843 if (all
|| (0 == asl_msg_lookup(q
, "debug", NULL
, NULL
)))
845 if (global
.debug
== 0) snprintf(val
, sizeof(val
), "0");
846 else snprintf(val
, sizeof(val
), "1 %s", global
.debug_file
);
847 asl_msg_set_key_val(m
, "debug", val
);
850 if (all
|| (0 == asl_msg_lookup(q
, "dbtype", NULL
, NULL
)))
853 if (global
.dbtype
& DB_TYPE_FILE
) n
++;
854 if (global
.dbtype
& DB_TYPE_MEMORY
) n
++;
858 asl_msg_set_key_val(m
, "dbtype", "unknown");
863 memset(val
, 0, sizeof(val
));
865 if (global
.dbtype
& DB_TYPE_FILE
)
868 strncat(val
, "file", 4);
869 if (i
< n
) strncat(val
, " ", 1);
872 if (global
.dbtype
& DB_TYPE_MEMORY
)
875 strncat(val
, "memory", 6);
876 if (i
< n
) strncat(val
, " ", 1);
879 asl_msg_set_key_val(m
, "dbtype", val
);
883 if (all
|| (0 == asl_msg_lookup(q
, "db_file_max", NULL
, NULL
)))
885 snprintf(val
, sizeof(val
), "%u", global
.db_file_max
);
886 asl_msg_set_key_val(m
, "db_file_max", val
);
889 if (all
|| (0 == asl_msg_lookup(q
, "db_memory_max", NULL
, NULL
)))
891 snprintf(val
, sizeof(val
), "%u", global
.db_memory_max
);
892 asl_msg_set_key_val(m
, "db_memory_max", val
);
895 if (all
|| (0 == asl_msg_lookup(q
, "db_memory_str_max", NULL
, NULL
)))
897 snprintf(val
, sizeof(val
), "%u", global
.db_memory_str_max
);
898 asl_msg_set_key_val(m
, "db_memory_str_max", val
);
901 if (all
|| (0 == asl_msg_lookup(q
, "mps_limit", NULL
, NULL
)))
903 snprintf(val
, sizeof(val
), "%u", global
.mps_limit
);
904 asl_msg_set_key_val(m
, "mps_limit", val
);
907 if (all
|| (0 == asl_msg_lookup(q
, "bsd_max_dup_time", NULL
, NULL
)))
909 snprintf(val
, sizeof(val
), "%llu", global
.bsd_max_dup_time
);
910 asl_msg_set_key_val(m
, "bsd_max_dup_time", val
);
913 if (all
|| (0 == asl_msg_lookup(q
, "mark_time", NULL
, NULL
)))
915 snprintf(val
, sizeof(val
), "%llu", global
.mark_time
);
916 asl_msg_set_key_val(m
, "mark_time", val
);
919 if (all
|| (0 == asl_msg_lookup(q
, "utmp_ttl", NULL
, NULL
)))
921 snprintf(val
, sizeof(val
), "%llu", (unsigned long long) global
.utmp_ttl
);
922 asl_msg_set_key_val(m
, "utmp_ttl", val
);
925 if (all
|| (0 == asl_msg_lookup(q
, "memory_size", NULL
, NULL
)))
927 snprintf(val
, sizeof(val
), "%lld", global
.memory_size
);
928 asl_msg_set_key_val(m
, "memory_size", val
);
931 if (all
|| (0 == asl_msg_lookup(q
, "memory_max", NULL
, NULL
)))
933 snprintf(val
, sizeof(val
), "%lld", global
.memory_max
);
934 asl_msg_set_key_val(m
, "memory_max", val
);
937 if (all
|| (0 == asl_msg_lookup(q
, "stats_interval", NULL
, NULL
)))
939 snprintf(val
, sizeof(val
), "%lld", (long long) global
.stats_interval
);
940 asl_msg_set_key_val(m
, "stats_interval", val
);
943 if (all
|| (0 == asl_msg_lookup(q
, "work_queue_count", NULL
, NULL
)))
945 snprintf(val
, sizeof(val
), "%d", global
.work_queue_count
);
946 asl_msg_set_key_val(m
, "work_queue_count", val
);
949 if (all
|| (0 == asl_msg_lookup(q
, "asl_queue_count", NULL
, NULL
)))
951 snprintf(val
, sizeof(val
), "%d", global
.asl_queue_count
);
952 asl_msg_set_key_val(m
, "asl_queue_count", val
);
955 if (all
|| (0 == asl_msg_lookup(q
, "bsd_queue_count", NULL
, NULL
)))
957 snprintf(val
, sizeof(val
), "%d", global
.bsd_queue_count
);
958 asl_msg_set_key_val(m
, "bsd_queue_count", val
);
961 if (all
|| (0 == asl_msg_lookup(q
, "client_count", NULL
, NULL
)))
963 snprintf(val
, sizeof(val
), "%d", global
.client_count
);
964 asl_msg_set_key_val(m
, "client_count", val
);
967 if (all
|| (0 == asl_msg_lookup(q
, "disaster_occurred", NULL
, NULL
)))
969 snprintf(val
, sizeof(val
), "%d", global
.disaster_occurred
);
970 asl_msg_set_key_val(m
, "disaster_occurred", val
);
974 if (all
|| (0 == asl_msg_lookup(q
, "lockdown_session_count", NULL
, NULL
)))
976 snprintf(val
, sizeof(val
), "%d", global
.lockdown_session_count
);
977 asl_msg_set_key_val(m
, "lockdown_session_count", val
);
980 if (all
|| (0 == asl_msg_lookup(q
, "remote_delay_time", NULL
, NULL
)))
982 snprintf(val
, sizeof(val
), "%u", global
.remote_delay_time
);
983 asl_msg_set_key_val(m
, "remote_delay_time", val
);
988 if (all
|| (0 == asl_msg_lookup(q
, "watchers_active", NULL
, NULL
)))
990 snprintf(val
, sizeof(val
), "%d", global
.watchers_active
);
991 asl_msg_set_key_val(m
, "watchers_active", val
);
994 for (i
= 0; i
< global
.module_count
; i
++)
996 if (all
|| (0 == asl_msg_lookup(q
, global
.module[i
]->name
, NULL
, NULL
)))
998 snprintf(val
, sizeof(val
), "%s", global
.module[i
]->enabled
? "enabled" : "disabled");
999 asl_msg_set_key_val(m
, global
.module[i
]->name
, val
);
1003 /* output module query must be on the asl_action_queue */
1004 asl_action_out_module_query(q
, m
, all
);
1006 /* synchronous actions use queries, since messages are simpleroutines */
1007 if (0 == asl_msg_lookup(q
, "action", &mval
, NULL
))
1010 if (uid
== 0) res
= asl_action_control_set_param(mval
);
1011 snprintf(val
, sizeof(val
), "%d", res
);
1012 asl_msg_set_key_val(m
, "action", val
);
1017 return ASL_STATUS_OK
;
1020 static kern_return_t
1021 _server_message_processing(asl_request_msg
*request
)
1023 const uint32_t sbits
= MACH_SEND_MSG
| MACH_SEND_TIMEOUT
;;
1025 asl_reply_msg
*reply
= calloc(1, sizeof(asl_reply_msg
) + MAX_TRAILER_SIZE
);
1027 voucher_mach_msg_state_t voucher
= voucher_mach_msg_adopt(&(request
->head
));
1029 /* MIG server routine */
1030 asl_ipc_server(&(request
->head
), &(reply
->head
));
1032 if (!(reply
->head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
))
1034 if (reply
->reply
.Reply__asl_server_message
.RetCode
== MIG_NO_REPLY
)
1036 reply
->head
.msgh_remote_port
= MACH_PORT_NULL
;
1038 else if ((reply
->reply
.Reply__asl_server_message
.RetCode
!= KERN_SUCCESS
) && (request
->head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
))
1040 /* destroy the request - but not the reply port */
1041 request
->head
.msgh_remote_port
= MACH_PORT_NULL
;
1042 mach_msg_destroy(&(request
->head
));
1046 if (reply
->head
.msgh_remote_port
!= MACH_PORT_NULL
)
1048 ks
= mach_msg(&(reply
->head
), sbits
, reply
->head
.msgh_size
, 0, MACH_PORT_NULL
, 10, MACH_PORT_NULL
);
1049 if ((ks
== MACH_SEND_INVALID_DEST
) || (ks
== MACH_SEND_TIMED_OUT
))
1052 mach_msg_destroy(&(reply
->head
));
1054 else if (ks
== MACH_SEND_INVALID_HEADER
)
1057 * This should never happen, but we can continue running.
1060 asldebug("ERROR: mach_msg() send failed with MACH_SEND_INVALID_HEADER 0x%08x\n", ks
);
1061 snprintf(str
, sizeof(str
), "[Sender syslogd] [Level 3] [PID %u] [Facility syslog] [Message mach_msg() send failed with status 0x%08x (MACH_SEND_INVALID_HEADER)]", global
.pid
, ks
);
1062 internal_log_message(str
);
1063 mach_msg_destroy(&(reply
->head
));
1065 else if (ks
== MACH_SEND_NO_BUFFER
)
1068 * This should never happen, but the kernel can run out of memory.
1069 * We clean up and continue running.
1072 asldebug("ERROR: mach_msg() send failed with MACH_SEND_NO_BUFFER 0x%08x\n", ks
);
1073 snprintf(str
, sizeof(str
), "[Sender syslogd] [Level 3] [PID %u] [Facility syslog] [Message mach_msg() send failed with status 0x%08x (MACH_SEND_NO_BUFFER)]", global
.pid
, ks
);
1074 internal_log_message(str
);
1075 mach_msg_destroy(&(reply
->head
));
1077 else if (ks
!= KERN_SUCCESS
)
1080 * Failed to send a reply message. This should never happen,
1081 * but the best action is to crash.
1084 asldebug("FATAL ERROR: mach_msg() send failed with status 0x%08x\n", ks
);
1085 snprintf(str
, sizeof(str
), "[Sender syslogd] [Level 1] [PID %u] [Facility syslog] [Message FATAL ERROR: mach_msg() send failed with status 0x%08x]", global
.pid
, ks
);
1086 internal_log_message(str
);
1091 else if (reply
->head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
)
1093 mach_msg_destroy(&reply
->head
);
1096 voucher_mach_msg_revert(voucher
);
1102 * Receives messages on the "com.apple.system.logger" mach port.
1103 * Services database search requests.
1104 * Runs in it's own thread.
1106 * The logic in this routine got a bit more complex due to (1) increased logging load and (2) 16K page size.
1107 * Out-of-line (OOL) memory sent to syslogd from libasl is allocated in pages, so the minimum size of a
1108 * message is one page. Since this routine can get slammed with messages at a very high rate, and since
1109 * the message queue in the kernel is only 5 messages, it is critical that this routine service the port
1110 * as fast as possible. To that end, it needs to do as little processing as possible.
1111 * In the version of this code found up to syslog-312, this routine received messages and dispatched them
1112 * on the asl_server_queue for further processing. When pages were only 4K, this was not a problem. With
1113 * 16K pages, it only takes about 650 messages to run syslogd's dirty memoory size up to the point of its
1114 * jetsam limit. Code was added here to track the memory being used in this queue + the work queue that's
1115 * used by process_message(), such that messages will get dropped if the queues reach a memory limit.
1116 * The actual message data in the VM pages is typically only a few hundred bytes, so holding VM pages in
1117 * the queue was a waste, and seriously limited the number of queued messages.
1119 * The solution implemented here is a bit of a hack. It peeks at the received message header to determine
1120 * which MIG routine is being called. If the call is for _asl_server_message, it calls asl_ipc_server()
1121 * on the server thread. This routes the call through the MIG server code for error checking and so on,
1122 * and invokes _asl_server_message() on this thread. _asl_server_message() has been modified to copy
1123 * the message data into malloced memory, vm_deallocate the OOL memory, and then it dispatches the real
1124 * work onto the asl_server_queue.
1129 asl_request_msg
*request
;
1130 uint32_t rqs
, asl_server_message_num
= 0;
1132 struct timeval now
, send_time
;
1133 mach_dead_name_notification_t
*deadname
;
1134 const uint32_t rbits
= MACH_RCV_MSG
| MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT
) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0
) | MACH_RCV_VOUCHER
;
1135 send_time
.tv_sec
= 0;
1136 send_time
.tv_usec
= 0;
1138 const char *routine
;
1140 } migmap
[] = { subsystem_to_name_map_asl_ipc
};
1142 for (i
= 0; (i
< (sizeof(migmap
) / sizeof(struct mig_map_s
))) && (asl_server_message_num
== 0); i
++)
1144 if (!strcmp(migmap
[i
].routine
, "_asl_server_message")) asl_server_message_num
= migmap
[i
].num
;
1147 rqs
= sizeof(asl_request_msg
) + MAX_TRAILER_SIZE
;
1149 asl_server_queue
= dispatch_queue_create("ASL Server Queue", NULL
);
1158 request
= (asl_request_msg
*)calloc(1, rqs
);
1159 if (request
== NULL
) continue;
1161 request
->head
.msgh_local_port
= global
.server_port
;
1162 request
->head
.msgh_size
= rqs
;
1164 ks
= mach_msg(&(request
->head
), rbits
, 0, rqs
, global
.listen_set
, 0, MACH_PORT_NULL
);
1165 if (ks
!= KERN_SUCCESS
)
1168 * This shouldn't happen, but if we get a failure the best thing to do is to crash.
1171 asldebug("FATAL ERROR: mach_msg() receive failed with status 0x%08x\n", ks
);
1172 snprintf(str
, sizeof(str
), "[Sender syslogd] [Level 1] [PID %u] [Facility syslog] [Message FATAL ERROR: mach_msg() receive failed with status 0x%08x]", global
.pid
, ks
);
1173 internal_log_message(str
);
1178 if (request
->head
.msgh_local_port
== global
.dead_session_port
&&
1179 request
->head
.msgh_id
== MACH_NOTIFY_DEAD_NAME
)
1181 deadname
= (mach_dead_name_notification_t
*)request
;
1182 dispatch_async(asl_server_queue
, ^{
1183 cancel_session(deadname
->not_port
);
1184 /* dead name notification includes a dead name right */
1185 mach_port_deallocate(mach_task_self(), deadname
->not_port
);
1193 if (request
->head
.msgh_id
== asl_server_message_num
)
1195 _server_message_processing(request
);
1199 dispatch_async(asl_server_queue
, ^{ _server_message_processing(request
); });
1205 caller_get_read_entitlement(pid_t pid
, uid_t
*uid
, gid_t
*gid
)
1207 #if TARGET_OS_EMBEDDED
1208 xpc_object_t edata
, entitlements
, val
;
1214 edata
= xpc_copy_entitlements_for_pid(pid
);
1215 if (edata
== NULL
) return;
1217 ptr
= xpc_data_get_bytes_ptr(edata
);
1218 len
= xpc_data_get_length(edata
);
1220 entitlements
= xpc_create_from_plist(ptr
, len
);
1222 if (entitlements
== NULL
) return;
1224 if (xpc_get_type(entitlements
) != XPC_TYPE_DICTIONARY
)
1226 asldebug("xpc_copy_entitlements_for_pid has non-dictionary data for pid %d\n", pid
);
1230 bval
= xpc_dictionary_get_bool(entitlements
, ASL_ENTITLEMENT_KEY
);
1231 if (bval
&& (uid
!= NULL
))
1234 xpc_release(entitlements
);
1238 val
= xpc_dictionary_get_value(entitlements
, ASL_ENTITLEMENT_UID_KEY
);
1241 if ((xpc_get_type(val
) == XPC_TYPE_INT64
) && (uid
!= NULL
))
1243 ival
= xpc_int64_get_value(val
);
1248 val
= xpc_dictionary_get_value(entitlements
, ASL_ENTITLEMENT_GID_KEY
);
1251 if ((xpc_get_type(val
) == XPC_TYPE_INT64
) && (gid
!= NULL
))
1253 ival
= xpc_int64_get_value(val
);
1258 xpc_release(entitlements
);
1262 static kern_return_t
1263 __asl_server_query_internal
1267 mach_msg_type_number_t requestCnt
,
1273 mach_msg_type_number_t
*replyCnt
,
1281 asl_msg_list_t
*query
;
1282 asl_msg_list_t
*res
;
1283 char *out
, *vmbuffer
;
1285 kern_return_t kstatus
;
1287 *status
= ASL_STATUS_OK
;
1289 if ((request
!= NULL
) && (request
[requestCnt
- 1] != '\0'))
1291 *status
= ASL_STATUS_INVALID_ARG
;
1292 vm_deallocate(mach_task_self(), (vm_address_t
)request
, requestCnt
);
1293 return KERN_SUCCESS
;
1296 query
= asl_msg_list_from_string(request
);
1297 if (request
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)request
, requestCnt
);
1300 /* A query list containing a single query, which itself contains
1301 * [ASLOption control] is an internal state query */
1302 if ((query
!= NULL
) && (query
->count
== 1) && asl_check_option(query
->msg
[0], ASL_OPT_CONTROL
))
1304 *status
= syslogd_state_query(query
->msg
[0], &res
, uid
);
1309 #if TARGET_OS_EMBEDDED
1315 caller_get_read_entitlement(pid
, &uid
, &gid
);
1316 if (uid
== 0) x
= 0;
1319 *status
= db_query(query
, &res
, startid
, count
, duration
, direction
, lastid
, uid
, gid
, x
);
1322 asl_msg_list_release(query
);
1323 if (*status
!= ASL_STATUS_INVALID_STORE
)
1327 else if (*status
!= ASL_STATUS_OK
)
1329 if (res
!= NULL
) asl_msg_list_release(res
);
1330 return KERN_SUCCESS
;
1335 out
= asl_msg_list_to_string(res
, &outlen
);
1336 asl_msg_list_release(res
);
1338 if ((out
== NULL
) || (outlen
== 0)) return KERN_SUCCESS
;
1340 kstatus
= vm_allocate(mach_task_self(), (vm_address_t
*)&vmbuffer
, outlen
, VM_FLAGS_ANYWHERE
| VM_MAKE_TAG(VM_MEMORY_ASL
));
1341 if (kstatus
!= KERN_SUCCESS
)
1347 memmove(vmbuffer
, out
, outlen
);
1353 return KERN_SUCCESS
;
1357 __asl_server_query_2
1361 mach_msg_type_number_t requestCnt
,
1366 mach_msg_type_number_t
*replyCnt
,
1372 uid_t uid
= (uid_t
)-1;
1373 gid_t gid
= (gid_t
)-1;
1374 pid_t pid
= (pid_t
)-1;
1376 int direction
= SEARCH_FORWARD
;
1377 if (flags
& QUERY_FLAG_SEARCH_REVERSE
) direction
= SEARCH_BACKWARD
;
1379 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1381 return __asl_server_query_internal(server
, request
, requestCnt
, startid
, count
, QUERY_DURATION_UNLIMITED
, direction
, reply
, replyCnt
, lastid
, status
, uid
, gid
, pid
);
1389 mach_msg_type_number_t requestCnt
,
1394 mach_msg_type_number_t
*replyCnt
,
1397 security_token_t
*token
1400 int direction
= SEARCH_FORWARD
;
1401 if (flags
& QUERY_FLAG_SEARCH_REVERSE
) direction
= SEARCH_BACKWARD
;
1403 return __asl_server_query_internal(server
, request
, requestCnt
, startid
, count
, QUERY_DURATION_UNLIMITED
, direction
, reply
, replyCnt
, lastid
, status
, (uid_t
)token
->val
[0], (gid_t
)token
->val
[1], (pid_t
)-1);
1407 __asl_server_query_timeout
1411 mach_msg_type_number_t requestCnt
,
1416 mach_msg_type_number_t
*replyCnt
,
1422 uid_t uid
= (uid_t
)-1;
1423 gid_t gid
= (gid_t
)-1;
1424 pid_t pid
= (pid_t
)-1;
1425 int direction
= SEARCH_FORWARD
;
1426 if (flags
& QUERY_FLAG_SEARCH_REVERSE
) direction
= SEARCH_BACKWARD
;
1428 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1430 return __asl_server_query_internal(server
, request
, requestCnt
, startid
, count
, QUERY_DURATION_UNLIMITED
, direction
, reply
, replyCnt
, lastid
, status
, uid
, gid
, pid
);
1438 mach_msg_type_number_t requestCnt
,
1444 mach_msg_type_number_t
*replyCnt
,
1450 uid_t uid
= (uid_t
)-1;
1451 gid_t gid
= (gid_t
)-1;
1452 pid_t pid
= (pid_t
)-1;
1454 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1456 return __asl_server_query_internal(server
, request
, requestCnt
, startid
, count
, duration
, direction
, reply
, replyCnt
, lastid
, status
, uid
, gid
, pid
);
1464 mach_msg_type_number_t requestCnt
,
1466 security_token_t
*token
1469 return KERN_SUCCESS
;
1473 * Does the actual processing for __asl_server_message.
1474 * Dispatched on asl_server_queue. This lets us avoid
1475 * calling asl_msg_from_string(), task_name_for_pid(),
1476 * and register_session() on the database_server() thread.
1479 _asl_message_processing(char *mbuf
, uint64_t msize
, uid_t uid
, gid_t gid
, pid_t pid
)
1483 kern_return_t kstatus
;
1484 mach_port_name_t client
;
1486 msg
= asl_msg_from_string(mbuf
);
1490 * process_message() will update global.memory_size with the
1491 * size of msg, and it increements the work_queue_count.
1493 OSAtomicAdd64(-1ll * msize
, &global
.memory_size
);
1494 OSAtomicDecrement32(&global
.work_queue_count
);
1496 if (msg
== NULL
) return;
1498 client
= MACH_PORT_NULL
;
1499 kstatus
= task_name_for_pid(mach_task_self(), pid
, &client
);
1500 if (kstatus
== KERN_SUCCESS
) register_session(client
, pid
);
1502 snprintf(tmp
, sizeof(tmp
), "%d", uid
);
1503 asl_msg_set_key_val(msg
, ASL_KEY_UID
, tmp
);
1505 snprintf(tmp
, sizeof(tmp
), "%d", gid
);
1506 asl_msg_set_key_val(msg
, ASL_KEY_GID
, tmp
);
1508 snprintf(tmp
, sizeof(tmp
), "%d", pid
);
1509 asl_msg_set_key_val(msg
, ASL_KEY_PID
, tmp
);
1511 process_message(msg
, SOURCE_ASL_MESSAGE
);
1515 * This MIG server routine is something of a special case in database_server() above.
1516 * It is called on the server thread that's responsible for servicing syslogd's mach port.
1517 * In this routine we copy the actual ASL message raw string out of the message into
1518 * malloc memory, deallocate the message, and dispatch the real work onto the asl_server_queue.
1521 __asl_server_message
1525 mach_msg_type_number_t messageCnt
,
1534 if (message
== NULL
) return KERN_SUCCESS
;
1536 if (message
[messageCnt
- 1] != '\0')
1538 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1539 return KERN_SUCCESS
;
1542 asldebug("__asl_server_message: %s\n", message
);
1544 if ((global
.memory_size
+ messageCnt
) > global
.memory_max
)
1547 asldebug("Server queue dropped message. message size %u queue size %lld max %lld\n", messageCnt
, global
.memory_size
, global
.memory_max
);
1548 snprintf(str
, sizeof(str
), "[Sender syslogd] [Level 2] [PID %u] [Message Received message size %u overflows work queue (size %lld limit %lld) - dropping message] [UID 0] [UID 0] [Facility syslog]", global
.pid
, messageCnt
, global
.memory_size
, global
.memory_max
);
1549 internal_log_message(str
);
1551 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1552 return KERN_SUCCESS
;
1555 mbuf
= malloc(messageCnt
);
1556 if (mbuf
!= NULL
) memcpy(mbuf
, message
, messageCnt
);
1557 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1559 if (mbuf
== NULL
) return KERN_SUCCESS
;
1564 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1566 OSAtomicIncrement32(&global
.work_queue_count
);
1567 OSAtomicAdd64(messageCnt
, &(global
.memory_size
));
1569 dispatch_async(asl_server_queue
, ^{ _asl_message_processing(mbuf
, messageCnt
, uid
, gid
, pid
); });
1571 return KERN_SUCCESS
;
1575 __asl_server_create_aux_link
1579 mach_msg_type_number_t messageCnt
,
1580 mach_port_t
*fileport
,
1582 mach_msg_type_number_t
*newurlCnt
,
1592 kern_return_t kstatus
;
1593 mach_port_name_t client
;
1594 char *url
, *vmbuffer
;
1597 *status
= ASL_STATUS_OK
;
1598 *fileport
= MACH_PORT_NULL
;
1601 if (message
== NULL
)
1603 *status
= ASL_STATUS_INVALID_ARG
;
1604 return KERN_SUCCESS
;
1607 if (message
[messageCnt
- 1] != '\0')
1609 *status
= ASL_STATUS_INVALID_ARG
;
1610 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1611 return KERN_SUCCESS
;
1614 asldebug("__asl_server_create_aux_link: %s\n", (message
== NULL
) ? "NULL" : message
);
1616 if ((global
.dbtype
& DB_TYPE_FILE
) == 0)
1618 *status
= ASL_STATUS_INVALID_STORE
;
1619 return KERN_SUCCESS
;
1622 *fileport
= MACH_PORT_NULL
;
1624 msg
= asl_msg_from_string(message
);
1625 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1627 if (msg
== NULL
) return KERN_SUCCESS
;
1632 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1634 client
= MACH_PORT_NULL
;
1635 kstatus
= task_name_for_pid(mach_task_self(), pid
, &client
);
1636 if (kstatus
== KERN_SUCCESS
) register_session(client
, pid
);
1638 snprintf(tmp
, sizeof(tmp
), "%d", uid
);
1639 asl_msg_set_key_val(msg
, ASL_KEY_UID
, tmp
);
1641 snprintf(tmp
, sizeof(tmp
), "%d", gid
);
1642 asl_msg_set_key_val(msg
, ASL_KEY_GID
, tmp
);
1644 snprintf(tmp
, sizeof(tmp
), "%d", pid
);
1645 asl_msg_set_key_val(msg
, ASL_KEY_PID
, tmp
);
1647 /* create a file for the client */
1648 *status
= asl_store_open_aux(global
.file_db
, msg
, &fd
, &url
);
1649 asl_msg_release(msg
);
1650 if (*status
!= ASL_STATUS_OK
) return KERN_SUCCESS
;
1653 if (fd
>= 0) close(fd
);
1654 *status
= ASL_STATUS_FAILED
;
1655 return KERN_SUCCESS
;
1658 if (fileport_makeport(fd
, (fileport_t
*)fileport
) < 0)
1662 *status
= ASL_STATUS_FAILED
;
1663 return KERN_SUCCESS
;
1668 *newurlCnt
= strlen(url
) + 1;
1670 kstatus
= vm_allocate(mach_task_self(), (vm_address_t
*)&vmbuffer
, *newurlCnt
, VM_FLAGS_ANYWHERE
| VM_MAKE_TAG(VM_MEMORY_ASL
));
1671 if (kstatus
!= KERN_SUCCESS
)
1677 memmove(vmbuffer
, url
, *newurlCnt
);
1682 return KERN_SUCCESS
;
1686 __asl_server_register_direct_watch
1693 uint16_t p16
= port
;
1694 pid_t pid
= (pid_t
)-1;
1696 audit_token_to_au32(token
, NULL
, NULL
, NULL
, NULL
, NULL
, &pid
, NULL
, NULL
);
1698 asldebug("__asl_server_register_direct_watch: pid %u port %hu\n", pid
, ntohs(p16
));
1700 dispatch_once(&watch_init_once
, ^{
1701 watch_queue
= dispatch_queue_create("Direct Watch Queue", NULL
);
1704 dispatch_async(watch_queue
, ^{ register_direct_watch(p16
); });
1706 return KERN_SUCCESS
;
1710 __asl_server_cancel_direct_watch
1717 uint16_t p16
= port
;
1719 asldebug("__asl_server_cancel_direct_watch: %hu\n", ntohs(p16
));
1721 dispatch_once(&watch_init_once
, ^{
1722 watch_queue
= dispatch_queue_create("Direct Watch Queue", NULL
);
1725 dispatch_async(watch_queue
, ^{ cancel_direct_watch(p16
); });
1727 return KERN_SUCCESS
;