1d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes/* 2d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org> 3d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * All rights reserved. 4d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 5d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Redistribution and use in source and binary forms, with or without 6d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * modification, are permitted provided that the following conditions 7d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * are met: 8d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 1. Redistributions of source code must retain the above copyright 9d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * notice, this list of conditions and the following disclaimer. 10d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 2. Redistributions in binary form must reproduce the above copyright 11d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * notice, this list of conditions and the following disclaimer in the 12d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * documentation and/or other materials provided with the distribution. 13d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 3. The name of the author may not be used to endorse or promote products 14d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * derived from this software without specific prior written permission. 15d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * 16d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 27d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 28d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#include "defs.h" 29d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#include "nsig.h" 30d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 31d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughestypedef unsigned int number_slot_t; 32d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes#define BITS_PER_SLOT (sizeof(number_slot_t) * 8) 33d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 34d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstruct number_set { 35d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes number_slot_t *vec; 36d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int nslots; 37d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes bool not; 38d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}; 39d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 40d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstruct number_set read_set; 41d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstruct number_set write_set; 42d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstruct number_set signal_set; 43d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 44d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set abbrev_set[SUPPORTED_PERSONALITIES]; 45d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set inject_set[SUPPORTED_PERSONALITIES]; 46d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set raw_set[SUPPORTED_PERSONALITIES]; 47d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set trace_set[SUPPORTED_PERSONALITIES]; 48d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic struct number_set verbose_set[SUPPORTED_PERSONALITIES]; 49d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 50d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 51d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesnumber_setbit(const unsigned int i, number_slot_t *const vec) 52d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 53d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes vec[i / BITS_PER_SLOT] |= (number_slot_t) 1 << (i % BITS_PER_SLOT); 54d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 55d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 56d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool 57d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesnumber_isset(const unsigned int i, const number_slot_t *const vec) 58d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 59d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return vec[i / BITS_PER_SLOT] & ((number_slot_t) 1 << (i % BITS_PER_SLOT)); 60d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 61d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 62d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 63d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesreallocate_number_set(struct number_set *const set, const unsigned int new_nslots) 64d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 65d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (new_nslots <= set->nslots) 66d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return; 67d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes set->vec = xreallocarray(set->vec, new_nslots, sizeof(*set->vec)); 68d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes memset(set->vec + set->nslots, 0, 69d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes sizeof(*set->vec) * (new_nslots - set->nslots)); 70d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes set->nslots = new_nslots; 71d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 72d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 73d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 74d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesadd_number_to_set(const unsigned int number, struct number_set *const set) 75d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 76d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes reallocate_number_set(set, number / BITS_PER_SLOT + 1); 77d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes number_setbit(number, set->vec); 78d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 79d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 80d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesbool 81d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesis_number_in_set(const unsigned int number, const struct number_set *const set) 82d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 83d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return ((number / BITS_PER_SLOT < set->nslots) 84d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes && number_isset(number, set->vec)) ^ set->not; 85d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 86d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 87d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughestypedef int (*string_to_uint_func)(const char *); 88d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 89d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes/* 90d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Add numbers to SET according to STR specification. 91d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 92d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 93d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_tokens(const char *const str, struct number_set *const set, 94d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes string_to_uint_func func, const char *const name) 95d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 96d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* Clear the set. */ 97d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (set->nslots) 98d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes memset(set->vec, 0, sizeof(*set->vec) * set->nslots); 99d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes set->not = false; 100d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 101d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* 102d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Each leading ! character means inversion 103d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * of the remaining specification. 104d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 105d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *s = str; 106d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hugheshandle_inversion: 107d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes while (*s == '!') { 108d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes set->not = !set->not; 109d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes ++s; 110d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 111d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 112d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (strcmp(s, "none") == 0) { 113d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* 114d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * No numbers are added to the set. 115d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Subsequent is_number_in_set invocations will return set->not. 116d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 117d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return; 118d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } else if (strcmp(s, "all") == 0) { 119d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes s = "!none"; 120d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes goto handle_inversion; 121d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 122d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 123d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* 124d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Split the string into comma separated tokens. 125d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * For each token, find out the corresponding number 126d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * by calling FUNC, and add that number to the set. 127d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * The absence of tokens or a negative answer 128d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * from FUNC is a fatal error. 129d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 130d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *copy = xstrdup(s); 131d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *saveptr = NULL; 132d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *token; 133d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes int number = -1; 134d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 135d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (token = strtok_r(copy, ",", &saveptr); token; 136d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes token = strtok_r(NULL, ",", &saveptr)) { 137d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes number = func(token); 138d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (number < 0) { 139d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes error_msg_and_die("invalid %s '%s'", name, token); 140d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 141d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 142d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes add_number_to_set(number, set); 143d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 144d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 145d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes free(copy); 146d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 147d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (number < 0) { 148d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes error_msg_and_die("invalid %s '%s'", name, str); 149d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 150d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 151d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 152d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic int 153d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughessigstr_to_uint(const char *s) 154d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 155d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes int i; 156d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 157d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (*s >= '0' && *s <= '9') 158d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return string_to_uint_upto(s, 255); 159d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 160d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (strncasecmp(s, "SIG", 3) == 0) 161d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes s += 3; 162d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 163d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (i = 0; i <= 255; ++i) { 164d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *name = signame(i); 165d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 166d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (strncasecmp(name, "SIG", 3) != 0) 167d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes continue; 168d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 169d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes name += 3; 170d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 171d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (strcasecmp(name, s) != 0) 172d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes continue; 173d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 174d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return i; 175d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 176d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 177d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return -1; 178d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 179d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 180d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool 181d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall_number(const char *s, struct number_set *set) 182d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 183d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes int n = string_to_uint(s); 184d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (n < 0) 185d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 186d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 187d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int p; 188d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes bool done = false; 189d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 190d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) { 191d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if ((unsigned) n >= nsyscall_vec[p]) { 192d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes continue; 193d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 194d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes add_number_to_set(n, &set[p]); 195d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes done = true; 196d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 197d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 198d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return done; 199d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 200d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 201d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic unsigned int 202d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hugheslookup_class(const char *s) 203d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 204d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes static const struct { 205d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *name; 206d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int value; 207d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } syscall_class[] = { 208d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "desc", TRACE_DESC }, 209d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "file", TRACE_FILE }, 210d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "memory", TRACE_MEMORY }, 211d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "process", TRACE_PROCESS }, 212d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "signal", TRACE_SIGNAL }, 213d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "ipc", TRACE_IPC }, 214d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "network", TRACE_NETWORK }, 215d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes }; 216d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 217d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int i; 218d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (i = 0; i < ARRAY_SIZE(syscall_class); ++i) { 219d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (strcmp(s, syscall_class[i].name) == 0) { 220d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return syscall_class[i].value; 221d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 222d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 223d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 224d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return 0; 225d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 226d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 227d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool 228d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall_class(const char *s, struct number_set *set) 229d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 230d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const unsigned int n = lookup_class(s); 231d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (!n) 232d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 233d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 234d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int p; 235d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) { 236d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int i; 237d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 238d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (i = 0; i < nsyscall_vec[p]; ++i) { 239d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (!sysent_vec[p][i].sys_name 240d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes || (sysent_vec[p][i].sys_flags & n) != n) { 241d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes continue; 242d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 243d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes add_number_to_set(i, &set[p]); 244d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 245d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 246d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 247d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return true; 248d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 249d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 250d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool 251d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall_name(const char *s, struct number_set *set) 252d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 253d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int p; 254d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes bool found = false; 255d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 256d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) { 257d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int i; 258d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 259d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (i = 0; i < nsyscall_vec[p]; ++i) { 260d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (!sysent_vec[p][i].sys_name 261d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes || strcmp(s, sysent_vec[p][i].sys_name)) { 262d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes continue; 263d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 264d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes add_number_to_set(i, &set[p]); 265d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes found = true; 266d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 267d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 268d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 269d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return found; 270d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 271d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 272d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool 273d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall(const char *token, struct number_set *set) 274d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 275d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (*token >= '0' && *token <= '9') 276d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return qualify_syscall_number(token, set); 277d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return qualify_syscall_class(token, set) 278d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes || qualify_syscall_name(token, set); 279d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 280d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 281d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes/* 282d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Add syscall numbers to SETs for each supported personality 283d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * according to STR specification. 284d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 285d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 286d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_syscall_tokens(const char *const str, struct number_set *const set, 287d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *const name) 288d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 289d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* Clear all sets. */ 290d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int p; 291d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) { 292d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (set[p].nslots) 293d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes memset(set[p].vec, 0, 294d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes sizeof(*set[p].vec) * set[p].nslots); 295d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes set[p].not = false; 296d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 297d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 298d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* 299d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Each leading ! character means inversion 300d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * of the remaining specification. 301d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 302d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *s = str; 303d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hugheshandle_inversion: 304d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes while (*s == '!') { 305d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) { 306d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes set[p].not = !set[p].not; 307d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 308d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes ++s; 309d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 310d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 311d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (strcmp(s, "none") == 0) { 312d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* 313d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * No syscall numbers are added to sets. 314d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Subsequent is_number_in_set invocations 315d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * will return set[p]->not. 316d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 317d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return; 318d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } else if (strcmp(s, "all") == 0) { 319d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes s = "!none"; 320d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes goto handle_inversion; 321d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 322d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 323d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* 324d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Split the string into comma separated tokens. 325d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * For each token, call qualify_syscall that will take care 326d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * if adding appropriate syscall numbers to sets. 327d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * The absence of tokens or a negative return code 328d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * from qualify_syscall is a fatal error. 329d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 330d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *copy = xstrdup(s); 331d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *saveptr = NULL; 332d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *token; 333d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes bool done = false; 334d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 335d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (token = strtok_r(copy, ",", &saveptr); token; 336d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes token = strtok_r(NULL, ",", &saveptr)) { 337d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes done = qualify_syscall(token, set); 338d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (!done) { 339d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes error_msg_and_die("invalid %s '%s'", name, token); 340d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 341d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 342d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 343d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes free(copy); 344d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 345d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (!done) { 346d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes error_msg_and_die("invalid %s '%s'", name, str); 347d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 348d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 349d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 350d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes/* 351d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Returns NULL if STR does not start with PREFIX, 352d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * or a pointer to the first char in STR after PREFIX. 353d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 354d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic const char * 355d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstrip_prefix(const char *prefix, const char *str) 356d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 357d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes size_t len = strlen(prefix); 358d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 359d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return strncmp(prefix, str, len) ? NULL : str + len; 360d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 361d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 362d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic int 363d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesfind_errno_by_name(const char *name) 364d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 365d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int i; 366d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 367d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (i = 1; i < nerrnos; ++i) { 368d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (errnoent[i] && (strcasecmp(name, errnoent[i]) == 0)) 369d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return i; 370d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 371d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 372d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return -1; 373d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 374d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 375d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic bool 376d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesparse_inject_token(const char *const token, struct inject_opts *const fopts, 377d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const bool fault_tokens_only) 378d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 379d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *val; 380d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes int intval; 381d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 382d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if ((val = strip_prefix("when=", token))) { 383d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* 384d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * == 1+1 385d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * F == F+0 386d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * F+ == F+1 387d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * F+S 388d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 389d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *end; 390d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes intval = string_to_uint_ex(val, &end, 0xffff, "+"); 391d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (intval < 1) 392d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 393d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 394d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes fopts->first = intval; 395d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 396d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (*end) { 397d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes val = end + 1; 398d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (*val) { 399d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* F+S */ 400d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes intval = string_to_uint_upto(val, 0xffff); 401d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (intval < 1) 402d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 403d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes fopts->step = intval; 404d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } else { 405d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* F+ == F+1 */ 406d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes fopts->step = 1; 407d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 408d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } else { 409d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* F == F+0 */ 410d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes fopts->step = 0; 411d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 412d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } else if ((val = strip_prefix("error=", token))) { 413d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (fopts->rval != INJECT_OPTS_RVAL_DEFAULT) 414d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 415d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes intval = string_to_uint_upto(val, MAX_ERRNO_VALUE); 416d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (intval < 0) 417d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes intval = find_errno_by_name(val); 418d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (intval < 1) 419d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 420d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes fopts->rval = -intval; 421d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } else if (!fault_tokens_only && (val = strip_prefix("retval=", token))) { 422d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (fopts->rval != INJECT_OPTS_RVAL_DEFAULT) 423d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 424d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes intval = string_to_uint(val); 425d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (intval < 0) 426d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 427d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes fopts->rval = intval; 428d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } else if (!fault_tokens_only && (val = strip_prefix("signal=", token))) { 429d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes intval = sigstr_to_uint(val); 430d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (intval < 1 || intval > NSIG_BYTES * 8) 431d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 432d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes fopts->signo = intval; 433d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } else { 434d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return false; 435d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 436d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 437d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return true; 438d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 439d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 440d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic char * 441d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesparse_inject_expression(const char *const s, char **buf, 442d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes struct inject_opts *const fopts, 443d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const bool fault_tokens_only) 444d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 445d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *saveptr = NULL; 446d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *name = NULL; 447d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *token; 448d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 449d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes *buf = xstrdup(s); 450d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (token = strtok_r(*buf, ":", &saveptr); token; 451d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes token = strtok_r(NULL, ":", &saveptr)) { 452d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (!name) 453d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes name = token; 454d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes else if (!parse_inject_token(token, fopts, fault_tokens_only)) 455d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes goto parse_error; 456d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 457d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 458d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (name) 459d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return name; 460d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 461d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesparse_error: 462d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes free(*buf); 463d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return *buf = NULL; 464d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 465d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 466d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 467d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_read(const char *const str) 468d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 469d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_tokens(str, &read_set, string_to_uint, "descriptor"); 470d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 471d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 472d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 473d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_write(const char *const str) 474d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 475d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_tokens(str, &write_set, string_to_uint, "descriptor"); 476d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 477d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 478d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 479d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_signals(const char *const str) 480d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 481d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_tokens(str, &signal_set, sigstr_to_uint, "signal"); 482d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 483d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 484d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 485d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_trace(const char *const str) 486d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 487d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_syscall_tokens(str, trace_set, "system call"); 488d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 489d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 490d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 491d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_abbrev(const char *const str) 492d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 493d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_syscall_tokens(str, abbrev_set, "system call"); 494d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 495d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 496d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 497d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_verbose(const char *const str) 498d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 499d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_syscall_tokens(str, verbose_set, "system call"); 500d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 501d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 502d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 503d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_raw(const char *const str) 504d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 505d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_syscall_tokens(str, raw_set, "system call"); 506d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 507d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 508d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 509d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_inject_common(const char *const str, 510d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const bool fault_tokens_only, 511d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *const description) 512d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 513d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes struct inject_opts opts = { 514d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes .first = 1, 515d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes .step = 1, 516d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes .rval = INJECT_OPTS_RVAL_DEFAULT, 517d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes .signo = 0 518d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes }; 519d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *buf = NULL; 520d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes char *name = parse_inject_expression(str, &buf, &opts, fault_tokens_only); 521d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (!name) { 522d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes error_msg_and_die("invalid %s '%s'", description, str); 523d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 524d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 525d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* If neither of retval, error, or signal is specified, then ... */ 526d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (opts.rval == INJECT_OPTS_RVAL_DEFAULT && !opts.signo) { 527d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (fault_tokens_only) { 528d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* in fault= syntax the default error code is ENOSYS. */ 529d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes opts.rval = -ENOSYS; 530d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } else { 531d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* in inject= syntax this is not allowed. */ 532d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes error_msg_and_die("invalid %s '%s'", description, str); 533d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 534d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 535d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 536d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes struct number_set tmp_set[SUPPORTED_PERSONALITIES]; 537d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes memset(tmp_set, 0, sizeof(tmp_set)); 538d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_syscall_tokens(name, tmp_set, description); 539d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 540d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes free(buf); 541d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 542d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes /* 543d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Initialize inject_vec accourding to tmp_set. 544d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes * Merge tmp_set into inject_set. 545d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes */ 546d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int p; 547d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) { 548d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (!tmp_set[p].nslots && !tmp_set[p].not) { 549d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes continue; 550d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 551d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 552d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (!inject_vec[p]) { 553d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes inject_vec[p] = xcalloc(nsyscall_vec[p], 554d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes sizeof(*inject_vec[p])); 555d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 556d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 557d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int i; 558d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (i = 0; i < nsyscall_vec[p]; ++i) { 559d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (is_number_in_set(i, &tmp_set[p])) { 560d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes add_number_to_set(i, &inject_set[p]); 561d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes inject_vec[p][i] = opts; 562d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 563d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 564d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 565d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes free(tmp_set[p].vec); 566d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 567d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 568d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 569d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 570d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_fault(const char *const str) 571d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 572d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_inject_common(str, true, "fault argument"); 573d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 574d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 575d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic void 576d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify_inject(const char *const str) 577d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 578d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes qualify_inject_common(str, false, "inject argument"); 579d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 580d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 581d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesstatic const struct qual_options { 582d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *name; 583d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes void (*qualify)(const char *); 584d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} qual_options[] = { 585d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "trace", qualify_trace }, 586d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "t", qualify_trace }, 587d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "abbrev", qualify_abbrev }, 588d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "a", qualify_abbrev }, 589d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "verbose", qualify_verbose }, 590d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "v", qualify_verbose }, 591d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "raw", qualify_raw }, 592d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "x", qualify_raw }, 593d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "signal", qualify_signals }, 594d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "signals", qualify_signals }, 595d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "s", qualify_signals }, 596d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "read", qualify_read }, 597d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "reads", qualify_read }, 598d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "r", qualify_read }, 599d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "write", qualify_write }, 600d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "writes", qualify_write }, 601d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "w", qualify_write }, 602d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "fault", qualify_fault }, 603d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes { "inject", qualify_inject }, 604d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes}; 605d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 606d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesvoid 607d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqualify(const char *str) 608d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 609d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const struct qual_options *opt = qual_options; 610d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int i; 611d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 612d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes for (i = 0; i < ARRAY_SIZE(qual_options); ++i) { 613d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes const char *p = qual_options[i].name; 614d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes unsigned int len = strlen(p); 615d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 616d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes if (strncmp(str, p, len) || str[len] != '=') 617d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes continue; 618d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 619d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes opt = &qual_options[i]; 620d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes str += len + 1; 621d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes break; 622d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes } 623d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 624d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes opt->qualify(str); 625d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 626d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes 627d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesunsigned int 628d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughesqual_flags(const unsigned int scno) 629d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes{ 630d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes return (is_number_in_set(scno, &trace_set[current_personality]) 631d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes ? QUAL_TRACE : 0) 632d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes | (is_number_in_set(scno, &abbrev_set[current_personality]) 633d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes ? QUAL_ABBREV : 0) 634d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes | (is_number_in_set(scno, &verbose_set[current_personality]) 635d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes ? QUAL_VERBOSE : 0) 636d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes | (is_number_in_set(scno, &raw_set[current_personality]) 637d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes ? QUAL_RAW : 0) 638d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes | (is_number_in_set(scno, &inject_set[current_personality]) 639d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes ? QUAL_INJECT : 0); 640d35df493b4e7684c50d2d2fa032ee3a7ac228009Elliott Hughes} 641