[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux SCSI]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux