Add support for personality designation in syscall qualifications

* syscall.c (personality_designators): New array.
* defs.h (personality_designators): New declaration.
* basic_filters.c (qualify_syscall_separate_personality,
qualify_syscall_number_personality): New functions.
(qualify_syscall_number): Use qualify_syscall_separate_personality for
checking for a personality specification, call
qualify_syscall_number_personality for setting number set for specific
personality.
(qualify_syscall_name_personality): New function.
(qualify_syscall_name): Use qualify_syscall_separate_personality for
checking for a personality specification, call
qualify_syscall_name_personality for setting number set for specific
personality.
* strace.1.in (.SS Filtering): Document it.
* NEWS: Mention it.

Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
Closes: https://github.com/strace/strace/issues/35
This commit is contained in:
Eugene Syromyatnikov 2018-02-11 05:04:05 +01:00 committed by Dmitry V. Levin
parent 4a329a0677
commit 3fedf07869
5 changed files with 111 additions and 17 deletions

2
NEWS
View File

@ -19,6 +19,8 @@ Noteworthy changes in release ?.?? (????-??-??)
using --enable-stacktrace option.
* Added -X option for configuring xlat output formatting (addresses
Debian bug #692915).
* Added support for personality designation ("64", "32", or "x32") to syscall
qualifications in -e trace expressions.
* Implemented injection of syscalls with no side effects as an alternative
to injection of an invalid syscall (-e inject=SET:syscall= expression).
* Improved support for reproducible builds (addresses Debian bug #896016).

View File

@ -27,25 +27,82 @@
*/
#include "defs.h"
#include "number_set.h"
#include "filter.h"
#include <regex.h>
#include "filter.h"
#include "number_set.h"
#include "xstring.h"
/**
* Checks whether a @-separated personality specification suffix is present.
* Personality suffix is a one of strings stored in personality_designators
* array.
*
* @param[in] s Specification string to check.
* @param[out] p Where to store personality number if it is found.
* @return If personality is found, the provided string is copied without
* suffix and returned as a result (callee should de-alllocate it
* with free() after use), and personality number is written to p.
* Otherwise, NULL is returned and p is untouched.
*/
static char *
qualify_syscall_separate_personality(const char *s, unsigned int *p)
{
char *pos = strchr(s, '@');
if (!pos)
return NULL;
for (unsigned int i = 0; i < SUPPORTED_PERSONALITIES; i++) {
if (!strcmp(pos + 1, personality_designators[i])) {
*p = i;
return xstrndup(s, pos - s);
}
}
error_msg_and_help("incorrect personality designator '%s'"
" in qualification '%s'", pos + 1, s);
}
static bool
qualify_syscall_number_personality(int n, unsigned int p,
struct number_set *set)
{
if ((unsigned int) n >= nsyscall_vec[p])
return false;
add_number_to_set_array(n, set, p);
return true;
}
static bool
qualify_syscall_number(const char *s, struct number_set *set)
{
int n = string_to_uint(s);
unsigned int p;
char *num_str = qualify_syscall_separate_personality(s, &p);
int n;
if (num_str) {
n = string_to_uint(num_str);
free(num_str);
if (n < 0)
return false;
return qualify_syscall_number_personality(n, p, set);
}
n = string_to_uint(s);
if (n < 0)
return false;
bool done = false;
for (unsigned int p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
if ((unsigned) n >= nsyscall_vec[p])
continue;
add_number_to_set_array(n, set, p);
done = true;
}
for (p = 0; p < SUPPORTED_PERSONALITIES; ++p)
done |= qualify_syscall_number_personality(n, p, set);
return done;
}
@ -164,22 +221,40 @@ scno_by_name(const char *s, unsigned int p, kernel_long_t start)
}
static bool
qualify_syscall_name(const char *s, struct number_set *set)
qualify_syscall_name_personality(const char *s, unsigned int p,
struct number_set *set)
{
bool found = false;
for (unsigned int p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
for (kernel_long_t scno = 0;
(scno = scno_by_name(s, p, scno)) >= 0;
++scno) {
add_number_to_set_array(scno, set, p);
found = true;
}
for (kernel_long_t scno = 0; (scno = scno_by_name(s, p, scno)) >= 0;
++scno) {
add_number_to_set_array(scno, set, p);
found = true;
}
return found;
}
static bool
qualify_syscall_name(const char *s, struct number_set *set)
{
unsigned int p;
char *name_str = qualify_syscall_separate_personality(s, &p);
bool found = false;
if (name_str) {
found = qualify_syscall_name_personality(name_str, p, set);
free(name_str);
return found;
}
for (p = 0; p < SUPPORTED_PERSONALITIES; ++p)
found |= qualify_syscall_name_personality(s, p, set);
return found;
}
static bool
qualify_syscall(const char *token, struct number_set *set)
{

2
defs.h
View File

@ -1370,6 +1370,8 @@ extern const struct_sysent sysent0[];
extern const struct_ioctlent ioctlent0[];
extern const char *const personality_names[];
/* Personality designators to be used for specifying personality */
extern const char *const personality_designators[];
#if SUPPORTED_PERSONALITIES > 1
extern const struct_sysent *sysent;

View File

@ -446,6 +446,9 @@ means to trace every system call except
.BR open .
Question mark before the syscall qualification allows suppression of error
in case no syscalls matched the qualification provided.
Appending one of "@64", "@32", or "@x32" suffixes to the syscall qualification
allows specifying syscalls only for the 64-bit, 32-bit, or 32-on-64-bit
personality, respectively.
In addition, the special values
.B all
and

View File

@ -191,6 +191,18 @@ const char *const personality_names[] =
# endif
;
const char *const personality_designators[] =
# if defined X86_64
{ "64", "32", "x32" }
# elif defined X32
{ "x32", "32" }
# elif SUPPORTED_PERSONALITIES == 2
{ "64", "32" }
# else
{ STRINGIFY_VAL(__WORDSIZE) }
# endif
;
#if SUPPORTED_PERSONALITIES > 1
unsigned current_personality;