Use accessors for tcp->s_ent, return a stub struct if it is NULL

Since code paths are non-trivial, it's an attempt to future-proof and
prevent improper access of tcp->s_ent fields.

* defs.h (struct tcb): Update the description of s_ent field.
(stub_sysent): New declaration.
(tcp_sysent, n_args): New macro functions.
* ipc.c (SYS_FUNC(ipc)): Use n_args() instead of tcp->s_ent->nargs.
* linux/alpha/get_syscall_args.c (get_syscall_args): Likewise.
* linux/bfin/get_syscall_args.c (get_syscall_args): Likewise.
* linux/hppa/get_syscall_args.c (get_syscall_args): Likewise.
* linux/ia64/get_syscall_args.c (get_syscall_args): Likewise.
* linux/microblaze/get_syscall_args.c (get_syscall_args): Likewise.
* linux/mips/get_syscall_args.c (get_syscall_args): Likewise.
* linux/sh/get_syscall_args.c (get_syscall_args): Likewise.
* linux/sh64/get_syscall_args.c (get_syscall_args): Likewise.
* linux/x86_64/get_syscall_args.c (get_syscall_args): Likewise.
* linux/xtensa/get_syscall_args.c (get_syscall_args): Likewise.
* prctl.c (print_prctl_args): Likewise.
* signal.c (SYS_FUNC(sgetmask)): Likewise.
* util.c (printargs, printargs_u, printargs_d): Likewise.
* syscall.c (decode_ipc_subcall, decode_syscall_subcall: Likewise.
(dumpio, tamper_with_syscall_exiting, syscall_entering_decode,
syscall_entering_decode, syscall_entering_trace, syscall_entering_trace,
syscall_exiting_decode, print_syscall_resume, syscall_exiting_trace,
get_syscall_result): Use tcp_sysent instead of tcp->s_ent().
(stub_sysent): New stub sysent.
(get_scno): Reset scno, s_ent, qual_flg; initialise s->ent from
stub_sysent.
* pathtrace.c (pathtrace_match_set): Use tcp_sysent instead of
tcp->s_ent().
This commit is contained in:
Eugene Syromyatnikov 2019-01-29 14:40:11 +01:00
parent 8c015ef905
commit 762abe0ce3
17 changed files with 57 additions and 43 deletions

8
defs.h
View File

@ -207,7 +207,9 @@ struct tcb {
const char *auxstr; /* Auxiliary info from syscall (see RVAL_STR) */
void *_priv_data; /* Private data for syscall decoding functions */
void (*_free_priv_data)(void *); /* Callback for freeing priv_data */
const struct_sysent *s_ent; /* sysent[scno] or dummy struct for bad scno */
const struct_sysent *s_ent; /* sysent[scno] or a stub struct for bad
* scno. Use tcp_sysent() macro for access.
*/
const struct_sysent *s_prev_ent; /* for "resuming interrupted SYSCALL" msg */
struct inject_opts *inject_vec[SUPPORTED_PERSONALITIES];
struct timespec stime; /* System time usage as of last process wait */
@ -295,6 +297,10 @@ struct tcb {
# define syscall_delayed(tcp) ((tcp)->flags & TCB_DELAYED)
# define syscall_tampered_nofail(tcp) ((tcp)->flags & TCB_TAMPERED_NO_FAIL)
extern const struct_sysent stub_sysent;
# define tcp_sysent(tcp) (tcp->s_ent ?: &stub_sysent)
# define n_args(tcp) (tcp_sysent(tcp)->nargs)
# include "xlat.h"
extern const struct xlat addrfams[];

2
ipc.c
View File

@ -21,7 +21,7 @@ SYS_FUNC(ipc)
printxval_u(ipccalls, call, NULL);
unsigned int i;
for (i = 1; i < tcp->s_ent->nargs; ++i)
for (i = 1; i < n_args(tcp); ++i)
tprintf(", %#" PRI_klx, tcp->u_arg[i]);
return RVAL_DECODED;

View File

@ -11,7 +11,7 @@ arch_get_syscall_args(struct tcb *tcp)
{
unsigned int i;
for (i = 0; i < tcp->s_ent->nargs; ++i)
for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
return -1;
return 1;

View File

@ -14,7 +14,7 @@ arch_get_syscall_args(struct tcb *tcp)
};
unsigned int i;
for (i = 0; i < tcp->s_ent->nargs; ++i)
for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
return -1;
return 1;

View File

@ -11,7 +11,7 @@ arch_get_syscall_args(struct tcb *tcp)
{
unsigned int i;
for (i = 0; i < tcp->s_ent->nargs; ++i)
for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
return -1;
return 1;

View File

@ -18,7 +18,7 @@ arch_get_syscall_args(struct tcb *tcp)
unsigned long *out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
unsigned int i;
for (i = 0; i < tcp->s_ent->nargs; ++i) {
for (i = 0; i < n_args(tcp); ++i) {
if (umove(tcp,
(unsigned long) ia64_rse_skip_regs(out0, i),
&tcp->u_arg[i]) < 0) {

View File

@ -11,7 +11,7 @@ arch_get_syscall_args(struct tcb *tcp)
{
unsigned int i;
for (i = 0; i < tcp->s_ent->nargs; ++i)
for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
return -1;
return 1;

View File

@ -21,16 +21,16 @@ arch_get_syscall_args(struct tcb *tcp)
tcp->u_arg[1] = mips_REG_A1;
tcp->u_arg[2] = mips_REG_A2;
tcp->u_arg[3] = mips_REG_A3;
if (tcp->s_ent->nargs > 4
if (n_args(tcp) > 4
&& umoven(tcp, mips_REG_SP + 4 * sizeof(tcp->u_arg[0]),
(tcp->s_ent->nargs - 4) * sizeof(tcp->u_arg[0]),
(n_args(tcp) - 4) * sizeof(tcp->u_arg[0]),
&tcp->u_arg[4]) < 0) {
/*
* Let's proceed with the first 4 arguments
* instead of reporting the failure.
*/
memset(&tcp->u_arg[4], 0,
(tcp->s_ent->nargs - 4) * sizeof(tcp->u_arg[0]));
(n_args(tcp) - 4) * sizeof(tcp->u_arg[0]));
}
#else
# error unsupported mips abi
@ -54,7 +54,7 @@ decode_syscall_subcall(struct tcb *tcp)
* and sync_file_range) requires additional code,
* see linux/mips/get_syscall_args.c
*/
if (tcp->s_ent->nargs == MAX_ARGS) {
if (n_args(tcp) == MAX_ARGS) {
if (umoven(tcp,
mips_REG_SP + MAX_ARGS * sizeof(tcp->u_arg[0]),
sizeof(tcp->u_arg[0]),

View File

@ -19,7 +19,7 @@ arch_get_syscall_args(struct tcb *tcp)
};
unsigned int i;
for (i = 0; i < tcp->s_ent->nargs; ++i)
for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
return -1;
return 1;

View File

@ -13,7 +13,7 @@ arch_get_syscall_args(struct tcb *tcp)
static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
unsigned int i;
for (i = 0; i < tcp->s_ent->nargs; ++i)
for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, REG_GENERAL(syscall_regs[i]),
&tcp->u_arg[i]) < 0)
return -1;

View File

@ -11,7 +11,7 @@ arch_get_syscall_args(struct tcb *tcp)
{
if (x86_io.iov_len != sizeof(i386_regs)) {
/* x86-64 or x32 ABI */
if (tcp->s_ent->sys_flags & COMPAT_SYSCALL_TYPES) {
if (tcp_sysent(tcp)->sys_flags & COMPAT_SYSCALL_TYPES) {
/*
* X32 compat syscall: zero-extend from 32 bits.
* Use truncate_klong_to_current_wordsize(tcp->u_arg[N])

View File

@ -20,7 +20,7 @@ arch_get_syscall_args(struct tcb *tcp)
};
unsigned int i;
for (i = 0; i < tcp->s_ent->nargs; ++i)
for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, xtensaregs[i], &tcp->u_arg[i]) < 0)
return -1;
return 1;

View File

@ -167,7 +167,7 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
{
const struct_sysent *s;
s = tcp->s_ent;
s = tcp_sysent(tcp);
if (!(s->sys_flags & (TRACE_FILE | TRACE_DESC | TRACE_NETWORK)))
return false;

View File

@ -61,7 +61,7 @@ print_prctl_args(struct tcb *tcp, const unsigned int first)
{
unsigned int i;
for (i = first; i < tcp->s_ent->nargs; ++i)
for (i = first; i < n_args(tcp); ++i)
tprintf(", %#" PRI_klx, tcp->u_arg[i]);
}

View File

@ -405,10 +405,10 @@ SYS_FUNC(sgetmask)
SYS_FUNC(sigsuspend)
{
#ifdef MIPS
print_sigset_addr_len(tcp, tcp->u_arg[tcp->s_ent->nargs - 1],
print_sigset_addr_len(tcp, tcp->u_arg[n_args(tcp) - 1],
current_wordsize);
#else
tprint_old_sigmask_val("", tcp->u_arg[tcp->s_ent->nargs - 1]);
tprint_old_sigmask_val("", tcp->u_arg[n_args(tcp) - 1]);
#endif
return RVAL_DECODED;

View File

@ -341,7 +341,7 @@ decode_ipc_subcall(struct tcb *tcp)
tcp->qual_flg = qual_flags(tcp->scno);
tcp->s_ent = &sysent[tcp->scno];
const unsigned int n = tcp->s_ent->nargs;
const unsigned int n = n_args(tcp);
unsigned int i;
for (i = 0; i < n; i++)
tcp->u_arg[i] = tcp->u_arg[i + 1];
@ -361,7 +361,7 @@ dumpio(struct tcb *tcp)
return;
if (is_number_in_set(fd, write_set)) {
switch (tcp->s_ent->sen) {
switch (tcp_sysent(tcp)->sen) {
case SEN_write:
case SEN_pwrite:
case SEN_send:
@ -388,7 +388,7 @@ dumpio(struct tcb *tcp)
return;
if (is_number_in_set(fd, read_set)) {
switch (tcp->s_ent->sen) {
switch (tcp_sysent(tcp)->sen) {
case SEN_read:
case SEN_pread:
case SEN_recv:
@ -548,10 +548,9 @@ syscall_entering_decode(struct tcb *tcp)
int res = get_scno(tcp);
if (res == 0)
return res;
int scno_good = res;
if (res != 1 || (res = get_syscall_args(tcp)) != 1) {
printleader(tcp);
tprintf("%s(", scno_good == 1 ? tcp->s_ent->sys_name : "????");
tprintf("%s(", tcp_sysent(tcp)->sys_name);
/*
* " <unavailable>" will be added later by the code which
* detects ptrace errors.
@ -563,7 +562,7 @@ syscall_entering_decode(struct tcb *tcp)
|| defined SYS_socket_subcall \
|| defined SYS_syscall_subcall
for (;;) {
switch (tcp->s_ent->sen) {
switch (tcp_sysent(tcp)->sen) {
# ifdef SYS_ipc_subcall
case SEN_ipc:
decode_ipc_subcall(tcp);
@ -577,7 +576,7 @@ syscall_entering_decode(struct tcb *tcp)
# ifdef SYS_syscall_subcall
case SEN_syscall:
decode_syscall_subcall(tcp);
if (tcp->s_ent->sen != SEN_syscall)
if (tcp_sysent(tcp)->sen != SEN_syscall)
continue;
break;
# endif
@ -599,7 +598,7 @@ syscall_entering_trace(struct tcb *tcp, unsigned int *sig)
*/
tcp->qual_flg &= ~QUAL_INJECT;
switch (tcp->s_ent->sen) {
switch (tcp_sysent(tcp)->sen) {
case SEN_execve:
case SEN_execveat:
case SEN_execv:
@ -631,14 +630,14 @@ syscall_entering_trace(struct tcb *tcp, unsigned int *sig)
#ifdef ENABLE_STACKTRACE
if (stack_trace_enabled) {
if (tcp->s_ent->sys_flags & STACKTRACE_CAPTURE_ON_ENTER)
if (tcp_sysent(tcp)->sys_flags & STACKTRACE_CAPTURE_ON_ENTER)
unwind_tcb_capture(tcp);
}
#endif
printleader(tcp);
tprintf("%s(", tcp->s_ent->sys_name);
int res = raw(tcp) ? printargs(tcp) : tcp->s_ent->sys_func(tcp);
tprintf("%s(", tcp_sysent(tcp)->sys_name);
int res = raw(tcp) ? printargs(tcp) : tcp_sysent(tcp)->sys_func(tcp);
fflush(tcp->outf);
return res;
}
@ -668,7 +667,7 @@ syscall_exiting_decode(struct tcb *tcp, struct timespec *pts)
if ((Tflag || cflag) && !filtered(tcp))
clock_gettime(CLOCK_MONOTONIC, pts);
if (tcp->s_ent->sys_flags & MEMORY_MAPPING_CHANGE)
if (tcp_sysent(tcp)->sys_flags & MEMORY_MAPPING_CHANGE)
mmap_notify_report(tcp);
if (filtered(tcp))
@ -702,7 +701,7 @@ print_syscall_resume(struct tcb *tcp)
|| (tcp->flags & TCB_REPRINT)) {
tcp->flags &= ~TCB_REPRINT;
printleader(tcp);
tprintf("<... %s resumed>", tcp->s_ent->sys_name);
tprintf("<... %s resumed>", tcp_sysent(tcp)->sys_name);
}
}
@ -750,7 +749,7 @@ syscall_exiting_trace(struct tcb *tcp, struct timespec *ts, int res)
if (tcp->sys_func_rval & RVAL_DECODED)
sys_res = tcp->sys_func_rval;
else
sys_res = tcp->s_ent->sys_func(tcp);
sys_res = tcp_sysent(tcp)->sys_func(tcp);
}
tprints(") ");
@ -1237,6 +1236,13 @@ get_syscall_regs(struct tcb *tcp)
return get_regs(tcp);
}
const struct_sysent stub_sysent = {
.nargs = MAX_ARGS,
.sen = SEN_printargs,
.sys_func = printargs,
.sys_name = "????",
};
/*
* Returns:
* 0: "ignore this ptrace stop", syscall_entering_decode() should return a "bail
@ -1248,6 +1254,10 @@ get_syscall_regs(struct tcb *tcp)
int
get_scno(struct tcb *tcp)
{
tcp->scno = -1;
tcp->s_ent = NULL;
tcp->qual_flg = QUAL_RAW | DEFAULT_QUAL_FLAGS;
if (get_syscall_regs(tcp) < 0)
return -1;
@ -1275,9 +1285,7 @@ get_scno(struct tcb *tcp)
struct sysent_buf *s = xcalloc(1, sizeof(*s));
s->tcp = tcp;
s->ent.nargs = MAX_ARGS;
s->ent.sen = SEN_printargs;
s->ent.sys_func = printargs;
s->ent = stub_sysent;
s->ent.sys_name = s->buf;
xsprintf(s->buf, "syscall_%#" PRI_klx, shuffle_scno(tcp->scno));
@ -1308,7 +1316,7 @@ get_syscall_args(struct tcb *tcp)
for (unsigned int i = 0; i < ARRAY_SIZE(tcp->u_arg); ++i)
tcp->u_arg[i] = ptrace_sci.entry.args[i];
#if SUPPORTED_PERSONALITIES > 1
if (tcp->s_ent->sys_flags & COMPAT_SYSCALL_TYPES) {
if (tcp_sysent(tcp)->sys_flags & COMPAT_SYSCALL_TYPES) {
for (unsigned int i = 0; i < ARRAY_SIZE(tcp->u_arg); ++i)
tcp->u_arg[i] = (uint32_t) tcp->u_arg[i];
}
@ -1335,7 +1343,7 @@ get_syscall_result(struct tcb *tcp)
if (get_syscall_result_regs(tcp) < 0)
return -1;
get_error(tcp,
(!(tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS)
(!(tcp_sysent(tcp)->sys_flags & SYSCALL_NEVER_FAILS)
|| syscall_tampered(tcp))
&& !syscall_tampered_nofail(tcp));
@ -1381,7 +1389,7 @@ set_error(struct tcb *tcp, unsigned long new_error)
if (ptrace_syscall_info_is_valid())
tcp->u_rval = -1;
else
get_error(tcp, !(tcp->s_ent->sys_flags &
get_error(tcp, !(tcp_sysent(tcp)->sys_flags &
SYSCALL_NEVER_FAILS));
}
}
@ -1405,7 +1413,7 @@ set_success(struct tcb *tcp, kernel_long_t new_rval)
if (ptrace_syscall_info_is_valid())
tcp->u_error = 0;
else
get_error(tcp, !(tcp->s_ent->sys_flags &
get_error(tcp, !(tcp_sysent(tcp)->sys_flags &
SYSCALL_NEVER_FAILS));
}
}

6
util.c
View File

@ -1161,7 +1161,7 @@ print_array_ex(struct tcb *const tcp,
int
printargs(struct tcb *tcp)
{
const int n = tcp->s_ent->nargs;
const int n = n_args(tcp);
int i;
for (i = 0; i < n; ++i)
tprintf("%s%#" PRI_klx, i ? ", " : "", tcp->u_arg[i]);
@ -1171,7 +1171,7 @@ printargs(struct tcb *tcp)
int
printargs_u(struct tcb *tcp)
{
const int n = tcp->s_ent->nargs;
const int n = n_args(tcp);
int i;
for (i = 0; i < n; ++i)
tprintf("%s%u", i ? ", " : "",
@ -1182,7 +1182,7 @@ printargs_u(struct tcb *tcp)
int
printargs_d(struct tcb *tcp)
{
const int n = tcp->s_ent->nargs;
const int n = n_args(tcp);
int i;
for (i = 0; i < n; ++i)
tprintf("%s%d", i ? ", " : "",