Here we introduce a trivial tokenizer to control socket domains assignment. It might be needed to disabled some sockets (or even all of them, if you're not interested in testing sockets). For this sake -f|--fds option introduced. The option takes argument in form of --fds sockets:[(all,)|(none,)|(PF_X,^PF_X)] where PF_X is appropriate domain like PF_INET and such. The prefix ^ before name means to exclude some particular family from being tested. Also note that all|none do overwrite previous option, this is done in a sake of code simplicity. IOW, if --fds sockets:^PF_INET,all is passed, in result all socket families are allowed. Signed-off-by: Cyrill Gorcunov <gorcunov@xxxxxxxxx> --- include/net.h | 6 +++- net/protocols.c | 11 +++++++ params.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 107 insertions(+), 2 deletions(-) diff --git a/include/net.h b/include/net.h index 4e43546..c5baaf4 100644 --- a/include/net.h +++ b/include/net.h @@ -1,9 +1,12 @@ #ifndef _NET_H #define _NET_H 1 +#include <sys/types.h> +#include <sys/socket.h> #include <netinet/in.h> extern unsigned int nr_sockets; +extern char disabled_protos[PF_MAX]; void open_sockets(void); void generate_sockaddr(unsigned long *addr, unsigned long *addrlen, int pf); @@ -11,7 +14,8 @@ void generate_sockaddr(unsigned long *addr, unsigned long *addrlen, int pf); extern unsigned int specific_proto; const char * get_proto_name(unsigned int proto); void find_specific_proto(const char *protoarg); - +unsigned int find_proto_by_name(const char *name); +int disable_socket(const char *domain); /* glibc headers might be older than the kernel, so chances are we know * about more protocols than glibc does. So we define our own PF_MAX */ diff --git a/net/protocols.c b/net/protocols.c index 891acfe..6aedd29 100644 --- a/net/protocols.c +++ b/net/protocols.c @@ -58,6 +58,17 @@ static const struct protocol protocols[] = { { "PF_VSOCK", 40 }, }; +unsigned int find_proto_by_name(const char *name) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(protocols); i++) { + if (!strcmp(protocols[i].name, name)) + return protocols[i].proto; + } + return -1u; +} + const char * get_proto_name(unsigned int proto) { unsigned int i; diff --git a/params.c b/params.c index 77dc7e4..f2b31a3 100644 --- a/params.c +++ b/params.c @@ -5,6 +5,7 @@ #include <getopt.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/socket.h> #include "trinity.h" // progname #include "random.h" @@ -12,6 +13,7 @@ #include "log.h" #include "params.h" #include "tables.h" +#include "net.h" #define TAINT_NAME_LEN 32 @@ -53,6 +55,13 @@ int kernel_taint_initial = 0; int kernel_taint_mask = 0xFFFFFFFF; bool kernel_taint_param_occured = FALSE; +/* + * Some socket domains might be disabled in command line, + * track the option here, probably worth to convert to + * bitmap. + */ +char disabled_protos[PF_MAX]; + static void usage(void) { outputerr("%s\n", progname); @@ -64,6 +73,7 @@ static void usage(void) outputerr(" --kernel_taint, -T: controls which kernel taint flags should be considered, for more details refer to README file. \n"); outputerr(" --list,-L: list all syscalls known on this architecture.\n"); outputerr(" --logging,-l: (off=disable logging).\n"); + outputerr(" --fds,-f: controls which kind of sockets and files to use.\n"); outputerr(" --monochrome,-m: don't output ANSI codes\n"); outputerr(" --no_files,-n: Only pass sockets as fd's, not files\n"); outputerr(" --proto,-P: specify specific network protocol for sockets.\n"); @@ -91,6 +101,7 @@ static const struct option longopts[] = { { "list", no_argument, NULL, 'L' }, { "ioctls", no_argument, NULL, 'I' }, { "logging", required_argument, NULL, 'l' }, + { "fds", required_argument, NULL, 'f' }, { "monochrome", no_argument, NULL, 'm' }, { "no_files", no_argument, NULL, 'n' }, { "proto", required_argument, NULL, 'P' }, @@ -172,11 +183,86 @@ static void process_taint_arg(char *taintarg) { toggle_taint_flag_by_name(beg,end); } +static void parse_fds(char *arg) +{ + enum { + FDS_NONE, + FDS_SOCKET, + } context = FDS_NONE; + char *p = strdup(arg); + char *tok; + + if (!p) { + outputerr("No memory to parse %s\n", arg); + exit(EXIT_FAILURE); + } + + /* + * We're expecting here the following format, + * but our parser is a way more greedy and simplier: + * spaces, semicolons and commas are all separators. + * + * sockets:[(all,)|(none,)(PF_X,^PF_X)] + * + * note, we're context dependant -- by default all sockets + * are enabled, if you need to disable a particular socket, + * the "^PF_" prefix should be passed. But if you need only + * a few sockets to be enabled then it must be "none,PF_X,PF_X". + * + * It might be not that convenient to type but easier to parse ;-) + */ + for (tok = strtok(p, " :,"); tok; tok = strtok(NULL, " :,")) { + if (strcmp(tok, "sockets") == 0) { + context = FDS_SOCKET; + continue; + } + + switch (context) { + case FDS_SOCKET: + if (strcmp(tok, "all") == 0) { + memset(disabled_protos, 'n', sizeof(disabled_protos)); + } else if (strcmp(tok, "none") == 0) { + memset(disabled_protos, 'y', sizeof(disabled_protos)); + } else if (strncmp(tok, "PF_", 3) == 0 || + strncmp(tok, "^PF_", 4) == 0) { + int neg = tok[0] == '^'; + unsigned int proto; + + + proto = find_proto_by_name(&tok[neg]); + if (proto == -1u) + goto err; + else if (proto > ARRAY_SIZE(disabled_protos)) + BUG_ON(1); + else { + if (neg) + disabled_protos[proto] = 'y'; + else + disabled_protos[proto] = 'n'; + } + } + break; + case FDS_NONE: + default: + outputerr("Unknown context.\n"); + goto err; + } + } + + free(p); + return; + +err: + free(p); + outputerr("Unrecognizable option in \"%s\".\n", arg); + exit(EXIT_FAILURE); +} + void parse_args(int argc, char *argv[]) { int opt; - while ((opt = getopt_long(argc, argv, "a:c:C:dDg:hIl:LN:mnP:pqr:s:T:SV:vx:", longopts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "a:c:C:dDg:hIlf:LN:mnP:pqr:s:T:SV:vx:", longopts, NULL)) != -1) { switch (opt) { default: if (opt == '?') @@ -240,6 +326,10 @@ void parse_args(int argc, char *argv[]) logging = 0; break; + case 'f': + parse_fds(optarg); + break; + case 'L': show_syscall_list = TRUE; break; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe trinity" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html