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