Remove PT_GET_SC_ARGS_ALL

Reimplement bdf0f24bb1 by checking for the caller' ABI in
the implementation of PT_GET_SC_ARGS, and copying out everything if
it is Linuxolator.

Also fix a minor information leak: if PT_GET_SC_ARGS_ALL is done on the
thread reused after other process, it allows to read some number of that
thread last syscall arguments. Clear td_sa.args in thread_alloc().

Reviewed by:	jhb
Sponsored by:	The FreeBSD Foundation
Differential revision:	https://reviews.freebsd.org/D31968
This commit is contained in:
Konstantin Belousov 2021-09-15 16:24:09 +03:00
parent 181bfb42fd
commit f575573ca5
6 changed files with 16 additions and 35 deletions

View File

@ -116,7 +116,7 @@ gen_table "nfssvcflags" "NFSSVC_[A-Z0-9]+[[:space:]]+0x[0-9]+" "nfs/
gen_table "pathconfname" "_PC_[A-Z4_]+[[:space:]]+[0-9]+" "sys/unistd.h" gen_table "pathconfname" "_PC_[A-Z4_]+[[:space:]]+[0-9]+" "sys/unistd.h"
gen_table "prio" "PRIO_[A-Z]+[[:space:]]+[0-9]" "sys/resource.h" gen_table "prio" "PRIO_[A-Z]+[[:space:]]+[0-9]" "sys/resource.h"
gen_table "procctlcmd" "PROC_[A-Z_]+[[:space:]]+[0-9]" "sys/procctl.h" "PROC_TRACE_CTL_" gen_table "procctlcmd" "PROC_[A-Z_]+[[:space:]]+[0-9]" "sys/procctl.h" "PROC_TRACE_CTL_"
gen_table "ptraceop" "PT_[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/ptrace.h" "PT_GET_SC_ARGS_ALL" gen_table "ptraceop" "PT_[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/ptrace.h"
gen_table "quotactlcmds" "Q_[A-Z]+[[:space:]]+0x[0-9]+" "ufs/ufs/quota.h" gen_table "quotactlcmds" "Q_[A-Z]+[[:space:]]+0x[0-9]+" "ufs/ufs/quota.h"
gen_table "rebootopt" "RB_[A-Z]+[[:space:]]+0x[0-9]+" "sys/reboot.h" gen_table "rebootopt" "RB_[A-Z]+[[:space:]]+0x[0-9]+" "sys/reboot.h"
gen_table "rforkflags" "RF[A-Z]+[[:space:]]+\([0-9]+<<[0-9]+\)" "sys/unistd.h" gen_table "rforkflags" "RF[A-Z]+[[:space:]]+\([0-9]+<<[0-9]+\)" "sys/unistd.h"

View File

@ -544,17 +544,19 @@ linux_ptrace_get_syscall_info(struct thread *td, pid_t pid,
si.op = LINUX_PTRACE_SYSCALL_INFO_ENTRY; si.op = LINUX_PTRACE_SYSCALL_INFO_ENTRY;
si.entry.nr = lwpinfo.pl_syscall_code; si.entry.nr = lwpinfo.pl_syscall_code;
/* /*
* The reason for using PT_GET_SC_ARGS_ALL instead * The use of PT_GET_SC_ARGS there is special,
* of PT_GET_SC_ARGS is to emulate Linux bug which strace(1) * implementation of PT_GET_SC_ARGS for Linux-ABI
* depends on: at initialization it tests whether ptrace works * callers emulates Linux bug which strace(1) depends
* by calling close(2), or some other single-argument syscall, * on: at initialization it tests whether ptrace works
* _with six arguments_, and then verifies whether it can * by calling close(2), or some other single-argument
* fetch them all using this API; otherwise it bails out. * syscall, _with six arguments_, and then verifies
* whether it can fetch them all using this API;
* otherwise it bails out.
*/ */
error = kern_ptrace(td, PT_GET_SC_ARGS_ALL, pid, error = kern_ptrace(td, PT_GET_SC_ARGS, pid,
&si.entry.args, sizeof(si.entry.args)); &si.entry.args, sizeof(si.entry.args));
if (error != 0) { if (error != 0) {
linux_msg(td, "PT_GET_SC_ARGS_ALL failed with error %d", linux_msg(td, "PT_GET_SC_ARGS failed with error %d",
error); error);
return (error); return (error);
} }

View File

@ -1032,9 +1032,6 @@ freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap)
r.pc.pc_limit = PAIR32TO64(off_t, r32.pc.pc_limit); r.pc.pc_limit = PAIR32TO64(off_t, r32.pc.pc_limit);
data = sizeof(r.pc); data = sizeof(r.pc);
break; break;
case PT_GET_SC_ARGS_ALL:
error = EINVAL;
break;
default: default:
addr = uap->addr; addr = uap->addr;
break; break;

View File

@ -762,6 +762,7 @@ thread_alloc(int pages)
return (NULL); return (NULL);
} }
td->td_tid = tid; td->td_tid = tid;
bzero(&td->td_sa.args, sizeof(td->td_sa.args));
kmsan_thread_alloc(td); kmsan_thread_alloc(td);
cpu_thread_alloc(td); cpu_thread_alloc(td);
EVENTHANDLER_DIRECT_INVOKE(thread_ctor, td); EVENTHANDLER_DIRECT_INVOKE(thread_ctor, td);

View File

@ -527,9 +527,6 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
else else
error = copyin(uap->addr, &r.pc, uap->data); error = copyin(uap->addr, &r.pc, uap->data);
break; break;
case PT_GET_SC_ARGS_ALL:
error = EINVAL;
break;
default: default:
addr = uap->addr; addr = uap->addr;
break; break;
@ -711,7 +708,6 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_SET_EVENT_MASK: case PT_SET_EVENT_MASK:
case PT_DETACH: case PT_DETACH:
case PT_GET_SC_ARGS: case PT_GET_SC_ARGS:
case PT_GET_SC_ARGS_ALL:
sx_xlock(&proctree_lock); sx_xlock(&proctree_lock);
proctree_locked = true; proctree_locked = true;
break; break;
@ -1011,21 +1007,10 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
break; break;
} }
bzero(addr, sizeof(td2->td_sa.args)); bzero(addr, sizeof(td2->td_sa.args));
bcopy(td2->td_sa.args, addr, td2->td_sa.callp->sy_narg * /* See the explanation in linux_ptrace_get_syscall_info(). */
sizeof(register_t)); bcopy(td2->td_sa.args, addr, SV_PROC_ABI(td->td_proc) ==
break; SV_ABI_LINUX ? sizeof(td2->td_sa.args) :
td2->td_sa.callp->sy_narg * sizeof(register_t));
case PT_GET_SC_ARGS_ALL:
CTR1(KTR_PTRACE, "PT_GET_SC_ARGS_ALL: pid %d", p->p_pid);
if ((td2->td_dbgflags & (TDB_SCE | TDB_SCX)) == 0
#ifdef COMPAT_FREEBSD32
|| (wrap32 && !safe)
#endif
) {
error = EINVAL;
break;
}
bcopy(td2->td_sa.args, addr, sizeof(td2->td_sa.args));
break; break;
case PT_GET_SC_RET: case PT_GET_SC_RET:

View File

@ -86,10 +86,6 @@
#define PT_VM_TIMESTAMP 40 /* Get VM version (timestamp) */ #define PT_VM_TIMESTAMP 40 /* Get VM version (timestamp) */
#define PT_VM_ENTRY 41 /* Get VM map (entry) */ #define PT_VM_ENTRY 41 /* Get VM map (entry) */
#ifdef _KERNEL
#define PT_GET_SC_ARGS_ALL 42 /* Used by linux(4) */
#endif
#define PT_FIRSTMACH 64 /* for machine-specific requests */ #define PT_FIRSTMACH 64 /* for machine-specific requests */
#include <machine/ptrace.h> /* machine-specific requests, if any */ #include <machine/ptrace.h> /* machine-specific requests, if any */