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
)
824 asl_out_module_t
*om
;
826 if (res
== NULL
) return ASL_STATUS_INVALID_ARG
;
829 out
= asl_msg_list_new();
830 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
832 m
= asl_msg_new(ASL_TYPE_MSG
);
835 asl_msg_list_release(out
);
836 return ASL_STATUS_NO_MEMORY
;
839 asl_msg_list_append(out
, m
);
841 /* q must have [ASLOption control], so a "null" query really has count == 1 */
842 if (asl_msg_count(q
) == 1) all
= true;
844 if (all
|| (0 == asl_msg_lookup(q
, "debug", NULL
, NULL
)))
846 if (global
.debug
== 0) snprintf(val
, sizeof(val
), "0");
847 else snprintf(val
, sizeof(val
), "1 %s", global
.debug_file
);
848 asl_msg_set_key_val(m
, "debug", val
);
851 if (all
|| (0 == asl_msg_lookup(q
, "dbtype", NULL
, NULL
)))
854 if (global
.dbtype
& DB_TYPE_FILE
) n
++;
855 if (global
.dbtype
& DB_TYPE_MEMORY
) n
++;
859 asl_msg_set_key_val(m
, "dbtype", "unknown");
864 memset(val
, 0, sizeof(val
));
866 if (global
.dbtype
& DB_TYPE_FILE
)
869 strncat(val
, "file", 4);
870 if (i
< n
) strncat(val
, " ", 1);
873 if (global
.dbtype
& DB_TYPE_MEMORY
)
876 strncat(val
, "memory", 6);
877 if (i
< n
) strncat(val
, " ", 1);
880 asl_msg_set_key_val(m
, "dbtype", val
);
884 if (all
|| (0 == asl_msg_lookup(q
, "db_file_max", NULL
, NULL
)))
886 snprintf(val
, sizeof(val
), "%u", global
.db_file_max
);
887 asl_msg_set_key_val(m
, "db_file_max", val
);
890 if (all
|| (0 == asl_msg_lookup(q
, "db_memory_max", NULL
, NULL
)))
892 snprintf(val
, sizeof(val
), "%u", global
.db_memory_max
);
893 asl_msg_set_key_val(m
, "db_memory_max", val
);
896 if (all
|| (0 == asl_msg_lookup(q
, "db_memory_str_max", NULL
, NULL
)))
898 snprintf(val
, sizeof(val
), "%u", global
.db_memory_str_max
);
899 asl_msg_set_key_val(m
, "db_memory_str_max", val
);
902 if (all
|| (0 == asl_msg_lookup(q
, "mps_limit", NULL
, NULL
)))
904 snprintf(val
, sizeof(val
), "%u", global
.mps_limit
);
905 asl_msg_set_key_val(m
, "mps_limit", val
);
908 if (all
|| (0 == asl_msg_lookup(q
, "bsd_max_dup_time", NULL
, NULL
)))
910 snprintf(val
, sizeof(val
), "%llu", global
.bsd_max_dup_time
);
911 asl_msg_set_key_val(m
, "bsd_max_dup_time", val
);
914 if (all
|| (0 == asl_msg_lookup(q
, "mark_time", NULL
, NULL
)))
916 snprintf(val
, sizeof(val
), "%llu", global
.mark_time
);
917 asl_msg_set_key_val(m
, "mark_time", val
);
920 if (all
|| (0 == asl_msg_lookup(q
, "utmp_ttl", NULL
, NULL
)))
922 snprintf(val
, sizeof(val
), "%llu", (unsigned long long) global
.utmp_ttl
);
923 asl_msg_set_key_val(m
, "utmp_ttl", val
);
926 if (all
|| (0 == asl_msg_lookup(q
, "memory_size", NULL
, NULL
)))
928 snprintf(val
, sizeof(val
), "%lld", global
.memory_size
);
929 asl_msg_set_key_val(m
, "memory_size", val
);
932 if (all
|| (0 == asl_msg_lookup(q
, "memory_max", NULL
, NULL
)))
934 snprintf(val
, sizeof(val
), "%lld", global
.memory_max
);
935 asl_msg_set_key_val(m
, "memory_max", val
);
938 if (all
|| (0 == asl_msg_lookup(q
, "stats_interval", NULL
, NULL
)))
940 snprintf(val
, sizeof(val
), "%lld", (long long) global
.stats_interval
);
941 asl_msg_set_key_val(m
, "stats_interval", val
);
944 if (all
|| (0 == asl_msg_lookup(q
, "work_queue_count", NULL
, NULL
)))
946 snprintf(val
, sizeof(val
), "%d", global
.work_queue_count
);
947 asl_msg_set_key_val(m
, "work_queue_count", val
);
950 if (all
|| (0 == asl_msg_lookup(q
, "asl_queue_count", NULL
, NULL
)))
952 snprintf(val
, sizeof(val
), "%d", global
.asl_queue_count
);
953 asl_msg_set_key_val(m
, "asl_queue_count", val
);
956 if (all
|| (0 == asl_msg_lookup(q
, "bsd_queue_count", NULL
, NULL
)))
958 snprintf(val
, sizeof(val
), "%d", global
.bsd_queue_count
);
959 asl_msg_set_key_val(m
, "bsd_queue_count", val
);
962 if (all
|| (0 == asl_msg_lookup(q
, "client_count", NULL
, NULL
)))
964 snprintf(val
, sizeof(val
), "%d", global
.client_count
);
965 asl_msg_set_key_val(m
, "client_count", val
);
968 if (all
|| (0 == asl_msg_lookup(q
, "disaster_occurred", NULL
, NULL
)))
970 snprintf(val
, sizeof(val
), "%d", global
.disaster_occurred
);
971 asl_msg_set_key_val(m
, "disaster_occurred", val
);
975 if (all
|| (0 == asl_msg_lookup(q
, "lockdown_session_count", NULL
, NULL
)))
977 snprintf(val
, sizeof(val
), "%d", global
.lockdown_session_count
);
978 asl_msg_set_key_val(m
, "lockdown_session_count", val
);
981 if (all
|| (0 == asl_msg_lookup(q
, "remote_delay_time", NULL
, NULL
)))
983 snprintf(val
, sizeof(val
), "%u", global
.remote_delay_time
);
984 asl_msg_set_key_val(m
, "remote_delay_time", val
);
989 if (all
|| (0 == asl_msg_lookup(q
, "watchers_active", NULL
, NULL
)))
991 snprintf(val
, sizeof(val
), "%d", global
.watchers_active
);
992 asl_msg_set_key_val(m
, "watchers_active", val
);
995 for (i
= 0; i
< global
.module_count
; i
++)
997 if (all
|| (0 == asl_msg_lookup(q
, global
.module[i
]->name
, NULL
, NULL
)))
999 snprintf(val
, sizeof(val
), "%s", global
.module[i
]->enabled
? "enabled" : "disabled");
1000 asl_msg_set_key_val(m
, global
.module[i
]->name
, val
);
1004 for (om
= global
.asl_out_module
; om
!= NULL
; om
= om
->next
)
1006 if (all
|| (0 == asl_msg_lookup(q
, om
->name
, NULL
, NULL
)))
1008 snprintf(val
, sizeof(val
), "%s", om
->flags
& MODULE_FLAG_ENABLED
? "enabled" : "disabled");
1009 if (om
->name
== NULL
) asl_msg_set_key_val(m
, "asl.conf", val
);
1010 else asl_msg_set_key_val(m
, om
->name
, val
);
1014 /* synchronous actions use queries, since messages are simpleroutines */
1015 if (0 == asl_msg_lookup(q
, "action", &mval
, NULL
))
1018 if (uid
== 0) res
= asl_action_control_set_param(mval
);
1019 snprintf(val
, sizeof(val
), "%d", res
);
1020 asl_msg_set_key_val(m
, "action", val
);
1025 return ASL_STATUS_OK
;
1028 static kern_return_t
1029 _server_message_processing(asl_request_msg
*request
)
1031 const uint32_t sbits
= MACH_SEND_MSG
| MACH_SEND_TIMEOUT
;;
1033 asl_reply_msg
*reply
= calloc(1, sizeof(asl_reply_msg
) + MAX_TRAILER_SIZE
);
1035 voucher_mach_msg_state_t voucher
= voucher_mach_msg_adopt(&(request
->head
));
1037 /* MIG server routine */
1038 asl_ipc_server(&(request
->head
), &(reply
->head
));
1040 if (!(reply
->head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
))
1042 if (reply
->reply
.Reply__asl_server_message
.RetCode
== MIG_NO_REPLY
)
1044 reply
->head
.msgh_remote_port
= MACH_PORT_NULL
;
1046 else if ((reply
->reply
.Reply__asl_server_message
.RetCode
!= KERN_SUCCESS
) && (request
->head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
))
1048 /* destroy the request - but not the reply port */
1049 request
->head
.msgh_remote_port
= MACH_PORT_NULL
;
1050 mach_msg_destroy(&(request
->head
));
1054 if (reply
->head
.msgh_remote_port
!= MACH_PORT_NULL
)
1056 ks
= mach_msg(&(reply
->head
), sbits
, reply
->head
.msgh_size
, 0, MACH_PORT_NULL
, 10, MACH_PORT_NULL
);
1057 if ((ks
== MACH_SEND_INVALID_DEST
) || (ks
== MACH_SEND_TIMED_OUT
))
1060 mach_msg_destroy(&(reply
->head
));
1062 else if (ks
== MACH_SEND_INVALID_HEADER
)
1065 * This should never happen, but we can continue running.
1068 asldebug("ERROR: mach_msg() send failed with MACH_SEND_INVALID_HEADER 0x%08x\n", ks
);
1069 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
);
1070 internal_log_message(str
);
1071 mach_msg_destroy(&(reply
->head
));
1073 else if (ks
== MACH_SEND_NO_BUFFER
)
1076 * This should never happen, but the kernel can run out of memory.
1077 * We clean up and continue running.
1080 asldebug("ERROR: mach_msg() send failed with MACH_SEND_NO_BUFFER 0x%08x\n", ks
);
1081 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
);
1082 internal_log_message(str
);
1083 mach_msg_destroy(&(reply
->head
));
1085 else if (ks
!= KERN_SUCCESS
)
1088 * Failed to send a reply message. This should never happen,
1089 * but the best action is to crash.
1092 asldebug("FATAL ERROR: mach_msg() send failed with status 0x%08x\n", ks
);
1093 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
);
1094 internal_log_message(str
);
1099 else if (reply
->head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
)
1101 mach_msg_destroy(&reply
->head
);
1104 voucher_mach_msg_revert(voucher
);
1110 * Receives messages on the "com.apple.system.logger" mach port.
1111 * Services database search requests.
1112 * Runs in it's own thread.
1114 * The logic in this routine got a bit more complex due to (1) increased logging load and (2) 16K page size.
1115 * Out-of-line (OOL) memory sent to syslogd from libasl is allocated in pages, so the minimum size of a
1116 * message is one page. Since this routine can get slammed with messages at a very high rate, and since
1117 * the message queue in the kernel is only 5 messages, it is critical that this routine service the port
1118 * as fast as possible. To that end, it needs to do as little processing as possible.
1119 * In the version of this code found up to syslog-312, this routine received messages and dispatched them
1120 * on the asl_server_queue for further processing. When pages were only 4K, this was not a problem. With
1121 * 16K pages, it only takes about 650 messages to run syslogd's dirty memoory size up to the point of its
1122 * jetsam limit. Code was added here to track the memory being used in this queue + the work queue that's
1123 * used by process_message(), such that messages will get dropped if the queues reach a memory limit.
1124 * The actual message data in the VM pages is typically only a few hundred bytes, so holding VM pages in
1125 * the queue was a waste, and seriously limited the number of queued messages.
1127 * The solution implemented here is a bit of a hack. It peeks at the received message header to determine
1128 * which MIG routine is being called. If the call is for _asl_server_message, it calls asl_ipc_server()
1129 * on the server thread. This routes the call through the MIG server code for error checking and so on,
1130 * and invokes _asl_server_message() on this thread. _asl_server_message() has been modified to copy
1131 * the message data into malloced memory, vm_deallocate the OOL memory, and then it dispatches the real
1132 * work onto the asl_server_queue.
1137 asl_request_msg
*request
;
1138 uint32_t rqs
, asl_server_message_num
= 0;
1140 struct timeval now
, send_time
;
1141 mach_dead_name_notification_t
*deadname
;
1142 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
;
1143 send_time
.tv_sec
= 0;
1144 send_time
.tv_usec
= 0;
1146 const char *routine
;
1148 } migmap
[] = { subsystem_to_name_map_asl_ipc
};
1150 for (i
= 0; (i
< (sizeof(migmap
) / sizeof(struct mig_map_s
))) && (asl_server_message_num
== 0); i
++)
1152 if (!strcmp(migmap
[i
].routine
, "_asl_server_message")) asl_server_message_num
= migmap
[i
].num
;
1155 rqs
= sizeof(asl_request_msg
) + MAX_TRAILER_SIZE
;
1157 asl_server_queue
= dispatch_queue_create("ASL Server Queue", NULL
);
1166 request
= (asl_request_msg
*)calloc(1, rqs
);
1167 if (request
== NULL
) continue;
1169 request
->head
.msgh_local_port
= global
.server_port
;
1170 request
->head
.msgh_size
= rqs
;
1172 ks
= mach_msg(&(request
->head
), rbits
, 0, rqs
, global
.listen_set
, 0, MACH_PORT_NULL
);
1173 if (ks
!= KERN_SUCCESS
)
1176 * This shouldn't happen, but if we get a failure the best thing to do is to crash.
1179 asldebug("FATAL ERROR: mach_msg() receive failed with status 0x%08x\n", ks
);
1180 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
);
1181 internal_log_message(str
);
1186 if (request
->head
.msgh_id
== MACH_NOTIFY_DEAD_NAME
)
1188 deadname
= (mach_dead_name_notification_t
*)request
;
1189 dispatch_async(asl_server_queue
, ^{
1190 cancel_session(deadname
->not_port
);
1191 /* dead name notification includes a dead name right */
1192 mach_port_deallocate(mach_task_self(), deadname
->not_port
);
1200 if (request
->head
.msgh_id
== asl_server_message_num
)
1202 _server_message_processing(request
);
1206 dispatch_async(asl_server_queue
, ^{ _server_message_processing(request
); });
1212 caller_get_read_entitlement(pid_t pid
, uid_t
*uid
, gid_t
*gid
)
1214 #if TARGET_OS_EMBEDDED
1215 xpc_object_t edata
, entitlements
, val
;
1221 edata
= xpc_copy_entitlements_for_pid(pid
);
1222 if (edata
== NULL
) return;
1224 ptr
= xpc_data_get_bytes_ptr(edata
);
1225 len
= xpc_data_get_length(edata
);
1227 entitlements
= xpc_create_from_plist(ptr
, len
);
1229 if (entitlements
== NULL
) return;
1231 if (xpc_get_type(entitlements
) != XPC_TYPE_DICTIONARY
)
1233 asldebug("xpc_copy_entitlements_for_pid has non-dictionary data for pid %d\n", pid
);
1237 bval
= xpc_dictionary_get_bool(entitlements
, ASL_ENTITLEMENT_KEY
);
1238 if (bval
&& (uid
!= NULL
))
1241 xpc_release(entitlements
);
1245 val
= xpc_dictionary_get_value(entitlements
, ASL_ENTITLEMENT_UID_KEY
);
1248 if ((xpc_get_type(val
) == XPC_TYPE_INT64
) && (uid
!= NULL
))
1250 ival
= xpc_int64_get_value(val
);
1255 val
= xpc_dictionary_get_value(entitlements
, ASL_ENTITLEMENT_GID_KEY
);
1258 if ((xpc_get_type(val
) == XPC_TYPE_INT64
) && (gid
!= NULL
))
1260 ival
= xpc_int64_get_value(val
);
1265 xpc_release(entitlements
);
1269 static kern_return_t
1270 __asl_server_query_internal
1274 mach_msg_type_number_t requestCnt
,
1280 mach_msg_type_number_t
*replyCnt
,
1288 asl_msg_list_t
*query
;
1289 asl_msg_list_t
*res
;
1290 char *out
, *vmbuffer
;
1292 kern_return_t kstatus
;
1294 *status
= ASL_STATUS_OK
;
1296 if ((request
!= NULL
) && (request
[requestCnt
- 1] != '\0'))
1298 *status
= ASL_STATUS_INVALID_ARG
;
1299 vm_deallocate(mach_task_self(), (vm_address_t
)request
, requestCnt
);
1300 return KERN_SUCCESS
;
1303 query
= asl_msg_list_from_string(request
);
1304 if (request
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)request
, requestCnt
);
1307 /* A query list containing a single query, which itself contains
1308 * [ASLOption control] is an internal state query */
1309 if ((query
!= NULL
) && (query
->count
== 1) && asl_check_option(query
->msg
[0], ASL_OPT_CONTROL
))
1311 *status
= syslogd_state_query(query
->msg
[0], &res
, uid
);
1316 #if TARGET_OS_EMBEDDED
1322 caller_get_read_entitlement(pid
, &uid
, &gid
);
1323 if (uid
== 0) x
= 0;
1326 *status
= db_query(query
, &res
, startid
, count
, duration
, direction
, lastid
, uid
, gid
, x
);
1329 asl_msg_list_release(query
);
1330 if (*status
!= ASL_STATUS_INVALID_STORE
)
1334 else if (*status
!= ASL_STATUS_OK
)
1336 if (res
!= NULL
) asl_msg_list_release(res
);
1337 return KERN_SUCCESS
;
1342 out
= asl_msg_list_to_string(res
, &outlen
);
1343 asl_msg_list_release(res
);
1345 if ((out
== NULL
) || (outlen
== 0)) return KERN_SUCCESS
;
1347 kstatus
= vm_allocate(mach_task_self(), (vm_address_t
*)&vmbuffer
, outlen
, VM_FLAGS_ANYWHERE
| VM_MAKE_TAG(VM_MEMORY_ASL
));
1348 if (kstatus
!= KERN_SUCCESS
)
1354 memmove(vmbuffer
, out
, outlen
);
1360 return KERN_SUCCESS
;
1364 __asl_server_query_2
1368 mach_msg_type_number_t requestCnt
,
1373 mach_msg_type_number_t
*replyCnt
,
1379 uid_t uid
= (uid_t
)-1;
1380 gid_t gid
= (gid_t
)-1;
1381 pid_t pid
= (pid_t
)-1;
1383 int direction
= SEARCH_FORWARD
;
1384 if (flags
& QUERY_FLAG_SEARCH_REVERSE
) direction
= SEARCH_BACKWARD
;
1386 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1388 return __asl_server_query_internal(server
, request
, requestCnt
, startid
, count
, QUERY_DURATION_UNLIMITED
, direction
, reply
, replyCnt
, lastid
, status
, uid
, gid
, pid
);
1396 mach_msg_type_number_t requestCnt
,
1401 mach_msg_type_number_t
*replyCnt
,
1404 security_token_t
*token
1407 int direction
= SEARCH_FORWARD
;
1408 if (flags
& QUERY_FLAG_SEARCH_REVERSE
) direction
= SEARCH_BACKWARD
;
1410 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);
1414 __asl_server_query_timeout
1418 mach_msg_type_number_t requestCnt
,
1423 mach_msg_type_number_t
*replyCnt
,
1429 uid_t uid
= (uid_t
)-1;
1430 gid_t gid
= (gid_t
)-1;
1431 pid_t pid
= (pid_t
)-1;
1432 int direction
= SEARCH_FORWARD
;
1433 if (flags
& QUERY_FLAG_SEARCH_REVERSE
) direction
= SEARCH_BACKWARD
;
1435 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1437 return __asl_server_query_internal(server
, request
, requestCnt
, startid
, count
, QUERY_DURATION_UNLIMITED
, direction
, reply
, replyCnt
, lastid
, status
, uid
, gid
, pid
);
1445 mach_msg_type_number_t requestCnt
,
1451 mach_msg_type_number_t
*replyCnt
,
1457 uid_t uid
= (uid_t
)-1;
1458 gid_t gid
= (gid_t
)-1;
1459 pid_t pid
= (pid_t
)-1;
1461 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1463 return __asl_server_query_internal(server
, request
, requestCnt
, startid
, count
, duration
, direction
, reply
, replyCnt
, lastid
, status
, uid
, gid
, pid
);
1471 mach_msg_type_number_t requestCnt
,
1473 security_token_t
*token
1476 return KERN_SUCCESS
;
1480 * Does the actual processing for __asl_server_message.
1481 * Dispatched on asl_server_queue. This lets us avoid
1482 * calling asl_msg_from_string(), task_name_for_pid(),
1483 * and register_session() on the database_server() thread.
1486 _asl_message_processing(char *mbuf
, uint64_t msize
, uid_t uid
, gid_t gid
, pid_t pid
)
1490 kern_return_t kstatus
;
1491 mach_port_name_t client
;
1493 msg
= asl_msg_from_string(mbuf
);
1497 * process_message() will update global.memory_size with the
1498 * size of msg, and it increements the work_queue_count.
1500 OSAtomicAdd64(-1ll * msize
, &global
.memory_size
);
1501 OSAtomicDecrement32(&global
.work_queue_count
);
1503 if (msg
== NULL
) return;
1505 client
= MACH_PORT_NULL
;
1506 kstatus
= task_name_for_pid(mach_task_self(), pid
, &client
);
1507 if (kstatus
== KERN_SUCCESS
) register_session(client
, pid
);
1509 snprintf(tmp
, sizeof(tmp
), "%d", uid
);
1510 asl_msg_set_key_val(msg
, ASL_KEY_UID
, tmp
);
1512 snprintf(tmp
, sizeof(tmp
), "%d", gid
);
1513 asl_msg_set_key_val(msg
, ASL_KEY_GID
, tmp
);
1515 snprintf(tmp
, sizeof(tmp
), "%d", pid
);
1516 asl_msg_set_key_val(msg
, ASL_KEY_PID
, tmp
);
1518 process_message(msg
, SOURCE_ASL_MESSAGE
);
1522 * This MIG server routine is something of a special case in database_server() above.
1523 * It is called on the server thread that's responsible for servicing syslogd's mach port.
1524 * In this routine we copy the actual ASL message raw string out of the message into
1525 * malloc memory, deallocate the message, and dispatch the real work onto the asl_server_queue.
1528 __asl_server_message
1532 mach_msg_type_number_t messageCnt
,
1541 if (message
== NULL
) return KERN_SUCCESS
;
1543 if (message
[messageCnt
- 1] != '\0')
1545 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1546 return KERN_SUCCESS
;
1549 asldebug("__asl_server_message: %s\n", message
);
1551 if ((global
.memory_size
+ messageCnt
) > global
.memory_max
)
1554 asldebug("Server queue dropped message. message size %u queue size %lld max %lld\n", messageCnt
, global
.memory_size
, global
.memory_max
);
1555 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
);
1556 internal_log_message(str
);
1558 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1559 return KERN_SUCCESS
;
1562 mbuf
= malloc(messageCnt
);
1563 if (mbuf
!= NULL
) memcpy(mbuf
, message
, messageCnt
);
1564 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1566 if (mbuf
== NULL
) return KERN_SUCCESS
;
1571 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1573 OSAtomicIncrement32(&global
.work_queue_count
);
1574 OSAtomicAdd64(messageCnt
, &(global
.memory_size
));
1576 dispatch_async(asl_server_queue
, ^{ _asl_message_processing(mbuf
, messageCnt
, uid
, gid
, pid
); });
1578 return KERN_SUCCESS
;
1582 __asl_server_create_aux_link
1586 mach_msg_type_number_t messageCnt
,
1587 mach_port_t
*fileport
,
1589 mach_msg_type_number_t
*newurlCnt
,
1599 kern_return_t kstatus
;
1600 mach_port_name_t client
;
1601 char *url
, *vmbuffer
;
1604 *status
= ASL_STATUS_OK
;
1605 *fileport
= MACH_PORT_NULL
;
1608 if (message
== NULL
)
1610 *status
= ASL_STATUS_INVALID_ARG
;
1611 return KERN_SUCCESS
;
1614 if (message
[messageCnt
- 1] != '\0')
1616 *status
= ASL_STATUS_INVALID_ARG
;
1617 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1618 return KERN_SUCCESS
;
1621 asldebug("__asl_server_create_aux_link: %s\n", (message
== NULL
) ? "NULL" : message
);
1623 if ((global
.dbtype
& DB_TYPE_FILE
) == 0)
1625 *status
= ASL_STATUS_INVALID_STORE
;
1626 return KERN_SUCCESS
;
1629 *fileport
= MACH_PORT_NULL
;
1631 msg
= asl_msg_from_string(message
);
1632 vm_deallocate(mach_task_self(), (vm_address_t
)message
, messageCnt
);
1634 if (msg
== NULL
) return KERN_SUCCESS
;
1639 audit_token_to_au32(token
, NULL
, &uid
, &gid
, NULL
, NULL
, &pid
, NULL
, NULL
);
1641 client
= MACH_PORT_NULL
;
1642 kstatus
= task_name_for_pid(mach_task_self(), pid
, &client
);
1643 if (kstatus
== KERN_SUCCESS
) register_session(client
, pid
);
1645 snprintf(tmp
, sizeof(tmp
), "%d", uid
);
1646 asl_msg_set_key_val(msg
, ASL_KEY_UID
, tmp
);
1648 snprintf(tmp
, sizeof(tmp
), "%d", gid
);
1649 asl_msg_set_key_val(msg
, ASL_KEY_GID
, tmp
);
1651 snprintf(tmp
, sizeof(tmp
), "%d", pid
);
1652 asl_msg_set_key_val(msg
, ASL_KEY_PID
, tmp
);
1654 /* create a file for the client */
1655 *status
= asl_store_open_aux(global
.file_db
, msg
, &fd
, &url
);
1656 asl_msg_release(msg
);
1657 if (*status
!= ASL_STATUS_OK
) return KERN_SUCCESS
;
1660 if (fd
>= 0) close(fd
);
1661 *status
= ASL_STATUS_FAILED
;
1662 return KERN_SUCCESS
;
1665 if (fileport_makeport(fd
, (fileport_t
*)fileport
) < 0)
1669 *status
= ASL_STATUS_FAILED
;
1670 return KERN_SUCCESS
;
1675 *newurlCnt
= strlen(url
) + 1;
1677 kstatus
= vm_allocate(mach_task_self(), (vm_address_t
*)&vmbuffer
, *newurlCnt
, VM_FLAGS_ANYWHERE
| VM_MAKE_TAG(VM_MEMORY_ASL
));
1678 if (kstatus
!= KERN_SUCCESS
)
1684 memmove(vmbuffer
, url
, *newurlCnt
);
1689 return KERN_SUCCESS
;
1693 __asl_server_register_direct_watch
1700 uint16_t p16
= port
;
1701 pid_t pid
= (pid_t
)-1;
1703 audit_token_to_au32(token
, NULL
, NULL
, NULL
, NULL
, NULL
, &pid
, NULL
, NULL
);
1705 asldebug("__asl_server_register_direct_watch: pid %u port %hu\n", pid
, ntohs(p16
));
1707 dispatch_once(&watch_init_once
, ^{
1708 watch_queue
= dispatch_queue_create("Direct Watch Queue", NULL
);
1711 dispatch_async(watch_queue
, ^{ register_direct_watch(p16
); });
1713 return KERN_SUCCESS
;
1717 __asl_server_cancel_direct_watch
1724 uint16_t p16
= port
;
1726 asldebug("__asl_server_cancel_direct_watch: %hu\n", ntohs(p16
));
1728 dispatch_once(&watch_init_once
, ^{
1729 watch_queue
= dispatch_queue_create("Direct Watch Queue", NULL
);
1732 dispatch_async(watch_queue
, ^{ cancel_direct_watch(p16
); });
1734 return KERN_SUCCESS
;