1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2021 Edward Tomasz Napierala <trasz@FreeBSD.org> 5 * Copyright (c) 2018 Chuck Tuffli 6 * Copyright (c) 2017 Dell EMC 7 * Copyright (c) 2000 David O'Brien 8 * Copyright (c) 1995-1996 Søren Schmidt 9 * Copyright (c) 1996 Peter Wemm 10 * All rights reserved. 11 * 12 * This software was developed by the University of Cambridge Computer 13 * Laboratory as part of the CHERI for Hypervisors and Operating Systems 14 * (CHaOS) project, funded by EPSRC grant EP/V000292/1. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer 21 * in this position and unchanged. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. The name of the author may not be used to endorse or promote products 26 * derived from this software without specific prior written permission 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 29 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 30 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 31 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 33 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 37 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/cdefs.h> 41 __FBSDID("$FreeBSD$"); 42 43 #include <sys/param.h> 44 #include <sys/exec.h> 45 #include <sys/imgact.h> 46 #include <sys/imgact_elf.h> 47 #include <sys/lock.h> 48 #include <sys/malloc.h> 49 #include <sys/mutex.h> 50 #include <sys/proc.h> 51 #include <sys/procfs.h> 52 #include <sys/reg.h> 53 #include <sys/sbuf.h> 54 #include <sys/sysent.h> 55 56 #include <vm/vm.h> 57 #include <vm/pmap.h> 58 #include <vm/vm_map.h> 59 60 #include <machine/elf.h> 61 62 #ifdef COMPAT_LINUX32 63 #define linux_pt_regset linux_pt_regset32 64 #define bsd_to_linux_regset bsd_to_linux_regset32 65 #include <machine/../linux32/linux.h> 66 #else 67 #include <machine/../linux/linux.h> 68 #endif 69 #include <compat/linux/linux_elf.h> 70 #include <compat/linux/linux_mib.h> 71 #include <compat/linux/linux_misc.h> 72 73 struct l_elf_siginfo { 74 l_int si_signo; 75 l_int si_code; 76 l_int si_errno; 77 }; 78 79 typedef struct linux_pt_regset l_elf_gregset_t; 80 81 struct linux_elf_prstatus { 82 struct l_elf_siginfo pr_info; 83 l_short pr_cursig; 84 l_ulong pr_sigpend; 85 l_ulong pr_sighold; 86 l_pid_t pr_pid; 87 l_pid_t pr_ppid; 88 l_pid_t pr_pgrp; 89 l_pid_t pr_sid; 90 l_timeval pr_utime; 91 l_timeval pr_stime; 92 l_timeval pr_cutime; 93 l_timeval pr_cstime; 94 l_elf_gregset_t pr_reg; 95 l_int pr_fpvalid; 96 }; 97 98 #define LINUX_NT_AUXV 6 99 100 static void __linuxN(note_fpregset)(void *, struct sbuf *, size_t *); 101 static void __linuxN(note_prpsinfo)(void *, struct sbuf *, size_t *); 102 static void __linuxN(note_prstatus)(void *, struct sbuf *, size_t *); 103 static void __linuxN(note_threadmd)(void *, struct sbuf *, size_t *); 104 static void __linuxN(note_nt_auxv)(void *, struct sbuf *, size_t *); 105 106 void 107 __linuxN(prepare_notes)(struct thread *td, struct note_info_list *list, 108 size_t *sizep) 109 { 110 struct proc *p; 111 struct thread *thr; 112 size_t size; 113 114 p = td->td_proc; 115 size = 0; 116 117 /* 118 * To have the debugger select the right thread (LWP) as the initial 119 * thread, we dump the state of the thread passed to us in td first. 120 * This is the thread that causes the core dump and thus likely to 121 * be the right thread one wants to have selected in the debugger. 122 */ 123 thr = td; 124 while (thr != NULL) { 125 size += __elfN(register_note)(td, list, 126 NT_PRSTATUS, __linuxN(note_prstatus), thr); 127 size += __elfN(register_note)(td, list, 128 NT_PRPSINFO, __linuxN(note_prpsinfo), p); 129 size += __elfN(register_note)(td, list, 130 LINUX_NT_AUXV, __linuxN(note_nt_auxv), p); 131 size += __elfN(register_note)(td, list, 132 NT_FPREGSET, __linuxN(note_fpregset), thr); 133 size += __elfN(register_note)(td, list, 134 -1, __linuxN(note_threadmd), thr); 135 136 thr = thr == td ? TAILQ_FIRST(&p->p_threads) : 137 TAILQ_NEXT(thr, td_plist); 138 if (thr == td) 139 thr = TAILQ_NEXT(thr, td_plist); 140 } 141 142 *sizep = size; 143 } 144 145 typedef struct linux_elf_prstatus linux_elf_prstatus_t; 146 #ifdef COMPAT_LINUX32 147 typedef struct prpsinfo32 linux_elf_prpsinfo_t; 148 typedef struct fpreg32 linux_elf_prfpregset_t; 149 #else 150 typedef prpsinfo_t linux_elf_prpsinfo_t; 151 typedef prfpregset_t linux_elf_prfpregset_t; 152 #endif 153 154 static void 155 __linuxN(note_prpsinfo)(void *arg, struct sbuf *sb, size_t *sizep) 156 { 157 struct sbuf sbarg; 158 size_t len; 159 char *cp, *end; 160 struct proc *p; 161 linux_elf_prpsinfo_t *psinfo; 162 int error; 163 164 p = arg; 165 if (sb != NULL) { 166 KASSERT(*sizep == sizeof(*psinfo), ("invalid size")); 167 psinfo = malloc(sizeof(*psinfo), M_TEMP, M_ZERO | M_WAITOK); 168 psinfo->pr_version = PRPSINFO_VERSION; 169 psinfo->pr_psinfosz = sizeof(linux_elf_prpsinfo_t); 170 strlcpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname)); 171 PROC_LOCK(p); 172 if (p->p_args != NULL) { 173 len = sizeof(psinfo->pr_psargs) - 1; 174 if (len > p->p_args->ar_length) 175 len = p->p_args->ar_length; 176 memcpy(psinfo->pr_psargs, p->p_args->ar_args, len); 177 PROC_UNLOCK(p); 178 error = 0; 179 } else { 180 _PHOLD(p); 181 PROC_UNLOCK(p); 182 sbuf_new(&sbarg, psinfo->pr_psargs, 183 sizeof(psinfo->pr_psargs), SBUF_FIXEDLEN); 184 error = proc_getargv(curthread, p, &sbarg); 185 PRELE(p); 186 if (sbuf_finish(&sbarg) == 0) { 187 len = sbuf_len(&sbarg) - 1; 188 if (len > 0) 189 len--; 190 } else { 191 len = sizeof(psinfo->pr_psargs) - 1; 192 } 193 sbuf_delete(&sbarg); 194 } 195 if (error != 0 || len == 0 || (ssize_t)len == -1) 196 strlcpy(psinfo->pr_psargs, p->p_comm, 197 sizeof(psinfo->pr_psargs)); 198 else { 199 KASSERT(len < sizeof(psinfo->pr_psargs), 200 ("len is too long: %zu vs %zu", len, 201 sizeof(psinfo->pr_psargs))); 202 cp = psinfo->pr_psargs; 203 end = cp + len - 1; 204 for (;;) { 205 cp = memchr(cp, '\0', end - cp); 206 if (cp == NULL) 207 break; 208 *cp = ' '; 209 } 210 } 211 psinfo->pr_pid = p->p_pid; 212 sbuf_bcat(sb, psinfo, sizeof(*psinfo)); 213 free(psinfo, M_TEMP); 214 } 215 *sizep = sizeof(*psinfo); 216 } 217 218 static void 219 __linuxN(note_prstatus)(void *arg, struct sbuf *sb, size_t *sizep) 220 { 221 struct thread *td; 222 linux_elf_prstatus_t *status; 223 #ifdef COMPAT_LINUX32 224 struct reg32 pr_reg; 225 #else 226 struct reg pr_reg; 227 #endif 228 229 td = arg; 230 if (sb != NULL) { 231 KASSERT(*sizep == sizeof(*status), ("invalid size")); 232 status = malloc(sizeof(*status), M_TEMP, M_ZERO | M_WAITOK); 233 234 /* 235 * XXX: Some fields missing. 236 */ 237 status->pr_cursig = td->td_proc->p_sig; 238 status->pr_pid = td->td_tid; 239 240 #ifdef COMPAT_LINUX32 241 fill_regs32(td, &pr_reg); 242 #else 243 fill_regs(td, &pr_reg); 244 #endif 245 bsd_to_linux_regset(&pr_reg, &status->pr_reg); 246 sbuf_bcat(sb, status, sizeof(*status)); 247 free(status, M_TEMP); 248 } 249 *sizep = sizeof(*status); 250 } 251 252 static void 253 __linuxN(note_fpregset)(void *arg, struct sbuf *sb, size_t *sizep) 254 { 255 struct thread *td; 256 linux_elf_prfpregset_t *fpregset; 257 258 td = arg; 259 if (sb != NULL) { 260 KASSERT(*sizep == sizeof(*fpregset), ("invalid size")); 261 fpregset = malloc(sizeof(*fpregset), M_TEMP, M_ZERO | M_WAITOK); 262 #ifdef COMPAT_LINUX32 263 fill_fpregs32(td, fpregset); 264 #else 265 fill_fpregs(td, fpregset); 266 #endif 267 sbuf_bcat(sb, fpregset, sizeof(*fpregset)); 268 free(fpregset, M_TEMP); 269 } 270 *sizep = sizeof(*fpregset); 271 } 272 273 /* 274 * Allow for MD specific notes, as well as any MD 275 * specific preparations for writing MI notes. 276 */ 277 static void 278 __linuxN(note_threadmd)(void *arg, struct sbuf *sb, size_t *sizep) 279 { 280 struct thread *td; 281 void *buf; 282 size_t size; 283 284 td = arg; 285 size = *sizep; 286 if (size != 0 && sb != NULL) 287 buf = malloc(size, M_TEMP, M_ZERO | M_WAITOK); 288 else 289 buf = NULL; 290 size = 0; 291 __elfN(dump_thread)(td, buf, &size); 292 KASSERT(sb == NULL || *sizep == size, ("invalid size")); 293 if (size != 0 && sb != NULL) 294 sbuf_bcat(sb, buf, size); 295 free(buf, M_TEMP); 296 *sizep = size; 297 } 298 299 static void 300 __linuxN(note_nt_auxv)(void *arg, struct sbuf *sb, size_t *sizep) 301 { 302 struct proc *p; 303 size_t size; 304 305 p = arg; 306 if (sb == NULL) { 307 size = 0; 308 sb = sbuf_new(NULL, NULL, LINUX_AT_COUNT * sizeof(Elf_Auxinfo), 309 SBUF_FIXEDLEN); 310 sbuf_set_drain(sb, sbuf_count_drain, &size); 311 PHOLD(p); 312 proc_getauxv(curthread, p, sb); 313 PRELE(p); 314 sbuf_finish(sb); 315 sbuf_delete(sb); 316 *sizep = size; 317 } else { 318 PHOLD(p); 319 proc_getauxv(curthread, p, sb); 320 PRELE(p); 321 } 322 } 323 324 /* 325 * Copy strings out to the new process address space, constructing new arg 326 * and env vector tables. Return a pointer to the base so that it can be used 327 * as the initial stack pointer. 328 */ 329 int 330 __linuxN(copyout_strings)(struct image_params *imgp, uintptr_t *stack_base) 331 { 332 char canary[LINUX_AT_RANDOM_LEN]; 333 char **vectp; 334 char *stringp; 335 uintptr_t destp, ustringp; 336 struct ps_strings *arginfo; 337 struct proc *p; 338 size_t execpath_len; 339 int argc, envc; 340 int error; 341 342 p = imgp->proc; 343 destp = PROC_PS_STRINGS(p); 344 arginfo = imgp->ps_strings = (void *)destp; 345 346 /* 347 * Copy the image path for the rtld. 348 */ 349 if (imgp->execpath != NULL && imgp->auxargs != NULL) { 350 execpath_len = strlen(imgp->execpath) + 1; 351 destp -= execpath_len; 352 destp = rounddown2(destp, sizeof(void *)); 353 imgp->execpathp = (void *)destp; 354 error = copyout(imgp->execpath, imgp->execpathp, execpath_len); 355 if (error != 0) 356 return (error); 357 } 358 359 /* 360 * Prepare the canary for SSP. 361 */ 362 arc4rand(canary, sizeof(canary), 0); 363 destp -= sizeof(canary); 364 imgp->canary = (void *)destp; 365 error = copyout(canary, imgp->canary, sizeof(canary)); 366 if (error != 0) 367 return (error); 368 imgp->canarylen = sizeof(canary); 369 370 /* 371 * Allocate room for the argument and environment strings. 372 */ 373 destp -= ARG_MAX - imgp->args->stringspace; 374 destp = rounddown2(destp, sizeof(void *)); 375 ustringp = destp; 376 377 if (imgp->auxargs) { 378 /* 379 * Allocate room on the stack for the ELF auxargs 380 * array. It has up to LINUX_AT_COUNT entries. 381 */ 382 destp -= LINUX_AT_COUNT * sizeof(Elf_Auxinfo); 383 destp = rounddown2(destp, sizeof(void *)); 384 } 385 386 vectp = (char **)destp; 387 388 /* 389 * Allocate room for the argv[] and env vectors including the 390 * terminating NULL pointers. 391 */ 392 vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; 393 394 /* 395 * Starting with 2.24, glibc depends on a 16-byte stack alignment. 396 */ 397 vectp = (char **)((((uintptr_t)vectp + 8) & ~0xF) - 8); 398 399 /* 400 * vectp also becomes our initial stack base 401 */ 402 *stack_base = (uintptr_t)vectp; 403 404 stringp = imgp->args->begin_argv; 405 argc = imgp->args->argc; 406 envc = imgp->args->envc; 407 408 /* 409 * Copy out strings - arguments and environment. 410 */ 411 error = copyout(stringp, (void *)ustringp, 412 ARG_MAX - imgp->args->stringspace); 413 if (error != 0) 414 return (error); 415 416 /* 417 * Fill in "ps_strings" struct for ps, w, etc. 418 */ 419 imgp->argv = vectp; 420 if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || 421 suword32(&arginfo->ps_nargvstr, argc) != 0) 422 return (EFAULT); 423 424 /* 425 * Fill in argument portion of vector table. 426 */ 427 for (; argc > 0; --argc) { 428 if (suword(vectp++, ustringp) != 0) 429 return (EFAULT); 430 while (*stringp++ != 0) 431 ustringp++; 432 ustringp++; 433 } 434 435 /* a null vector table pointer separates the argp's from the envp's */ 436 if (suword(vectp++, 0) != 0) 437 return (EFAULT); 438 439 imgp->envv = vectp; 440 if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || 441 suword32(&arginfo->ps_nenvstr, envc) != 0) 442 return (EFAULT); 443 444 /* 445 * Fill in environment portion of vector table. 446 */ 447 for (; envc > 0; --envc) { 448 if (suword(vectp++, ustringp) != 0) 449 return (EFAULT); 450 while (*stringp++ != 0) 451 ustringp++; 452 ustringp++; 453 } 454 455 /* end of vector table is a null pointer */ 456 if (suword(vectp, 0) != 0) 457 return (EFAULT); 458 459 if (imgp->auxargs) { 460 vectp++; 461 error = imgp->sysent->sv_copyout_auxargs(imgp, 462 (uintptr_t)vectp); 463 if (error != 0) 464 return (error); 465 } 466 467 return (0); 468 } 469 470 bool 471 linux_trans_osrel(const Elf_Note *note, int32_t *osrel) 472 { 473 const Elf32_Word *desc; 474 uintptr_t p; 475 476 p = (uintptr_t)(note + 1); 477 p += roundup2(note->n_namesz, sizeof(Elf32_Addr)); 478 479 desc = (const Elf32_Word *)p; 480 if (desc[0] != GNU_ABI_LINUX) 481 return (false); 482 /* 483 * For Linux we encode osrel using the Linux convention of 484 * (version << 16) | (major << 8) | (minor) 485 * See macro in linux_mib.h 486 */ 487 *osrel = LINUX_KERNVER(desc[1], desc[2], desc[3]); 488 489 return (true); 490 } 491 492 int 493 __linuxN(copyout_auxargs)(struct image_params *imgp, uintptr_t base) 494 { 495 Elf_Auxargs *args; 496 Elf_Auxinfo *aarray, *pos; 497 struct proc *p; 498 int error, issetugid; 499 500 p = imgp->proc; 501 issetugid = p->p_flag & P_SUGID ? 1 : 0; 502 args = imgp->auxargs; 503 aarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, 504 M_WAITOK | M_ZERO); 505 506 __linuxN(arch_copyout_auxargs)(imgp, &pos); 507 /* 508 * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0, 509 * as it has appeared in the 2.4.0-rc7 first time. 510 * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK), 511 * glibc falls back to the hard-coded CLK_TCK value when aux entry 512 * is not present. 513 * Also see linux_times() implementation. 514 */ 515 if (linux_kernver(curthread) >= LINUX_KERNVER_2004000) 516 AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz); 517 AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 518 AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 519 AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 520 AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 521 AUXARGS_ENTRY(pos, AT_BASE, args->base); 522 AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 523 AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 524 AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); 525 AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); 526 AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); 527 AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); 528 AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid); 529 if (p->p_osrel >= LINUX_KERNVER_2006030 || p->p_osrel == 0) 530 AUXARGS_ENTRY_PTR(pos, LINUX_AT_RANDOM, imgp->canary); 531 if ((p->p_osrel >= LINUX_KERNVER_2006026 || p->p_osrel == 0) && 532 imgp->execpathp != 0) 533 AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, PTROUT(imgp->execpathp)); 534 if (args->execfd != -1) 535 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 536 if (p->p_osrel >= LINUX_KERNVER_5013000 || p->p_osrel == 0) 537 AUXARGS_ENTRY(pos, LINUX_AT_MINSIGSTKSZ, 538 imgp->sysent->sv_minsigstksz); 539 AUXARGS_ENTRY(pos, AT_NULL, 0); 540 541 free(imgp->auxargs, M_TEMP); 542 imgp->auxargs = NULL; 543 KASSERT(pos - aarray <= LINUX_AT_COUNT, ("Too many auxargs")); 544 545 error = copyout(aarray, PTRIN(base), sizeof(*aarray) * LINUX_AT_COUNT); 546 free(aarray, M_TEMP); 547 return (error); 548 } 549