lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20150105132052.23808449@gandalf.local.home>
Date:	Mon, 5 Jan 2015 13:20:52 -0500
From:	Steven Rostedt <rostedt@...dmis.org>
To:	Pauli Nieminen <suokkos@...il.com>
Cc:	linux-kernel@...r.kernel.org
Subject: Re: [RFC] trace-cmd: Add decoder plugin for raw syscalls

On Sat, 28 Sep 2013 15:47:10 +0300
Pauli Nieminen <suokkos@...il.com> wrote:

> Some kernel packagers like to disable syscalls ftrace events claiming it
> would be runtime overhead. But those kernels still can have raw_syscalls
> events enabled. To be able to use stock kernels for tracing system
> behavior I decided to write simple translation plugin for trace-cmd.
> 
> Translation tables are automatically generated from asm/unistd*.h files
> during compilation. Those translation tables are then used to find
> possible matches from all supported syscall ids for the running system.
> 
> Possible improvements to build on top of this:
> * Is it possible to figure out the architecture for sure from trace data?
> * UI communication to allow user to select process architecture
> * Heuristics to guess the process architecture from syscall patterns
> 
> Is this idea worth of cleaning to be good enough to apply?
> Is auto generated or manual syscall tables better idea?
> 

Sorry for the very late reply, but do you have any plans on extending
this? This looks very useful.

This got lost in my INBOX, and I just recently discovered it.

-- Steve


> Signed-off-by: Pauli Nieminen <suokkos@...il.com>
> ---
>  .gitignore            |   1 +
>  Makefile              |  40 +++++++++++++++--
>  plugin_raw_syscalls.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  plugin_raw_syscalls.h |  12 +++++
>  unistd.c.in           |   7 +++
>  5 files changed, 178 insertions(+), 3 deletions(-)
>  create mode 100644 plugin_raw_syscalls.c
>  create mode 100644 plugin_raw_syscalls.h
>  create mode 100644 unistd.c.in
> 
> diff --git a/.gitignore b/.gitignore
> index b7b405f..870c4f3 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -20,3 +20,4 @@ TAGS
>  cscope*
>  trace_plugin_dir
>  trace_python_dir
> +plugin_raw_syscall_unistd*.c
> diff --git a/Makefile b/Makefile
> index 1964949..b2584e4 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -248,6 +248,7 @@ ifeq ($(VERBOSE),1)
>    print_plugin_obj_compile =
>    print_plugin_build =
>    print_install =
> +  print_unistd_source_gen =
>  else
>    Q = @
>    print_compile =		echo '  $(GUI)COMPILE            '$(GOBJ);
> @@ -258,6 +259,7 @@ else
>    print_plugin_build =		echo '  $(GUI)BUILD PLUGIN       '$(GOBJ);
>    print_static_lib_build =	echo '  $(GUI)BUILD STATIC LIB   '$(GOBJ);
>    print_install =		echo '  $(GUI)INSTALL     '$(GSPACE)$1'	to	$(DESTDIR_SQ)$2';
> +  print_unistd_source_gen =	echo '  $(GUI)GEN                '$(GOBJ);
>  endif
>  
>  do_fpic_compile =					\
> @@ -276,9 +278,30 @@ do_compile_plugin_obj =				\
>  	($(print_plugin_obj_compile)		\
>  	$(CC) -c $(CFLAGS) -fPIC -o $@ $<)
>  
> +do_gen_unistd_source =								\
> +	($(print_unistd_source_gen)						\
> +	ARCH_UNISTD=$<;								\
> +	ARCH=`echo $$ARCH_UNISTD | sed 's/^.*d_\(.*\).h$$/\1/'` || exit $$?;	\
> +	ARCH_UNISTD_INCL=`echo $$ARCH_UNISTD | sed 's/^.*asm/asm/'`;		\
> +	PREFIX=raw_syscalls_$$ARCH; 						\
> +	echo "const char $${PREFIX}_arch[] = \"$$ARCH\";" > $@;			\
> +	echo "/* $(UNISTD_H_PATH) defines */" >> $@;				\
> +	grep "\#\s*define\s\+[A-Za-z_0-9]\+\s\+[A-Za-z_0-9(]\+" $(UNISTD_H_PATH) >> $@; \
> +										\
> +	echo "/* $(ARCH_UNISTD) defines */" >> $@;				\
> +	echo "\#include <$$ARCH_UNISTD_INCL>" >> $@;				\
> +										\
> +	echo "/* syscall table */" >> $@;					\
> +	echo "\#include \"plugin_raw_syscalls.h\"" >> $@;				\
> +	echo "static const struct raw_syscalls_entry $${PREFIX}_syscalls[] = {" >> $@; \
> +	sed -n "s/^.*\#\s*define\s\+__NR_\([A-Za-z_0-9]\+\)\s\+\(.*\)\s*$$/{\"\1\", \2},/p" < $$ARCH_UNISTD >> $@; \
> +	echo "};" >> $@;							\
> +										\
> +	sed "s/PREFIX/$$PREFIX/g" < $(UNISTD_TEMPLATE) >> $@)
> +
>  do_plugin_build =				\
>  	($(print_plugin_build)			\
> -	$(CC) $(CFLAGS) $(LDFLAGS) -shared -nostartfiles -o $@ $<)
> +	$(CC) $(CFLAGS) $(LDFLAGS) -shared -nostartfiles -o $@ $^)
>  
>  do_build_static_lib =				\
>  	($(print_static_lib_build)		\
> @@ -318,7 +341,7 @@ TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \
>  
>  PLUGIN_OBJS = plugin_hrtimer.o plugin_kmem.o plugin_sched_switch.o \
>  	plugin_mac80211.o plugin_jbd2.o plugin_function.o plugin_kvm.o \
> -	plugin_blk.o
> +	plugin_blk.o plugin_raw_syscalls.o
>  
>  PLUGINS := $(PLUGIN_OBJS:.o=.so)
>  
> @@ -332,6 +355,11 @@ GUI_TARGETS = ks_version.h trace-graph trace-view kernelshark
>  
>  TARGETS = $(CMD_TARGETS) $(GUI_TARGETS)
>  
> +ARCH_INCL_PATH ?= /usr/include/$(shell $(CC) $(CFLAGS) -print-multiarch)/asm
> +UNISTD_H_PATH ?= $(ARCH_INCL_PATH)/unistd.h
> +UNISTD_ARCH_HEADERS = $(notdir $(shell sed -n 's/^\s*\#\s*include\s\+<\(.*\)>\s*$$/\1/p' $(UNISTD_H_PATH)))
> +UNISTD_OBJS = $(patsubst %.h,plugin_raw_syscalls_%.o, $(UNISTD_ARCH_HEADERS))
> +UNISTD_TEMPLATE = unistd.c.in
>  
>  #	cpp $(INCLUDES)
>  
> @@ -388,12 +416,17 @@ libtracecmd.a: $(TCMD_LIB_OBJS)
>  
>  trace-util.o: trace_plugin_dir
>  
> -$(PLUGIN_OBJS): %.o : $(src)/%.c
> +$(PLUGIN_OBJS) $(UNISTD_OBJS): %.o : $(src)/%.c
>  	$(Q)$(do_compile_plugin_obj)
>  
> +$(CURDIR)/plugin_raw_syscalls_%.c: $(ARCH_INCL_PATH)/%.h Makefile
> +	$(Q)$(do_gen_unistd_source)
> +
>  $(PLUGINS): %.so: %.o
>  	$(Q)$(do_plugin_build)
>  
> +plugin_raw_syscalls.so: $(UNISTD_OBJS)
> +
>  define make_version.h
>  	(echo '/* This file is automatically generated. Do not modify. */';		\
>  	echo \#define VERSION_CODE $(shell						\
> @@ -546,6 +579,7 @@ install_doc:
>  clean:
>  	$(RM) *.o *~ $(TARGETS) *.a *.so ctracecmd_wrap.c .*.d
>  	$(RM) tags TAGS cscope*
> +	$(RM) plugin_raw_syscalls_unistd*.c
>  
>  
>  ##### PYTHON STUFF #####
> diff --git a/plugin_raw_syscalls.c b/plugin_raw_syscalls.c
> new file mode 100644
> index 0000000..e6270c0
> --- /dev/null
> +++ b/plugin_raw_syscalls.c
> @@ -0,0 +1,121 @@
> +/*
> + * Copyright (C) 2013 Pauli Nieminen <suokkos@...il.com
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation;
> + * version 2.1 of the License (not later!)
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this program; if not,  see <http://www.gnu.org/licenses>
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + */
> +
> +#include <limits.h>
> +#include <search.h>
> +
> +#include "trace-cmd.h"
> +#include "plugin_raw_syscalls.h"
> +
> +static struct raw_syscalls_tables {
> +	const char *name;
> +	size_t nr_calls;
> +	const struct raw_syscalls_entry *table;
> +	int in_order;
> +	struct raw_syscalls_tables *next;
> +} *raw_syscalls_tables = NULL;
> +
> +static int syscalls_cmp(const void *va, const void *vb)
> +{
> +	const struct raw_syscalls_entry *a = va, *b = vb;
> +	return (int)(a->id - b->id);
> +}
> +
> +static int raw_syscalls_handler(struct trace_seq *s, struct pevent_record *record,
> +				struct event_format *event, void *context)
> +{
> +	unsigned long long val;
> +	long id;
> +	struct raw_syscalls_tables *table = raw_syscalls_tables;
> +
> +	if (pevent_get_field_val(s, event, "id", record, &val, 1))
> +		return trace_seq_putc(s, '!');
> +
> +	id = val;
> +
> +	while (table) {
> +		struct raw_syscalls_entry key = { .id = id };
> +		const struct raw_syscalls_entry *syscalls;
> +		if (table->in_order) {
> +			syscalls = bsearch(&key, table->table,
> +					   table->nr_calls,
> +					   sizeof(table->table[0]),
> +					   syscalls_cmp);
> +		} else {
> +			syscalls = lfind(&key, table->table,
> +					 &table->nr_calls,
> +					 sizeof(table->table[0]),
> +					 syscalls_cmp);
> +		}
> +
> +		if (syscalls) {
> +			trace_seq_printf(s, "%s(%s) ",
> +					 syscalls->name, table->name);
> +		}
> +		table = table->next;
> +	}
> +
> +	return 1;
> +}
> +
> +void raw_syscalls_register_table(const char *arch,
> +				 size_t nr_calls,
> +				 const struct raw_syscalls_entry *table)
> +{
> +	int i;
> +	long current_id = LONG_MIN;
> +	struct raw_syscalls_tables *lookup = malloc_or_die(sizeof(*lookup));
> +
> +	lookup->next = raw_syscalls_tables;
> +	raw_syscalls_tables = lookup;
> +
> +	lookup->name = arch;
> +	lookup->nr_calls = nr_calls;
> +	lookup->table = table;
> +	lookup->in_order = 1;
> +
> +	for (i = 0; i < nr_calls; i++) {
> +		if (table[i].id < current_id) {
> +			lookup->in_order = 0;
> +			break;
> +		}
> +		current_id = table[i].id;
> +	}
> +}
> +
> +int PEVENT_PLUGIN_UNLOADER(void)
> +{
> +	struct raw_syscalls_tables *next = raw_syscalls_tables;
> +	while (next) {
> +		struct raw_syscalls_tables *cur = next;
> +		next = cur->next;
> +		free(cur);
> +	}
> +	return 0;
> +}
> +
> +int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
> +{
> +	pevent_register_event_handler(pevent, -1, "raw_syscalls", "sys_enter",
> +			raw_syscalls_handler, NULL);
> +	pevent_register_event_handler(pevent, -1, "raw_syscalls", "sys_exit",
> +			raw_syscalls_handler, NULL);
> +	return 0;
> +}
> diff --git a/plugin_raw_syscalls.h b/plugin_raw_syscalls.h
> new file mode 100644
> index 0000000..daf968f
> --- /dev/null
> +++ b/plugin_raw_syscalls.h
> @@ -0,0 +1,12 @@
> +#pragma once
> +
> +#include <stddef.h>
> +
> +struct raw_syscalls_entry {
> +	const char *name;
> +	long id;
> +};
> +
> +void raw_syscalls_register_table(const char *arch,
> +				 size_t nr_calls,
> +				 const struct raw_syscalls_entry *table);
> diff --git a/unistd.c.in b/unistd.c.in
> new file mode 100644
> index 0000000..377dd27
> --- /dev/null
> +++ b/unistd.c.in
> @@ -0,0 +1,7 @@
> +
> +static __attribute__((constructor)) void PREFIX_init(void)
> +{
> +	raw_syscalls_register_table(PREFIX_arch,
> +				    sizeof PREFIX_syscalls/sizeof PREFIX_syscalls[0],
> +				    PREFIX_syscalls);
> +};

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ