[PATCH 2/5] Implement parsing of inject and fault filter actions

Nikolay Marchuk marchuk.nikolay.a at gmail.com
Mon Jun 26 07:45:37 UTC 2017


* basic_actions.c (parse_inject, parse_fault, apply_fault): Implement.
(apply_inject): Change inject private data.
* defs.h (inject_vec): Remove.
(inject_opts): Add init flag.
* filter.h (parse_inject_token): Add definition.
* filter_action.c: Add fault action.
* filter_qualify.c (parse_inject_common): Generate new inject private data.
---
 basic_actions.c  | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 defs.h           |  2 +-
 filter.h         |  2 ++
 filter_action.c  |  3 ++
 filter_qualify.c | 44 ++++++++++----------------
 5 files changed, 109 insertions(+), 37 deletions(-)

diff --git a/basic_actions.c b/basic_actions.c
index de87cde..1eb597e 100644
--- a/basic_actions.c
+++ b/basic_actions.c
@@ -25,6 +25,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "defs.h"
+#include "filter.h"
 
 bool
 is_traced(struct tcb *tcp)
@@ -49,50 +50,126 @@ apply_trace(struct tcb *tcp, void *_priv_data)
 {
 	tcp->qual_flg |= QUAL_TRACE;
 }
+
+struct inject_priv_data {
+	struct inject_opts opts;
+	struct inject_opts **inject_vec;
+};
+
 void
 apply_inject(struct tcb *tcp, void *_priv_data)
 {
-	struct inject_opts **inject_vec = (struct inject_opts **)_priv_data;
+	struct inject_priv_data *data = (struct inject_priv_data *)_priv_data;
+	struct inject_opts *opts;
+	if (!(scno_in_range(tcp->scno) && data->inject_vec[current_personality]))
+		return;
+	opts = &data->inject_vec[current_personality][tcp->scno];
+	if (!opts->init) {
+		data->inject_vec[current_personality][tcp->scno] = data->opts;
+		opts = &data->inject_vec[current_personality][tcp->scno];
+		opts->init = true;
+	}
 	tcp->qual_flg |= QUAL_INJECT;
-	tcp->inject_opts = (scno_in_range(tcp->scno) && inject_vec[current_personality])
-	       ? &inject_vec[current_personality][tcp->scno] : NULL;
+	tcp->inject_opts = opts;
 }
-void*
+
+static void *
+parse_inject_common_args(const char *const str,
+                         const bool fault_tokens_only,
+                         const char *const description)
+{
+	struct inject_priv_data *data = xmalloc(sizeof(struct inject_priv_data));
+	data->inject_vec = xcalloc(SUPPORTED_PERSONALITIES,
+	                           sizeof(struct inject_opts *));
+	unsigned int p;
+	for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
+		data->inject_vec[p] = xcalloc(nsyscall_vec[p],
+		                              sizeof(struct inject_opts));
+	}
+	data->opts.first = 1;
+	data->opts.step = 1;
+	data->opts.rval = INJECT_OPTS_RVAL_DEFAULT;
+	data->opts.signo = 0;
+	char *buf = xstrdup(str);
+	char *saveptr = NULL;
+	char *token;
+	for (token = strtok_r(buf, ";", &saveptr); token;
+	     token = strtok_r(NULL, ";", &saveptr)) {
+		if (!parse_inject_token(token, &data->opts, fault_tokens_only))
+			error_msg_and_die("invalid %s argument '%s'",
+			                  description, token);
+	}
+	free(buf);
+	if (data->opts.rval == INJECT_OPTS_RVAL_DEFAULT && !data->opts.signo) {
+		if (fault_tokens_only) {
+			data->opts.rval = -ENOSYS;
+		} else {
+			error_msg_and_die("invalid %s arguments '%s'",
+			                  description, str);
+		}
+	}
+	return data;
+}
+
+void *
 parse_inject(const char *str)
 {
-	return NULL;
+	return parse_inject_common_args(str, false, "inject");
 }
+
 void free_inject(void *_priv_data)
 {
-	struct inject_opts **vec = (struct inject_opts **)_priv_data;
+	struct inject_priv_data *data = (struct inject_priv_data *)_priv_data;
 	unsigned int p;
 	for (p = 0; p < SUPPORTED_PERSONALITIES; ++p)
-		if (vec[p])
-			free(vec[p]);
-	free(vec);
+		if (data->inject_vec[p])
+			free(data->inject_vec[p]);
+	free(data->inject_vec);
+	free(data);
 }
+
 void
 apply_read(struct tcb *tcp, void *_priv_data)
 {
 	tcp->qual_flg |= QUAL_READ;
 }
+
 void
 apply_write(struct tcb *tcp, void *_priv_data)
 {
 	tcp->qual_flg |= QUAL_WRITE;
 }
+
 void
 apply_raw(struct tcb *tcp, void *_priv_data)
 {
 	tcp->qual_flg |= QUAL_RAW;
 }
+
 void
 apply_abbrev(struct tcb *tcp, void *_priv_data)
 {
 	tcp->qual_flg |= QUAL_ABBREV;
 }
+
 void
 apply_verbose(struct tcb *tcp, void *_priv_data)
 {
 	tcp->qual_flg |= QUAL_VERBOSE;
 }
+
+void *
+parse_fault(const char *str)
+{
+	return parse_inject_common_args(str, true, "fault");
+}
+
+void
+apply_fault(struct tcb *tcp, void *_priv_data)
+{
+	apply_inject(tcp, _priv_data);
+}
+
+void free_fault(void *_priv_data) {
+	free_inject(_priv_data);
+}
diff --git a/defs.h b/defs.h
index ae75444..b69e5c9 100644
--- a/defs.h
+++ b/defs.h
@@ -203,6 +203,7 @@ struct inject_opts {
 	uint16_t step;
 	uint16_t signo;
 	int rval;
+	bool init;
 };
 
 #define MAX_ERRNO_VALUE			4095
@@ -945,7 +946,6 @@ extern unsigned nioctlents;
 
 extern const unsigned int nsyscall_vec[SUPPORTED_PERSONALITIES];
 extern const struct_sysent *const sysent_vec[SUPPORTED_PERSONALITIES];
-extern struct inject_opts *inject_vec[SUPPORTED_PERSONALITIES];
 
 #ifdef IN_MPERS_BOOTSTRAP
 /* Transform multi-line MPERS_PRINTER_DECL statements to one-liners.  */
diff --git a/filter.h b/filter.h
index ed435c8..7e03d75 100644
--- a/filter.h
+++ b/filter.h
@@ -41,6 +41,8 @@ extern bool is_traced(struct tcb *);
 typedef int (*string_to_uint_func)(const char *);
 void parse_set(const char *const, struct number_set *const,
                string_to_uint_func, const char *const);
+bool parse_inject_token(const char *const, struct inject_opts *const,
+                        const bool);
 
 struct filter* add_filter_to_array(struct filter **, unsigned int *nfilters,
                                    const char *name);
diff --git a/filter_action.c b/filter_action.c
index f71f140..fd3fa92 100644
--- a/filter_action.c
+++ b/filter_action.c
@@ -34,6 +34,7 @@ apply_ ## name(struct tcb *, void *)
 
 DECL_FILTER_ACTION(trace);
 DECL_FILTER_ACTION(inject);
+DECL_FILTER_ACTION(fault);
 DECL_FILTER_ACTION(read);
 DECL_FILTER_ACTION(write);
 DECL_FILTER_ACTION(raw);
@@ -50,6 +51,7 @@ free_ ## name(void *)
 
 DECL_FILTER_ACTION_PARSER(null);
 DECL_FILTER_ACTION_PARSER(inject);
+DECL_FILTER_ACTION_PARSER(fault);
 
 #undef DECL_FILTER_ACTION_PARSER
 
@@ -68,6 +70,7 @@ static const struct filter_action_type {
 } action_types[] = {
 	FILTER_ACTION_TYPE(trace,	2,	null,	NULL),
 	FILTER_ACTION_TYPE(inject,	2,	inject,	NULL),
+	FILTER_ACTION_TYPE(fault,	2,	fault,	NULL),
 	FILTER_ACTION_TYPE(read,	1,	null,	is_traced),
 	FILTER_ACTION_TYPE(write,	1,	null,	is_traced),
 	FILTER_ACTION_TYPE(raw,		1,	null,	is_traced),
diff --git a/filter_qualify.c b/filter_qualify.c
index ddc4a8c..99c71f4 100644
--- a/filter_qualify.c
+++ b/filter_qualify.c
@@ -79,7 +79,7 @@ sigstr_to_uint(const char *s)
 	return -1;
 }
 
-static bool
+bool
 parse_inject_token(const char *const token, struct inject_opts *const fopts,
 		   const bool fault_tokens_only)
 {
@@ -232,6 +232,11 @@ parse_raw(const char *const str)
 	set_qualify_mode(action);
 }
 
+struct inject_priv_data {
+	struct inject_opts opts;
+	struct inject_opts **inject_vec;
+};
+
 static void
 parse_inject_common(const char *const str,
 		      const bool fault_tokens_only,
@@ -241,7 +246,8 @@ parse_inject_common(const char *const str,
 		.first = 1,
 		.step = 1,
 		.rval = INJECT_OPTS_RVAL_DEFAULT,
-		.signo = 0
+		.signo = 0,
+		.init = true
 	};
 	char *buf = NULL;
 	char *name = parse_inject_expression(str, &buf, &opts, fault_tokens_only);
@@ -264,35 +270,19 @@ parse_inject_common(const char *const str,
 	struct filter *filter = create_filter(action, "syscall");
 	parse_filter(filter, name, description);
 	set_qualify_mode(action);
-
 	free(buf);
-	const struct number_set *tmp_set = (const struct number_set *)
-	                                    get_filter_priv_data(filter);
-	struct inject_opts **inject_vec = xcalloc(SUPPORTED_PERSONALITIES,
-	                                          sizeof(struct inject_opts *));
-	/*
-	 * Initialize inject_vec accourding to tmp_set.
-	 */
+
+	struct inject_priv_data *data = xmalloc(sizeof(struct inject_priv_data));
+	data->opts = opts;
+	data->inject_vec = xcalloc(SUPPORTED_PERSONALITIES,
+	                           sizeof(struct inject_opts *));
 
 	unsigned int p;
 	for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
-		if (is_empty(&tmp_set[p])) {
-			continue;
-		}
-
-		if (!inject_vec[p]) {
-			inject_vec[p] = xcalloc(nsyscall_vec[p],
-					       sizeof(*inject_vec[p]));
-		}
-
-		unsigned int i;
-		for (i = 0; i < nsyscall_vec[p]; ++i) {
-			if (is_number_in_set(i, &tmp_set[p])) {
-				inject_vec[p][i] = opts;
-			}
-		}
+		data->inject_vec[p] = xcalloc(nsyscall_vec[p],
+		                              sizeof(struct inject_opts));
 	}
-	set_filter_action_priv_data(action, inject_vec);
+	set_filter_action_priv_data(action, data);
 }
 
 static void
-- 
2.1.4





More information about the Strace-devel mailing list