]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_asl.c
xnu-6153.41.3.tar.gz
[apple/xnu.git] / bsd / kern / kern_asl.c
1 /*
2 * Copyright (c) 2019 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <sys/errno.h>
30 #include <sys/types.h>
31 #include <sys/malloc.h>
32 #include <sys/buf.h>
33 #include <sys/time.h>
34 #include <sys/kauth.h>
35 #include <sys/mount.h>
36 #include <sys/vnode.h>
37 #include <sys/syslog.h>
38 #include <sys/vnode_internal.h>
39 #include <sys/fslog.h>
40 #include <sys/mount_internal.h>
41 #include <sys/kasl.h>
42
43 #include <dev/random/randomdev.h>
44
45 #include <uuid/uuid.h>
46
47 #include <stdarg.h>
48
49 /* String to append as format modifier for each key-value pair */
50 #define KASL_KEYVAL_FMT "[%s %s] "
51 #define KASL_KEYVAL_FMT_LEN (sizeof(KASL_KEYVAL_FMT) - 1)
52
53 #define KASL_NEWLINE_CHAR "\n"
54 #define KASL_NEWLINE_CHAR_LEN (sizeof(KASL_NEWLINE_CHAR) - 1)
55
56 /* Length of entire ASL message in 10 characters. Kernel defaults to zero */
57 #define KASL_ASL_MSG_LEN " 0"
58
59 /* Length of default format string to be used by printf */
60 #define MAX_FMT_LEN 256
61
62
63 /* Function to print input values as key-value pairs in format
64 * identifiable by Apple system log (ASL) facility. All key-value pairs
65 * are assumed to be pointer to strings and are provided using va_list
66 * argument which is a list of varying number of arguments created by the
67 * caller of this function.
68 *
69 * Parameters -
70 * level - Priority level for this ASL message
71 * facility - Facility for this ASL message.
72 * num_pairs - Number of key-value pairs provided by vargs argument.
73 * vargs - List of key-value pairs.
74 *
75 * Returns -
76 * zero - On success, when it prints all key-values pairs provided.
77 * E2BIG - When it cannot print all key-value pairs provided and had
78 * to truncate the output.
79 */
80 static int
81 kern_asl_msg_va(int level, const char *facility, int num_pairs, va_list vargs)
82 {
83 int err = 0;
84 char fmt[MAX_FMT_LEN]; /* Format string to use with vaddlog */
85 int calc_pairs = 0;
86 size_t len;
87 int i;
88
89 /* Mask extra bits, if any, from priority level */
90 level = LOG_PRI(level);
91
92 /* Create the first part of format string consisting of ASL
93 * message length, level, and facility.
94 */
95 if (facility) {
96 snprintf(fmt, MAX_FMT_LEN, "%s [%s %d] [%s %s] ",
97 KASL_ASL_MSG_LEN,
98 KASL_KEY_LEVEL, level,
99 KASL_KEY_FACILITY, facility);
100 } else {
101 snprintf(fmt, MAX_FMT_LEN, "%s [%s %d] ",
102 KASL_ASL_MSG_LEN,
103 KASL_KEY_LEVEL, level);
104 }
105
106 /* Determine the number of key-value format string [%s %s] that
107 * should be added in format string for every key-value pair provided
108 * in va_list. Calculate maximum number of format string that can be
109 * accommodated in the remaining format buffer (after saving space
110 * for newline character). If the caller provided pairs in va_list
111 * is more than calculated pairs, truncate extra pairs.
112 */
113 len = MAX_FMT_LEN - strlen(fmt) - KASL_NEWLINE_CHAR_LEN - 1;
114 calc_pairs = len / KASL_KEYVAL_FMT_LEN;
115 if (num_pairs <= calc_pairs) {
116 calc_pairs = num_pairs;
117 } else {
118 err = E2BIG;
119 }
120
121 /* Append format strings [%s %s] for the key-value pairs in vargs */
122 len = MAX_FMT_LEN - KASL_NEWLINE_CHAR_LEN;
123 for (i = 0; i < calc_pairs; i++) {
124 (void) strlcat(fmt, KASL_KEYVAL_FMT, len);
125 }
126
127 /* Append newline */
128 (void) strlcat(fmt, KASL_NEWLINE_CHAR, MAX_FMT_LEN);
129
130 /* Print the key-value pairs in ASL format */
131 vaddlog(fmt, vargs);
132
133 /*
134 * Note: can't use os_log_with_args() here because 'fmt' is
135 * constructed on the stack i.e. doesn't come from a text
136 * section. More importantly, the newer logging system
137 * doesn't grok ASL either.
138 */
139
140 return err;
141 }
142
143 int
144 kern_asl_msg(int level, const char *facility, int num_pairs, ...)
145 {
146 int err;
147 va_list ap;
148
149 va_start(ap, num_pairs);
150 err = kern_asl_msg_va(level, facility,
151 num_pairs, ap);
152 va_end(ap);
153
154 return err;
155 }
156
157 /* Search if given string contains '[' and ']'. If any, escape it by
158 * prefixing with a '\'. If the length of the string is not big enough,
159 * no changes are done and error is returned.
160 *
161 * Parameters -
162 * str - string that can contain '[' or ']', should be NULL terminated
163 * len - length, in bytes, of valid data, including NULL character.
164 * buflen - size of buffer that contains the string
165 */
166 int
167 escape_str(char *str, int len, int buflen)
168 {
169 int count;
170 char *src, *dst;
171
172 /* Count number of characters to escape */
173 src = str;
174 count = 0;
175 do {
176 if ((*src == '[') || (*src == ']')) {
177 count++;
178 }
179 } while (*src++);
180
181 if (count) {
182 /*
183 * Check if the buffer has enough space to escape all
184 * characters
185 */
186 if ((buflen - len) < count) {
187 return ENOSPC;
188 }
189
190 src = str + len;
191 dst = src + count;
192 while (count) {
193 *dst-- = *src;
194 if ((*src == '[') || (*src == ']')) {
195 /* Last char copied needs to be escaped */
196 *dst-- = '\\';
197 count--;
198 }
199 src--;
200 }
201 }
202
203 return 0;
204 }