linux_ptrace.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (c) 2001 Alexander Kabaev
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. #include <sys/cdefs.h>
  29. __FBSDID("$FreeBSD$");
  30. #include "opt_cpu.h"
  31. #include <sys/param.h>
  32. #include <sys/lock.h>
  33. #include <sys/mutex.h>
  34. #include <sys/proc.h>
  35. #include <sys/ptrace.h>
  36. #include <sys/syscallsubr.h>
  37. #include <sys/systm.h>
  38. #include <machine/md_var.h>
  39. #include <machine/pcb.h>
  40. #include <machine/reg.h>
  41. #include <i386/linux/linux.h>
  42. #include <i386/linux/linux_proto.h>
  43. #include <compat/linux/linux_signal.h>
  44. /*
  45. * Linux ptrace requests numbers. Mostly identical to FreeBSD,
  46. * except for MD ones and PT_ATTACH/PT_DETACH.
  47. */
  48. #define PTRACE_TRACEME 0
  49. #define PTRACE_PEEKTEXT 1
  50. #define PTRACE_PEEKDATA 2
  51. #define PTRACE_PEEKUSR 3
  52. #define PTRACE_POKETEXT 4
  53. #define PTRACE_POKEDATA 5
  54. #define PTRACE_POKEUSR 6
  55. #define PTRACE_CONT 7
  56. #define PTRACE_KILL 8
  57. #define PTRACE_SINGLESTEP 9
  58. #define PTRACE_ATTACH 16
  59. #define PTRACE_DETACH 17
  60. #define LINUX_PTRACE_SYSCALL 24
  61. #define PTRACE_GETREGS 12
  62. #define PTRACE_SETREGS 13
  63. #define PTRACE_GETFPREGS 14
  64. #define PTRACE_SETFPREGS 15
  65. #define PTRACE_GETFPXREGS 18
  66. #define PTRACE_SETFPXREGS 19
  67. #define PTRACE_SETOPTIONS 21
  68. /*
  69. * Linux keeps debug registers at the following
  70. * offset in the user struct
  71. */
  72. #define LINUX_DBREG_OFFSET 252
  73. #define LINUX_DBREG_SIZE (8*sizeof(l_int))
  74. static __inline int
  75. map_signum(int signum)
  76. {
  77. signum = linux_to_bsd_signal(signum);
  78. return ((signum == SIGSTOP)? 0 : signum);
  79. }
  80. struct linux_pt_reg {
  81. l_long ebx;
  82. l_long ecx;
  83. l_long edx;
  84. l_long esi;
  85. l_long edi;
  86. l_long ebp;
  87. l_long eax;
  88. l_int xds;
  89. l_int xes;
  90. l_int xfs;
  91. l_int xgs;
  92. l_long orig_eax;
  93. l_long eip;
  94. l_int xcs;
  95. l_long eflags;
  96. l_long esp;
  97. l_int xss;
  98. };
  99. /*
  100. * Translate i386 ptrace registers between Linux and FreeBSD formats.
  101. * The translation is pretty straighforward, for all registers, but
  102. * orig_eax on Linux side and r_trapno and r_err in FreeBSD
  103. */
  104. static void
  105. map_regs_to_linux(struct reg *bsd_r, struct linux_pt_reg *linux_r)
  106. {
  107. linux_r->ebx = bsd_r->r_ebx;
  108. linux_r->ecx = bsd_r->r_ecx;
  109. linux_r->edx = bsd_r->r_edx;
  110. linux_r->esi = bsd_r->r_esi;
  111. linux_r->edi = bsd_r->r_edi;
  112. linux_r->ebp = bsd_r->r_ebp;
  113. linux_r->eax = bsd_r->r_eax;
  114. linux_r->xds = bsd_r->r_ds;
  115. linux_r->xes = bsd_r->r_es;
  116. linux_r->xfs = bsd_r->r_fs;
  117. linux_r->xgs = bsd_r->r_gs;
  118. linux_r->orig_eax = bsd_r->r_eax;
  119. linux_r->eip = bsd_r->r_eip;
  120. linux_r->xcs = bsd_r->r_cs;
  121. linux_r->eflags = bsd_r->r_eflags;
  122. linux_r->esp = bsd_r->r_esp;
  123. linux_r->xss = bsd_r->r_ss;
  124. }
  125. static void
  126. map_regs_from_linux(struct reg *bsd_r, struct linux_pt_reg *linux_r)
  127. {
  128. bsd_r->r_ebx = linux_r->ebx;
  129. bsd_r->r_ecx = linux_r->ecx;
  130. bsd_r->r_edx = linux_r->edx;
  131. bsd_r->r_esi = linux_r->esi;
  132. bsd_r->r_edi = linux_r->edi;
  133. bsd_r->r_ebp = linux_r->ebp;
  134. bsd_r->r_eax = linux_r->eax;
  135. bsd_r->r_ds = linux_r->xds;
  136. bsd_r->r_es = linux_r->xes;
  137. bsd_r->r_fs = linux_r->xfs;
  138. bsd_r->r_gs = linux_r->xgs;
  139. bsd_r->r_eip = linux_r->eip;
  140. bsd_r->r_cs = linux_r->xcs;
  141. bsd_r->r_eflags = linux_r->eflags;
  142. bsd_r->r_esp = linux_r->esp;
  143. bsd_r->r_ss = linux_r->xss;
  144. }
  145. struct linux_pt_fpreg {
  146. l_long cwd;
  147. l_long swd;
  148. l_long twd;
  149. l_long fip;
  150. l_long fcs;
  151. l_long foo;
  152. l_long fos;
  153. l_long st_space[2*10];
  154. };
  155. static void
  156. map_fpregs_to_linux(struct fpreg *bsd_r, struct linux_pt_fpreg *linux_r)
  157. {
  158. linux_r->cwd = bsd_r->fpr_env[0];
  159. linux_r->swd = bsd_r->fpr_env[1];
  160. linux_r->twd = bsd_r->fpr_env[2];
  161. linux_r->fip = bsd_r->fpr_env[3];
  162. linux_r->fcs = bsd_r->fpr_env[4];
  163. linux_r->foo = bsd_r->fpr_env[5];
  164. linux_r->fos = bsd_r->fpr_env[6];
  165. bcopy(bsd_r->fpr_acc, linux_r->st_space, sizeof(linux_r->st_space));
  166. }
  167. static void
  168. map_fpregs_from_linux(struct fpreg *bsd_r, struct linux_pt_fpreg *linux_r)
  169. {
  170. bsd_r->fpr_env[0] = linux_r->cwd;
  171. bsd_r->fpr_env[1] = linux_r->swd;
  172. bsd_r->fpr_env[2] = linux_r->twd;
  173. bsd_r->fpr_env[3] = linux_r->fip;
  174. bsd_r->fpr_env[4] = linux_r->fcs;
  175. bsd_r->fpr_env[5] = linux_r->foo;
  176. bsd_r->fpr_env[6] = linux_r->fos;
  177. bcopy(bsd_r->fpr_acc, linux_r->st_space, sizeof(bsd_r->fpr_acc));
  178. }
  179. struct linux_pt_fpxreg {
  180. l_ushort cwd;
  181. l_ushort swd;
  182. l_ushort twd;
  183. l_ushort fop;
  184. l_long fip;
  185. l_long fcs;
  186. l_long foo;
  187. l_long fos;
  188. l_long mxcsr;
  189. l_long reserved;
  190. l_long st_space[32];
  191. l_long xmm_space[32];
  192. l_long padding[56];
  193. };
  194. static int
  195. linux_proc_read_fpxregs(struct thread *td, struct linux_pt_fpxreg *fpxregs)
  196. {
  197. PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);
  198. if (cpu_fxsr == 0 || (td->td_proc->p_flag & P_INMEM) == 0)
  199. return (EIO);
  200. bcopy(&get_pcb_user_save_td(td)->sv_xmm, fpxregs, sizeof(*fpxregs));
  201. return (0);
  202. }
  203. static int
  204. linux_proc_write_fpxregs(struct thread *td, struct linux_pt_fpxreg *fpxregs)
  205. {
  206. PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);
  207. if (cpu_fxsr == 0 || (td->td_proc->p_flag & P_INMEM) == 0)
  208. return (EIO);
  209. bcopy(fpxregs, &get_pcb_user_save_td(td)->sv_xmm, sizeof(*fpxregs));
  210. return (0);
  211. }
  212. int
  213. linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
  214. {
  215. union {
  216. struct linux_pt_reg reg;
  217. struct linux_pt_fpreg fpreg;
  218. struct linux_pt_fpxreg fpxreg;
  219. } r;
  220. union {
  221. struct reg bsd_reg;
  222. struct fpreg bsd_fpreg;
  223. struct dbreg bsd_dbreg;
  224. } u;
  225. void *addr;
  226. pid_t pid;
  227. int error, req;
  228. error = 0;
  229. /* by default, just copy data intact */
  230. req = uap->req;
  231. pid = (pid_t)uap->pid;
  232. addr = (void *)uap->addr;
  233. switch (req) {
  234. case PTRACE_TRACEME:
  235. case PTRACE_POKETEXT:
  236. case PTRACE_POKEDATA:
  237. case PTRACE_KILL:
  238. error = kern_ptrace(td, req, pid, addr, uap->data);
  239. break;
  240. case PTRACE_PEEKTEXT:
  241. case PTRACE_PEEKDATA: {
  242. /* need to preserve return value */
  243. int rval = td->td_retval[0];
  244. error = kern_ptrace(td, req, pid, addr, 0);
  245. if (error == 0)
  246. error = copyout(td->td_retval, (void *)uap->data,
  247. sizeof(l_int));
  248. td->td_retval[0] = rval;
  249. break;
  250. }
  251. case PTRACE_DETACH:
  252. error = kern_ptrace(td, PT_DETACH, pid, (void *)1,
  253. map_signum(uap->data));
  254. break;
  255. case PTRACE_SINGLESTEP:
  256. case PTRACE_CONT:
  257. error = kern_ptrace(td, req, pid, (void *)1,
  258. map_signum(uap->data));
  259. break;
  260. case PTRACE_ATTACH:
  261. error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data);
  262. break;
  263. case PTRACE_GETREGS:
  264. /* Linux is using data where FreeBSD is using addr */
  265. error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
  266. if (error == 0) {
  267. map_regs_to_linux(&u.bsd_reg, &r.reg);
  268. error = copyout(&r.reg, (void *)uap->data,
  269. sizeof(r.reg));
  270. }
  271. break;
  272. case PTRACE_SETREGS:
  273. /* Linux is using data where FreeBSD is using addr */
  274. error = copyin((void *)uap->data, &r.reg, sizeof(r.reg));
  275. if (error == 0) {
  276. map_regs_from_linux(&u.bsd_reg, &r.reg);
  277. error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0);
  278. }
  279. break;
  280. case PTRACE_GETFPREGS:
  281. /* Linux is using data where FreeBSD is using addr */
  282. error = kern_ptrace(td, PT_GETFPREGS, pid, &u.bsd_fpreg, 0);
  283. if (error == 0) {
  284. map_fpregs_to_linux(&u.bsd_fpreg, &r.fpreg);
  285. error = copyout(&r.fpreg, (void *)uap->data,
  286. sizeof(r.fpreg));
  287. }
  288. break;
  289. case PTRACE_SETFPREGS:
  290. /* Linux is using data where FreeBSD is using addr */
  291. error = copyin((void *)uap->data, &r.fpreg, sizeof(r.fpreg));
  292. if (error == 0) {
  293. map_fpregs_from_linux(&u.bsd_fpreg, &r.fpreg);
  294. error = kern_ptrace(td, PT_SETFPREGS, pid,
  295. &u.bsd_fpreg, 0);
  296. }
  297. break;
  298. case PTRACE_SETFPXREGS:
  299. error = copyin((void *)uap->data, &r.fpxreg, sizeof(r.fpxreg));
  300. if (error)
  301. break;
  302. /* FALL THROUGH */
  303. case PTRACE_GETFPXREGS: {
  304. struct proc *p;
  305. struct thread *td2;
  306. if (sizeof(struct linux_pt_fpxreg) != sizeof(struct savexmm)) {
  307. static int once = 0;
  308. if (!once) {
  309. printf("linux: savexmm != linux_pt_fpxreg\n");
  310. once = 1;
  311. }
  312. error = EIO;
  313. break;
  314. }
  315. if ((p = pfind(uap->pid)) == NULL) {
  316. error = ESRCH;
  317. break;
  318. }
  319. /* Exiting processes can't be debugged. */
  320. if ((p->p_flag & P_WEXIT) != 0) {
  321. error = ESRCH;
  322. goto fail;
  323. }
  324. if ((error = p_candebug(td, p)) != 0)
  325. goto fail;
  326. /* System processes can't be debugged. */
  327. if ((p->p_flag & P_SYSTEM) != 0) {
  328. error = EINVAL;
  329. goto fail;
  330. }
  331. /* not being traced... */
  332. if ((p->p_flag & P_TRACED) == 0) {
  333. error = EPERM;
  334. goto fail;
  335. }
  336. /* not being traced by YOU */
  337. if (p->p_pptr != td->td_proc) {
  338. error = EBUSY;
  339. goto fail;
  340. }
  341. /* not currently stopped */
  342. if (!P_SHOULDSTOP(p) || (p->p_flag & P_WAITED) == 0) {
  343. error = EBUSY;
  344. goto fail;
  345. }
  346. if (req == PTRACE_GETFPXREGS) {
  347. _PHOLD(p); /* may block */
  348. td2 = FIRST_THREAD_IN_PROC(p);
  349. error = linux_proc_read_fpxregs(td2, &r.fpxreg);
  350. _PRELE(p);
  351. PROC_UNLOCK(p);
  352. if (error == 0)
  353. error = copyout(&r.fpxreg, (void *)uap->data,
  354. sizeof(r.fpxreg));
  355. } else {
  356. /* clear dangerous bits exactly as Linux does*/
  357. r.fpxreg.mxcsr &= 0xffbf;
  358. _PHOLD(p); /* may block */
  359. td2 = FIRST_THREAD_IN_PROC(p);
  360. error = linux_proc_write_fpxregs(td2, &r.fpxreg);
  361. _PRELE(p);
  362. PROC_UNLOCK(p);
  363. }
  364. break;
  365. fail:
  366. PROC_UNLOCK(p);
  367. break;
  368. }
  369. case PTRACE_PEEKUSR:
  370. case PTRACE_POKEUSR: {
  371. error = EIO;
  372. /* check addr for alignment */
  373. if (uap->addr < 0 || uap->addr & (sizeof(l_int) - 1))
  374. break;
  375. /*
  376. * Allow Linux programs to access register values in
  377. * user struct. We simulate this through PT_GET/SETREGS
  378. * as necessary.
  379. */
  380. if (uap->addr < sizeof(struct linux_pt_reg)) {
  381. error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
  382. if (error != 0)
  383. break;
  384. map_regs_to_linux(&u.bsd_reg, &r.reg);
  385. if (req == PTRACE_PEEKUSR) {
  386. error = copyout((char *)&r.reg + uap->addr,
  387. (void *)uap->data, sizeof(l_int));
  388. break;
  389. }
  390. *(l_int *)((char *)&r.reg + uap->addr) =
  391. (l_int)uap->data;
  392. map_regs_from_linux(&u.bsd_reg, &r.reg);
  393. error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0);
  394. }
  395. /*
  396. * Simulate debug registers access
  397. */
  398. if (uap->addr >= LINUX_DBREG_OFFSET &&
  399. uap->addr <= LINUX_DBREG_OFFSET + LINUX_DBREG_SIZE) {
  400. error = kern_ptrace(td, PT_GETDBREGS, pid, &u.bsd_dbreg,
  401. 0);
  402. if (error != 0)
  403. break;
  404. uap->addr -= LINUX_DBREG_OFFSET;
  405. if (req == PTRACE_PEEKUSR) {
  406. error = copyout((char *)&u.bsd_dbreg +
  407. uap->addr, (void *)uap->data,
  408. sizeof(l_int));
  409. break;
  410. }
  411. *(l_int *)((char *)&u.bsd_dbreg + uap->addr) =
  412. uap->data;
  413. error = kern_ptrace(td, PT_SETDBREGS, pid,
  414. &u.bsd_dbreg, 0);
  415. }
  416. break;
  417. }
  418. case LINUX_PTRACE_SYSCALL:
  419. /* fall through */
  420. default:
  421. printf("linux: ptrace(%u, ...) not implemented\n",
  422. (unsigned int)uap->req);
  423. error = EINVAL;
  424. break;
  425. }
  426. return (error);
  427. }