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:
parent
8c015ef905
commit
762abe0ce3
8
defs.h
8
defs.h
@ -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
2
ipc.c
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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]),
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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])
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
2
prctl.c
2
prctl.c
@ -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]);
|
||||
}
|
||||
|
||||
|
4
signal.c
4
signal.c
@ -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;
|
||||
|
50
syscall.c
50
syscall.c
@ -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
6
util.c
@ -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 ? ", " : "",
|
||||
|
Loading…
x
Reference in New Issue
Block a user