log_event_list.c revision 9dd6510dd09f40973b8834c5cad1217ce1c3011d
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <errno.h>
18#include <inttypes.h>
19#include <stdbool.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <log/log.h>
26#include <log/logger.h>
27
28#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
29
30typedef struct {
31    uint32_t tag;
32    unsigned pos; /* Read/write position into buffer */
33    unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements   */
34    unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1];  /* pos for list counter */
35    unsigned list_nest_depth;
36    unsigned len; /* Length or raw buffer. */
37    bool overflow;
38    bool list_stop; /* next call decrement list_nest_depth and issue a stop */
39    enum {
40        kAndroidLoggerRead = 1,
41        kAndroidLoggerWrite = 2,
42    } read_write_flag;
43    uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
44} android_log_context_internal;
45
46android_log_context create_android_logger(uint32_t tag) {
47    size_t needed, i;
48    android_log_context_internal *context;
49
50    context = calloc(1, sizeof(android_log_context_internal));
51    if (!context) {
52        return NULL;
53    }
54    context->tag = tag;
55    context->read_write_flag = kAndroidLoggerWrite;
56    needed = sizeof(uint8_t) + sizeof(uint8_t);
57    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
58        context->overflow = true;
59    }
60    /* Everything is a list */
61    context->storage[context->pos + 0] = EVENT_TYPE_LIST;
62    context->list[0] = context->pos + 1;
63    context->pos += needed;
64
65    return (android_log_context)context;
66}
67
68android_log_context create_android_log_parser(const char *msg, size_t len) {
69    android_log_context_internal *context;
70    size_t i;
71
72    context = calloc(1, sizeof(android_log_context_internal));
73    if (!context) {
74        return NULL;
75    }
76    len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
77    context->len = len;
78    memcpy(context->storage, msg, len);
79    context->read_write_flag = kAndroidLoggerRead;
80
81    return (android_log_context)context;
82}
83
84int android_log_destroy(android_log_context *ctx) {
85    android_log_context_internal *context;
86
87    context = (android_log_context_internal *)*ctx;
88    if (!context) {
89        return -EBADF;
90    }
91    memset(context, 0, sizeof(*context));
92    free(context);
93    *ctx = NULL;
94    return 0;
95}
96
97int android_log_write_list_begin(android_log_context ctx) {
98    size_t needed;
99    android_log_context_internal *context;
100
101    context = (android_log_context_internal *)ctx;
102    if (!context ||
103            (kAndroidLoggerWrite != context->read_write_flag)) {
104        return -EBADF;
105    }
106    if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
107        context->overflow = true;
108        return -EOVERFLOW;
109    }
110    needed = sizeof(uint8_t) + sizeof(uint8_t);
111    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
112        context->overflow = true;
113        return -EIO;
114    }
115    context->count[context->list_nest_depth]++;
116    context->list_nest_depth++;
117    if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
118        context->overflow = true;
119        return -EOVERFLOW;
120    }
121    if (context->overflow) {
122        return -EIO;
123    }
124    context->storage[context->pos + 0] = EVENT_TYPE_LIST;
125    context->storage[context->pos + 1] = 0;
126    context->list[context->list_nest_depth] = context->pos + 1;
127    context->count[context->list_nest_depth] = 0;
128    context->pos += needed;
129    return 0;
130}
131
132static inline void copy4LE(uint8_t *buf, uint32_t val)
133{
134    buf[0] = val & 0xFF;
135    buf[1] = (val >> 8) & 0xFF;
136    buf[2] = (val >> 16) & 0xFF;
137    buf[3] = (val >> 24) & 0xFF;
138}
139
140int android_log_write_int32(android_log_context ctx, int32_t value) {
141    size_t needed;
142    android_log_context_internal *context;
143
144    context = (android_log_context_internal *)ctx;
145    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
146        return -EBADF;
147    }
148    if (context->overflow) {
149        return -EIO;
150    }
151    needed = sizeof(uint8_t) + sizeof(value);
152    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
153        context->overflow = true;
154        return -EIO;
155    }
156    context->count[context->list_nest_depth]++;
157    context->storage[context->pos + 0] = EVENT_TYPE_INT;
158    copy4LE(&context->storage[context->pos + 1], value);
159    context->pos += needed;
160    return 0;
161}
162
163static inline void copy8LE(uint8_t *buf, uint64_t val)
164{
165    buf[0] = val & 0xFF;
166    buf[1] = (val >> 8) & 0xFF;
167    buf[2] = (val >> 16) & 0xFF;
168    buf[3] = (val >> 24) & 0xFF;
169    buf[4] = (val >> 32) & 0xFF;
170    buf[5] = (val >> 40) & 0xFF;
171    buf[6] = (val >> 48) & 0xFF;
172    buf[7] = (val >> 56) & 0xFF;
173}
174
175int android_log_write_int64(android_log_context ctx, int64_t value) {
176    size_t needed;
177    android_log_context_internal *context;
178
179    context = (android_log_context_internal *)ctx;
180    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
181        return -EBADF;
182    }
183    if (context->overflow) {
184        return -EIO;
185    }
186    needed = sizeof(uint8_t) + sizeof(value);
187    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
188        context->overflow = true;
189        return -EIO;
190    }
191    context->count[context->list_nest_depth]++;
192    context->storage[context->pos + 0] = EVENT_TYPE_LONG;
193    copy8LE(&context->storage[context->pos + 1], value);
194    context->pos += needed;
195    return 0;
196}
197
198int android_log_write_string8(android_log_context ctx, const char *value) {
199    size_t needed;
200    int32_t len;
201    android_log_context_internal *context;
202
203    context = (android_log_context_internal *)ctx;
204    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
205        return -EBADF;
206    }
207    if (context->overflow) {
208        return -EIO;
209    }
210    if (!value) {
211        return -EINVAL;
212    }
213    len = strlen(value);
214    needed = sizeof(uint8_t) + sizeof(len) + len;
215    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
216        /* Truncate string for delivery */
217        len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(len);
218        if (len <= 0) {
219            context->overflow = true;
220            return -EIO;
221        }
222    }
223    context->count[context->list_nest_depth]++;
224    context->storage[context->pos + 0] = EVENT_TYPE_STRING;
225    copy4LE(&context->storage[context->pos + 1], len);
226    memcpy(&context->storage[context->pos + 5], value, len);
227    context->pos += needed;
228    return 0;
229}
230
231int android_log_write_float32(android_log_context ctx, float value) {
232    size_t needed;
233    uint32_t ivalue;
234    android_log_context_internal *context;
235
236    context = (android_log_context_internal *)ctx;
237    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
238        return -EBADF;
239    }
240    if (context->overflow) {
241        return -EIO;
242    }
243    needed = sizeof(uint8_t) + sizeof(ivalue);
244    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
245        context->overflow = true;
246        return -EIO;
247    }
248    ivalue = *(uint32_t *)&value;
249    context->count[context->list_nest_depth]++;
250    context->storage[context->pos + 0] = EVENT_TYPE_FLOAT;
251    copy4LE(&context->storage[context->pos + 1], ivalue);
252    context->pos += needed;
253    return 0;
254}
255
256int android_log_write_list_end(android_log_context ctx) {
257    android_log_context_internal *context;
258
259    context = (android_log_context_internal *)ctx;
260    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
261        return -EBADF;
262    }
263    if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) {
264        context->overflow = true;
265        context->list_nest_depth--;
266        return -EOVERFLOW;
267    }
268    if (!context->list_nest_depth) {
269        context->overflow = true;
270        return -EOVERFLOW;
271    }
272    if (context->list[context->list_nest_depth] <= 0) {
273        context->list_nest_depth--;
274        context->overflow = true;
275        return -EOVERFLOW;
276    }
277    context->storage[context->list[context->list_nest_depth]] =
278        context->count[context->list_nest_depth];
279    context->list_nest_depth--;
280    return 0;
281}
282
283/*
284 * Logs the list of elements to the event log.
285 */
286int android_log_write_list(android_log_context ctx, log_id_t id) {
287    android_log_context_internal *context;
288    const char *msg;
289    ssize_t len;
290
291    if ((id != LOG_ID_EVENTS) && (id != LOG_ID_SECURITY)) {
292        return -EINVAL;
293    }
294
295    context = (android_log_context_internal *)ctx;
296    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
297        return -EBADF;
298    }
299    if (context->list_nest_depth) {
300        return -EIO;
301    }
302    /* NB: if there was overflow, then log is truncated. Nothing reported */
303    context->storage[1] = context->count[0];
304    len = context->len = context->pos;
305    msg = (const char *)context->storage;
306    /* it'snot a list */
307    if (context->count[0] <= 1) {
308        len -= sizeof(uint8_t) + sizeof(uint8_t);
309        if (len < 0) {
310            len = 0;
311        }
312        msg += sizeof(uint8_t) + sizeof(uint8_t);
313    }
314    return (id == LOG_ID_EVENTS) ?
315        __android_log_bwrite(context->tag, msg, len) :
316        __android_log_security_bwrite(context->tag, msg, len);
317}
318
319/*
320 * Extract a 4-byte value from a byte stream.
321 */
322static inline uint32_t get4LE(const uint8_t* src)
323{
324    return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
325}
326
327/*
328 * Extract an 8-byte value from a byte stream.
329 */
330static inline uint64_t get8LE(const uint8_t* src)
331{
332    uint32_t low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
333    uint32_t high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
334    return ((uint64_t) high << 32) | (uint64_t) low;
335}
336
337/*
338 * Gets the next element. Parsing errors result in an EVENT_TYPE_UNKNOWN type.
339 * If there is nothing to process, the complete field is set to non-zero. If
340 * an EVENT_TYPE_UNKNOWN type is returned once, and the caller does not check
341 * this and continues to call this function, the behavior is undefined
342 * (although it won't crash).
343 */
344static android_log_list_element android_log_read_next_internal(
345        android_log_context ctx, int peek) {
346    android_log_list_element elem;
347    unsigned pos;
348    android_log_context_internal *context;
349
350    context = (android_log_context_internal *)ctx;
351
352    memset(&elem, 0, sizeof(elem));
353
354    /* Nothing to parse from this context, so return complete. */
355    if (!context || (kAndroidLoggerRead != context->read_write_flag) ||
356            (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) ||
357            (context->count[context->list_nest_depth] >=
358                (MAX_EVENT_PAYLOAD / (sizeof(uint8_t) + sizeof(uint8_t))))) {
359        elem.type = EVENT_TYPE_UNKNOWN;
360        if (context &&
361                (context->list_stop ||
362                ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) &&
363                    !context->count[context->list_nest_depth]))) {
364            elem.type = EVENT_TYPE_LIST_STOP;
365        }
366        elem.complete = true;
367        return elem;
368    }
369
370    /*
371     * Use a different variable to update the position in case this
372     * operation is a "peek".
373     */
374    pos = context->pos;
375    if (context->list_stop) {
376        elem.type = EVENT_TYPE_LIST_STOP;
377        elem.complete = !context->count[0] && (!context->list_nest_depth ||
378            ((context->list_nest_depth == 1) && !context->count[1]));
379        if (!peek) {
380            /* Suck in superfluous stop */
381            if (context->storage[pos] == EVENT_TYPE_LIST_STOP) {
382                context->pos = pos + 1;
383            }
384            if (context->list_nest_depth) {
385                --context->list_nest_depth;
386                if (context->count[context->list_nest_depth]) {
387                    context->list_stop = false;
388                }
389            } else {
390                context->list_stop = false;
391            }
392        }
393        return elem;
394    }
395    if ((pos + 1) > context->len) {
396        elem.type = EVENT_TYPE_UNKNOWN;
397        elem.complete = true;
398        return elem;
399    }
400
401    elem.type = context->storage[pos++];
402    switch ((int)elem.type) {
403    case EVENT_TYPE_FLOAT:
404        /* Rely on union to translate elem.data.int32 into elem.data.float32 */
405        /* FALLTHRU */
406    case EVENT_TYPE_INT:
407        elem.len = sizeof(int32_t);
408        if ((pos + elem.len) > context->len) {
409            elem.type = EVENT_TYPE_UNKNOWN;
410            return elem;
411        }
412        elem.data.int32 = get4LE(&context->storage[pos]);
413        /* common tangeable object suffix */
414        pos += elem.len;
415        elem.complete = !context->list_nest_depth && !context->count[0];
416        if (!peek) {
417            if (!context->count[context->list_nest_depth] ||
418                    !--(context->count[context->list_nest_depth])) {
419                context->list_stop = true;
420            }
421            context->pos = pos;
422        }
423        return elem;
424
425    case EVENT_TYPE_LONG:
426        elem.len = sizeof(int64_t);
427        if ((pos + elem.len) > context->len) {
428            elem.type = EVENT_TYPE_UNKNOWN;
429            return elem;
430        }
431        elem.data.int64 = get8LE(&context->storage[pos]);
432        /* common tangeable object suffix */
433        pos += elem.len;
434        elem.complete = !context->list_nest_depth && !context->count[0];
435        if (!peek) {
436            if (!context->count[context->list_nest_depth] ||
437                    !--(context->count[context->list_nest_depth])) {
438                context->list_stop = true;
439            }
440            context->pos = pos;
441        }
442        return elem;
443
444    case EVENT_TYPE_STRING:
445        if ((pos + sizeof(int32_t)) > context->len) {
446            elem.type = EVENT_TYPE_UNKNOWN;
447            elem.complete = true;
448            return elem;
449        }
450        elem.len = get4LE(&context->storage[pos]);
451        pos += sizeof(int32_t);
452        if ((pos + elem.len) > context->len) {
453            elem.len = context->len - pos; /* truncate string */
454            elem.complete = true;
455            if (!elem.len) {
456                elem.type = EVENT_TYPE_UNKNOWN;
457                return elem;
458            }
459        }
460        elem.data.string = (char *)&context->storage[pos];
461        /* common tangeable object suffix */
462        pos += elem.len;
463        elem.complete = !context->list_nest_depth && !context->count[0];
464        if (!peek) {
465            if (!context->count[context->list_nest_depth] ||
466                    !--(context->count[context->list_nest_depth])) {
467                context->list_stop = true;
468            }
469            context->pos = pos;
470        }
471        return elem;
472
473    case EVENT_TYPE_LIST:
474        if ((pos + sizeof(uint8_t)) > context->len) {
475            elem.type = EVENT_TYPE_UNKNOWN;
476            elem.complete = true;
477            return elem;
478        }
479        elem.complete = context->list_nest_depth >= ANDROID_MAX_LIST_NEST_DEPTH;
480        if (peek) {
481            return elem;
482        }
483        if (context->count[context->list_nest_depth]) {
484            context->count[context->list_nest_depth]--;
485        }
486        context->list_stop = !context->storage[pos];
487        context->list_nest_depth++;
488        if (context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) {
489            context->count[context->list_nest_depth] = context->storage[pos];
490        }
491        context->pos = pos + sizeof(uint8_t);
492        return elem;
493
494    case EVENT_TYPE_LIST_STOP: /* Suprise Newline terminates lists. */
495        if (!peek) {
496            context->pos = pos;
497        }
498        elem.type = EVENT_TYPE_UNKNOWN;
499        elem.complete = !context->list_nest_depth;
500        if (context->list_nest_depth > 0) {
501            elem.type = EVENT_TYPE_LIST_STOP;
502            if (!peek) {
503                context->list_nest_depth--;
504            }
505        }
506        return elem;
507
508    default:
509        elem.type = EVENT_TYPE_UNKNOWN;
510        return elem;
511    }
512}
513
514android_log_list_element android_log_read_next(android_log_context ctx) {
515    return android_log_read_next_internal(ctx, 0);
516}
517
518android_log_list_element android_log_peek_next(android_log_context ctx) {
519    return android_log_read_next_internal(ctx, 1);
520}
521