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