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