xref: /freebsd/sys/compat/linux/linux_elf.c (revision 7ef62cebc2f965b0f640263e179276928885e33d)
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 	struct thread *td = curthread;
496 	Elf_Auxargs *args;
497 	Elf_Auxinfo *aarray, *pos;
498 	struct proc *p;
499 	int error, issetugid;
500 
501 	p = imgp->proc;
502 	issetugid = p->p_flag & P_SUGID ? 1 : 0;
503 	args = imgp->auxargs;
504 	aarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
505 	    M_WAITOK | M_ZERO);
506 
507 	__linuxN(arch_copyout_auxargs)(imgp, &pos);
508 	/*
509 	 * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0,
510 	 * as it has appeared in the 2.4.0-rc7 first time.
511 	 * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK),
512 	 * glibc falls back to the hard-coded CLK_TCK value when aux entry
513 	 * is not present.
514 	 * Also see linux_times() implementation.
515 	 */
516 	if (linux_kernver(td) >= LINUX_KERNVER(2,4,0))
517 		AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz);
518 	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
519 	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
520 	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
521 	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
522 	AUXARGS_ENTRY(pos, AT_BASE, args->base);
523 	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
524 	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
525 	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
526 	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
527 	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
528 	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
529 	AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid);
530 	if (linux_kernver(td) >= LINUX_KERNVER(2,6,30))
531 		AUXARGS_ENTRY_PTR(pos, LINUX_AT_RANDOM, imgp->canary);
532 	if (linux_kernver(td) >= LINUX_KERNVER(2,6,26) && 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 (linux_kernver(td) >= LINUX_KERNVER(5,13,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