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