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 <[email protected]>
---
 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to