diff options
author | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-29 08:22:13 -0800 |
---|---|---|
committer | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-29 08:22:13 -0800 |
commit | df5afa4fcd9725380f94ca6476248d4cc24f889a (patch) | |
tree | 65456f62397305febf7f40778c5a413a35d094ef /framework/src/audit/lib/gen_tables.c | |
parent | 76f6bf922552c00546e6e85ca471eab28f56986c (diff) |
v2.4.4 audit sources
Change-Id: I9315a7408817db51edf084fb4d27fbb492785084
Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/audit/lib/gen_tables.c')
-rw-r--r-- | framework/src/audit/lib/gen_tables.c | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/framework/src/audit/lib/gen_tables.c b/framework/src/audit/lib/gen_tables.c new file mode 100644 index 00000000..9f25b506 --- /dev/null +++ b/framework/src/audit/lib/gen_tables.c @@ -0,0 +1,418 @@ +/* gen_tables.c -- Generator of lookup tables. + * Copyright 2008 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Miloslav Trmač <mitr@redhat.com> + */ + +#include "config.h" +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <linux/net.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/personality.h> +#include <sys/mount.h> +#ifndef MS_DIRSYNC +#include <linux/fs.h> +#endif +#include "gen_tables.h" +#include "libaudit.h" +#include "interpret.h" + +/* This is from asm/ipc.h. Copying it for now as some platforms + * * have broken headers. */ +#define SEMOP 1 +#define SEMGET 2 +#define SEMCTL 3 +#define SEMTIMEDOP 4 +#define MSGSND 11 +#define MSGRCV 12 +#define MSGGET 13 +#define MSGCTL 14 +#define SHMAT 21 +#define SHMDT 22 +#define SHMGET 23 +#define SHMCTL 24 + + +/* The ratio of table size to number of non-empty elements allowed for a + "direct" s2i table; if the ratio would be bigger, bsearch tables are used + instead. + + 2 looks like a lot at a first glance, but the bsearch tables need twice as + much space per element, so with the ratio equal to 2 the direct table uses + no more memory and is faster. */ +#define DIRECT_THRESHOLD 2 + +/* Allow more than one string defined for a single integer value */ +static bool allow_duplicate_ints; /* = false; */ + +struct value { + int val; + const char *s; + size_t s_offset; + size_t orig_index; +}; + +/* The mapping to store. */ +static struct value values[] = { +#define _S(VAL, S) { (VAL), (S), 0, 0 }, +#include TABLE_H +#undef _S +}; + +#define NUM_VALUES (sizeof(values) / sizeof(*values)) + +/* Compare two "struct value" members by name. */ +static int +cmp_value_strings(const void *xa, const void *xb) +{ + const struct value *a, *b; + + a = xa; + b = xb; + return strcmp(a->s, b->s); +} + +/* Compare two "struct value" members by value. */ +static int +cmp_value_vals(const void *xa, const void *xb) +{ + const struct value *a, *b; + + a = xa; + b = xb; + if (a->val > b->val) + return 1; + if (a->val < b->val) + return -1; + /* Preserve the original order if there is an ambiguity, to always use + the first specified value. */ + if (a->orig_index > b->orig_index) + return 1; + if (a->orig_index < b->orig_index) + return -1; + return 0; +} + +/* Compare two "struct value" members by orig_index. */ +static int +cmp_value_orig_index(const void *xa, const void *xb) +{ + const struct value *a, *b; + + a = xa; + b = xb; + if (a->orig_index > b->orig_index) + return 1; + if (a->orig_index < b->orig_index) + return -1; + return 0; +} + +/* Output the string table, initialize values[*]->s_offset. */ +static void +output_strings(const char *prefix) +{ + size_t i, offset; + + offset = 0; + for (i = 0; i < NUM_VALUES; i++) { + values[i].s_offset = offset; + offset += strlen(values[i].s) + 1; + } + printf("static const char %s_strings[] = \"", prefix); + assert(NUM_VALUES > 0); + for (i = 0; i < NUM_VALUES; i++) { + const char *c; + + if (i != 0 && i % 10 == 0) + fputs("\"\n" + "\t\"", stdout); + for (c = values[i].s; *c != '\0'; c++) { + assert(*c != '"' && *c != '\\' + && isprint((unsigned char)*c)); + putc(*c, stdout); + } + if (i != NUM_VALUES - 1) + fputs("\\0", stdout); + } + fputs("\";\n", stdout); +} + +/* Output the string to integer mapping code. + Assume strings are all uppsercase or all lowercase if specified by + parameters; in that case, make the search case-insensitive. + values must be sorted by strings. */ +static void +output_s2i(const char *prefix, bool uppercase, bool lowercase) +{ + size_t i; + + for (i = 0; i < NUM_VALUES - 1; i++) { + assert(strcmp(values[i].s, values[i + 1].s) <= 0); + if (strcmp(values[i].s, values[i + 1].s) == 0) { + fprintf(stderr, "Duplicate value `%s': %d, %d\n", + values[i].s, values[i].val, values[i + 1].val); + abort(); + } + } + printf("static const unsigned %s_s2i_s[] = {", prefix); + for (i = 0; i < NUM_VALUES; i++) { + if (i % 10 == 0) + fputs("\n\t", stdout); + assert(values[i].s_offset <= UINT_MAX); + printf("%zu,", values[i].s_offset); + } + printf("\n" + "};\n" + "static const int %s_s2i_i[] = {", prefix); + for (i = 0; i < NUM_VALUES; i++) { + if (i % 10 == 0) + fputs("\n\t", stdout); + printf("%d,", values[i].val); + } + fputs("\n" + "};\n", stdout); + assert(!(uppercase && lowercase)); + if (uppercase) { + for (i = 0; i < NUM_VALUES; i++) { + const char *c; + + for (c = values[i].s; *c != '\0'; c++) + assert(isascii((unsigned char)*c) + && !GT_ISLOWER(*c)); + } + } else if (lowercase) { + for (i = 0; i < NUM_VALUES; i++) { + const char *c; + + for (c = values[i].s; *c != '\0'; c++) + assert(isascii((unsigned char)*c) + && !GT_ISUPPER(*c)); + } + } + if (uppercase || lowercase) { + printf("static int %s_s2i(const char *s, int *value) {\n" + "\tsize_t len, i;\n" + "\tlen = strlen(s);\n" + "\t{ char copy[len + 1];\n" + "\tfor (i = 0; i < len; i++) {\n" + "\t\tchar c = s[i];\n", prefix); + if (uppercase) + fputs("\t\tcopy[i] = GT_ISLOWER(c) ? c - 'a' + 'A' " + ": c;\n", stdout); + else + fputs("\t\tcopy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' " + ": c;\n", stdout); + printf("\t}\n" + "\tcopy[i] = 0;\n" + "\treturn s2i__(%s_strings, %s_s2i_s, %s_s2i_i, %zu, " + "copy, value);\n" + "\t}\n" + "}\n", prefix, prefix, prefix, NUM_VALUES); + } else + printf("static int %s_s2i(const char *s, int *value) {\n" + "\treturn s2i__(%s_strings, %s_s2i_s, %s_s2i_i, %zu, s, " + "value);\n" + "}\n", prefix, prefix, prefix, prefix, NUM_VALUES); +} + +/* Output the string to integer mapping table. + values must be sorted by strings. */ +static void +output_i2s(const char *prefix) +{ + struct value *unique_values; + int min_val, max_val; + size_t i, n; + + assert(NUM_VALUES > 0); + for (i = 0; i < NUM_VALUES - 1; i++) { + assert(values[i].val <= values[i + 1].val); + if (!allow_duplicate_ints + && values[i].val == values[i + 1].val) { + fprintf(stderr, "Duplicate value %d: `%s', `%s'\n", + values[i].val, values[i].s, values[i + 1].s); + abort(); + } + } + + unique_values = malloc(NUM_VALUES * sizeof(*unique_values)); + assert(unique_values != NULL); + n = 0; + for (i = 0; i < NUM_VALUES; i++) { + if (n == 0 || unique_values[n - 1].val != values[i].val) { + unique_values[n] = values[i]; + n++; + } + } + + min_val = unique_values[0].val; + max_val = unique_values[n - 1].val; + if (((double)max_val - (double)min_val) / n <= DIRECT_THRESHOLD) { + int next_index; + + printf("static const unsigned %s_i2s_direct[] = {", prefix); + next_index = min_val; + i = 0; + for (;;) { + if ((next_index - min_val) % 10 == 0) + fputs("\n\t", stdout); + while (unique_values[i].val < next_index) + /* This can happen if (allow_duplicate_ints) */ + i++; + if (unique_values[i].val == next_index) { + assert(unique_values[i].s_offset <= UINT_MAX); + printf("%zu,", unique_values[i].s_offset); + } else + fputs("-1u,", stdout); + if (next_index == max_val) + /* Done like this to avoid integer overflow */ + break; + next_index++; + } + printf("\n" + "};\n" + "static const char *%s_i2s(int v) {\n" + "\treturn i2s_direct__(%s_strings, %s_i2s_direct, %d, " + "%d, v);\n" + "}\n", prefix, prefix, prefix, min_val, max_val); + } else { + printf("static const int %s_i2s_i[] = {", prefix); + for (i = 0; i < n; i++) { + if (i % 10 == 0) + fputs("\n\t", stdout); + printf("%d,", unique_values[i].val); + } + printf("\n" + "};\n" + "static const unsigned %s_i2s_s[] = {", prefix); + for (i = 0; i < n; i++) { + if (i % 10 == 0) + fputs("\n\t", stdout); + assert(unique_values[i].s_offset <= UINT_MAX); + printf("%zu,", unique_values[i].s_offset); + } + printf("\n" + "};\n" + "static const char *%s_i2s(int v) {\n" + "\treturn i2s_bsearch__(%s_strings, %s_i2s_i, %s_i2s_s, " + "%zu, v);\n" + "}\n", prefix, prefix, prefix, prefix, n); + } + free(unique_values); +} + +/* Output the string to integer mapping table as a transtab[]. + values must be sorted in the desired order. */ +static void +output_i2s_transtab(const char *prefix) +{ + size_t i; + char *uc_prefix; + + printf("static const struct transtab %s_table[] = {", prefix); + for (i = 0; i < NUM_VALUES; i++) { + if (i % 10 == 0) + fputs("\n\t", stdout); + printf("{%d,%zu},", values[i].val, values[i].s_offset); + } + uc_prefix = strdup(prefix); + assert(uc_prefix != NULL); + for (i = 0; uc_prefix[i] != '\0'; i++) + uc_prefix[i] = toupper((unsigned char)uc_prefix[i]); + printf("\n" + "};\n" + "#define %s_NUM_ENTRIES " + "(sizeof(%s_table) / sizeof(*%s_table))\n", uc_prefix, prefix, + prefix); + free(uc_prefix); +} + +int +main(int argc, char **argv) +{ + bool gen_i2s, gen_i2s_transtab, gen_s2i, uppercase, lowercase; + char *prefix; + size_t i; + + /* This is required by gen_tables.h */ + assert(NUM_VALUES <= (SSIZE_MAX / 2 + 1)); + + /* To make sure GT_ISUPPER and GT_ISLOWER work. */ + assert('Z' == 'A' + 25 && 'z' == 'a' + 25); + gen_i2s = false; + gen_i2s_transtab = false; + gen_s2i = false; + uppercase = false; + lowercase = false; + prefix = NULL; + assert (argc > 1); + for (i = 1; i < (size_t)argc; i++) { + if (strcmp(argv[i], "--i2s") == 0) + gen_i2s = true; + else if (strcmp(argv[i], "--i2s-transtab") == 0) + gen_i2s_transtab = true; + else if (strcmp(argv[i], "--s2i") == 0) + gen_s2i = true; + else if (strcmp(argv[i], "--uppercase") == 0) + uppercase = true; + else if (strcmp(argv[i], "--lowercase") == 0) + lowercase = true; + else if (strcmp(argv[i], "--duplicate-ints") == 0) + allow_duplicate_ints = true; + else { + assert(*argv[i] != '-'); + assert(prefix == NULL); + prefix = argv[i]; + } + } + assert(prefix != NULL); + assert(!(uppercase && lowercase)); + + printf("/* This is a generated file, see Makefile.am for its " + "inputs. */\n"); + for (i = 0; i < NUM_VALUES; i++) + values[i].orig_index = i; + qsort(values, NUM_VALUES, sizeof(*values), cmp_value_strings); + /* FIXME? if (gen_s2i), sort the strings in some other order + (e.g. "first 4 nodes in BFS of the bsearch tree first") to use the + cache better. */ + /* FIXME? If the only thing generated is a transtab, keep the strings + in the original order to use the cache better. */ + output_strings(prefix); + if (gen_s2i) + output_s2i(prefix, uppercase, lowercase); + if (gen_i2s) { + qsort(values, NUM_VALUES, sizeof(*values), cmp_value_vals); + output_i2s(prefix); + } + if (gen_i2s_transtab) { + qsort(values, NUM_VALUES, sizeof(*values), + cmp_value_orig_index); + output_i2s_transtab(prefix); + } + return EXIT_SUCCESS; +} |