17cf8b4b9SBjoern A. Zeeb /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni *
47cf8b4b9SBjoern A. Zeeb * Copyright (c) 2009 Robert N. M. Watson
57cf8b4b9SBjoern A. Zeeb * Copyright (c) 2009 Bjoern A. Zeeb <bz@FreeBSD.org>
67cf8b4b9SBjoern A. Zeeb * All rights reserved.
77cf8b4b9SBjoern A. Zeeb *
87cf8b4b9SBjoern A. Zeeb * Redistribution and use in source and binary forms, with or without
97cf8b4b9SBjoern A. Zeeb * modification, are permitted provided that the following conditions
107cf8b4b9SBjoern A. Zeeb * are met:
117cf8b4b9SBjoern A. Zeeb * 1. Redistributions of source code must retain the above copyright
127cf8b4b9SBjoern A. Zeeb * notice, this list of conditions and the following disclaimer.
137cf8b4b9SBjoern A. Zeeb * 2. Redistributions in binary form must reproduce the above copyright
147cf8b4b9SBjoern A. Zeeb * notice, this list of conditions and the following disclaimer in the
157cf8b4b9SBjoern A. Zeeb * documentation and/or other materials provided with the distribution.
167cf8b4b9SBjoern A. Zeeb *
177cf8b4b9SBjoern A. Zeeb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
187cf8b4b9SBjoern A. Zeeb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
197cf8b4b9SBjoern A. Zeeb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
207cf8b4b9SBjoern A. Zeeb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
217cf8b4b9SBjoern A. Zeeb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
227cf8b4b9SBjoern A. Zeeb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
237cf8b4b9SBjoern A. Zeeb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
247cf8b4b9SBjoern A. Zeeb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
257cf8b4b9SBjoern A. Zeeb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
267cf8b4b9SBjoern A. Zeeb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
277cf8b4b9SBjoern A. Zeeb * SUCH DAMAGE.
287cf8b4b9SBjoern A. Zeeb */
297cf8b4b9SBjoern A. Zeeb
307cf8b4b9SBjoern A. Zeeb #include <sys/param.h>
317cf8b4b9SBjoern A. Zeeb
327cf8b4b9SBjoern A. Zeeb #define _WANT_PRISON
337cf8b4b9SBjoern A. Zeeb #define _WANT_UCRED
347cf8b4b9SBjoern A. Zeeb #define _WANT_VNET
357cf8b4b9SBjoern A. Zeeb
367cf8b4b9SBjoern A. Zeeb #include <sys/_lock.h>
377cf8b4b9SBjoern A. Zeeb #include <sys/_mutex.h>
387cf8b4b9SBjoern A. Zeeb #include <sys/_task.h>
397cf8b4b9SBjoern A. Zeeb #include <sys/jail.h>
407cf8b4b9SBjoern A. Zeeb #include <sys/proc.h>
417cf8b4b9SBjoern A. Zeeb #include <sys/types.h>
427cf8b4b9SBjoern A. Zeeb
4310108cb6SBjoern A. Zeeb #include <stdbool.h>
447cf8b4b9SBjoern A. Zeeb #include <net/vnet.h>
457cf8b4b9SBjoern A. Zeeb
467cf8b4b9SBjoern A. Zeeb #include <kvm.h>
477cf8b4b9SBjoern A. Zeeb #include <limits.h>
487cf8b4b9SBjoern A. Zeeb #include <stdlib.h>
497cf8b4b9SBjoern A. Zeeb #include <unistd.h>
507cf8b4b9SBjoern A. Zeeb
517cf8b4b9SBjoern A. Zeeb #include "kvm_private.h"
527cf8b4b9SBjoern A. Zeeb
537cf8b4b9SBjoern A. Zeeb /*
547cf8b4b9SBjoern A. Zeeb * Set up libkvm to handle virtual network stack symbols by selecting a
557cf8b4b9SBjoern A. Zeeb * starting pid.
567cf8b4b9SBjoern A. Zeeb */
577cf8b4b9SBjoern A. Zeeb int
_kvm_vnet_selectpid(kvm_t * kd,pid_t pid)587cf8b4b9SBjoern A. Zeeb _kvm_vnet_selectpid(kvm_t *kd, pid_t pid)
597cf8b4b9SBjoern A. Zeeb {
607cf8b4b9SBjoern A. Zeeb struct proc proc;
617cf8b4b9SBjoern A. Zeeb struct ucred cred;
627cf8b4b9SBjoern A. Zeeb struct prison prison;
637cf8b4b9SBjoern A. Zeeb struct vnet vnet;
647f911abeSJohn Baldwin struct kvm_nlist nl[] = {
657cf8b4b9SBjoern A. Zeeb /*
667cf8b4b9SBjoern A. Zeeb * Note: kvm_nlist strips the first '_' so add an extra one
677cf8b4b9SBjoern A. Zeeb * here to __{start,stop}_set_vnet.
687cf8b4b9SBjoern A. Zeeb */
697cf8b4b9SBjoern A. Zeeb #define NLIST_START_VNET 0
707cf8b4b9SBjoern A. Zeeb { .n_name = "___start_" VNET_SETNAME },
717cf8b4b9SBjoern A. Zeeb #define NLIST_STOP_VNET 1
727cf8b4b9SBjoern A. Zeeb { .n_name = "___stop_" VNET_SETNAME },
737cf8b4b9SBjoern A. Zeeb #define NLIST_VNET_HEAD 2
747cf8b4b9SBjoern A. Zeeb { .n_name = "vnet_head" },
757cf8b4b9SBjoern A. Zeeb #define NLIST_ALLPROC 3
767cf8b4b9SBjoern A. Zeeb { .n_name = "allproc" },
777cf8b4b9SBjoern A. Zeeb #define NLIST_DUMPTID 4
787cf8b4b9SBjoern A. Zeeb { .n_name = "dumptid" },
797cf8b4b9SBjoern A. Zeeb #define NLIST_PROC0 5
807cf8b4b9SBjoern A. Zeeb { .n_name = "proc0" },
817cf8b4b9SBjoern A. Zeeb { .n_name = NULL },
827cf8b4b9SBjoern A. Zeeb };
83c10970ddSUlrich Spörlein uintptr_t procp, credp;
84c10970ddSUlrich Spörlein #define VMCORE_VNET_OF_PROC0
85c10970ddSUlrich Spörlein #ifndef VMCORE_VNET_OF_PROC0
86c10970ddSUlrich Spörlein struct thread td;
87c10970ddSUlrich Spörlein uintptr_t tdp;
88c10970ddSUlrich Spörlein #endif
897cf8b4b9SBjoern A. Zeeb lwpid_t dumptid;
907cf8b4b9SBjoern A. Zeeb
917cf8b4b9SBjoern A. Zeeb /*
927f911abeSJohn Baldwin * XXX: This only works for native kernels for now.
937f911abeSJohn Baldwin */
947f911abeSJohn Baldwin if (!kvm_native(kd))
957f911abeSJohn Baldwin return (-1);
967f911abeSJohn Baldwin
977f911abeSJohn Baldwin /*
987cf8b4b9SBjoern A. Zeeb * Locate and cache locations of important symbols
997cf8b4b9SBjoern A. Zeeb * using the internal version of _kvm_nlist, turning
1007cf8b4b9SBjoern A. Zeeb * off initialization to avoid recursion in case of
1017cf8b4b9SBjoern A. Zeeb * unresolveable symbols.
1027cf8b4b9SBjoern A. Zeeb */
1037cf8b4b9SBjoern A. Zeeb if (_kvm_nlist(kd, nl, 0) != 0) {
1047cf8b4b9SBjoern A. Zeeb /*
1057cf8b4b9SBjoern A. Zeeb * XXX-BZ: ___start_/___stop_VNET_SETNAME may fail.
1067cf8b4b9SBjoern A. Zeeb * For now do not report an error here as we are called
1077cf8b4b9SBjoern A. Zeeb * internally and in `void context' until we merge the
1087cf8b4b9SBjoern A. Zeeb * functionality to optionally activate this into programs.
1097cf8b4b9SBjoern A. Zeeb * By that time we can properly fail and let the callers
1107cf8b4b9SBjoern A. Zeeb * handle the error.
1117cf8b4b9SBjoern A. Zeeb */
1127cf8b4b9SBjoern A. Zeeb /* _kvm_err(kd, kd->program, "%s: no namelist", __func__); */
1137cf8b4b9SBjoern A. Zeeb return (-1);
1147cf8b4b9SBjoern A. Zeeb }
1157cf8b4b9SBjoern A. Zeeb
1167cf8b4b9SBjoern A. Zeeb /*
1177cf8b4b9SBjoern A. Zeeb * Auto-detect if this is a crashdump by reading dumptid.
1187cf8b4b9SBjoern A. Zeeb */
1197cf8b4b9SBjoern A. Zeeb dumptid = 0;
1207cf8b4b9SBjoern A. Zeeb if (nl[NLIST_DUMPTID].n_value) {
1217cf8b4b9SBjoern A. Zeeb if (kvm_read(kd, nl[NLIST_DUMPTID].n_value, &dumptid,
1227cf8b4b9SBjoern A. Zeeb sizeof(dumptid)) != sizeof(dumptid)) {
1237cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: dumptid", __func__);
1247cf8b4b9SBjoern A. Zeeb return (-1);
1257cf8b4b9SBjoern A. Zeeb }
1267cf8b4b9SBjoern A. Zeeb }
1277cf8b4b9SBjoern A. Zeeb
1287cf8b4b9SBjoern A. Zeeb /*
129f0506e89SRobert Watson * First, find the process for this pid. If we are working on a
13075f46cf6SPedro F. Giffuni * dump, either locate the thread dumptid is referring to or proc0.
1317cf8b4b9SBjoern A. Zeeb * Based on either, take the address of the ucred.
1327cf8b4b9SBjoern A. Zeeb */
1337cf8b4b9SBjoern A. Zeeb credp = 0;
1347cf8b4b9SBjoern A. Zeeb
1357cf8b4b9SBjoern A. Zeeb procp = nl[NLIST_ALLPROC].n_value;
1367cf8b4b9SBjoern A. Zeeb #ifdef VMCORE_VNET_OF_PROC0
1377cf8b4b9SBjoern A. Zeeb if (dumptid > 0) {
1387cf8b4b9SBjoern A. Zeeb procp = nl[NLIST_PROC0].n_value;
1397cf8b4b9SBjoern A. Zeeb pid = 0;
1407cf8b4b9SBjoern A. Zeeb }
1417cf8b4b9SBjoern A. Zeeb #endif
1427cf8b4b9SBjoern A. Zeeb while (procp != 0) {
1437cf8b4b9SBjoern A. Zeeb if (kvm_read(kd, procp, &proc, sizeof(proc)) != sizeof(proc)) {
1447cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: proc", __func__);
1457cf8b4b9SBjoern A. Zeeb return (-1);
1467cf8b4b9SBjoern A. Zeeb }
1477cf8b4b9SBjoern A. Zeeb #ifndef VMCORE_VNET_OF_PROC0
1487cf8b4b9SBjoern A. Zeeb if (dumptid > 0) {
1497cf8b4b9SBjoern A. Zeeb tdp = (uintptr_t)TAILQ_FIRST(&proc.p_threads);
1507cf8b4b9SBjoern A. Zeeb while (tdp != 0) {
1517cf8b4b9SBjoern A. Zeeb if (kvm_read(kd, tdp, &td, sizeof(td)) !=
1527cf8b4b9SBjoern A. Zeeb sizeof(td)) {
1537cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: thread",
1547cf8b4b9SBjoern A. Zeeb __func__);
1557cf8b4b9SBjoern A. Zeeb return (-1);
1567cf8b4b9SBjoern A. Zeeb }
1577cf8b4b9SBjoern A. Zeeb if (td.td_tid == dumptid) {
1587cf8b4b9SBjoern A. Zeeb credp = (uintptr_t)td.td_ucred;
1597cf8b4b9SBjoern A. Zeeb break;
1607cf8b4b9SBjoern A. Zeeb }
1617cf8b4b9SBjoern A. Zeeb tdp = (uintptr_t)TAILQ_NEXT(&td, td_plist);
1627cf8b4b9SBjoern A. Zeeb }
1637cf8b4b9SBjoern A. Zeeb } else
1647cf8b4b9SBjoern A. Zeeb #endif
1657cf8b4b9SBjoern A. Zeeb if (proc.p_pid == pid)
1667cf8b4b9SBjoern A. Zeeb credp = (uintptr_t)proc.p_ucred;
1677cf8b4b9SBjoern A. Zeeb if (credp != 0)
1687cf8b4b9SBjoern A. Zeeb break;
1697cf8b4b9SBjoern A. Zeeb procp = (uintptr_t)LIST_NEXT(&proc, p_list);
1707cf8b4b9SBjoern A. Zeeb }
1717cf8b4b9SBjoern A. Zeeb if (credp == 0) {
1727cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: pid/tid not found", __func__);
1737cf8b4b9SBjoern A. Zeeb return (-1);
1747cf8b4b9SBjoern A. Zeeb }
1757cf8b4b9SBjoern A. Zeeb if (kvm_read(kd, (uintptr_t)credp, &cred, sizeof(cred)) !=
1767cf8b4b9SBjoern A. Zeeb sizeof(cred)) {
1777cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: cred", __func__);
1787cf8b4b9SBjoern A. Zeeb return (-1);
1797cf8b4b9SBjoern A. Zeeb }
1807cf8b4b9SBjoern A. Zeeb if (cred.cr_prison == NULL) {
1817cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: no jail", __func__);
1827cf8b4b9SBjoern A. Zeeb return (-1);
1837cf8b4b9SBjoern A. Zeeb }
1847cf8b4b9SBjoern A. Zeeb if (kvm_read(kd, (uintptr_t)cred.cr_prison, &prison, sizeof(prison)) !=
1857cf8b4b9SBjoern A. Zeeb sizeof(prison)) {
1867cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: prison", __func__);
1877cf8b4b9SBjoern A. Zeeb return (-1);
1887cf8b4b9SBjoern A. Zeeb }
1897cf8b4b9SBjoern A. Zeeb if (prison.pr_vnet == NULL) {
1907cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: no vnet", __func__);
1917cf8b4b9SBjoern A. Zeeb return (-1);
1927cf8b4b9SBjoern A. Zeeb }
1937cf8b4b9SBjoern A. Zeeb if (kvm_read(kd, (uintptr_t)prison.pr_vnet, &vnet, sizeof(vnet)) !=
1947cf8b4b9SBjoern A. Zeeb sizeof(vnet)) {
1957cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: vnet", __func__);
1967cf8b4b9SBjoern A. Zeeb return (-1);
1977cf8b4b9SBjoern A. Zeeb }
1987cf8b4b9SBjoern A. Zeeb if (vnet.vnet_magic_n != VNET_MAGIC_N) {
1997cf8b4b9SBjoern A. Zeeb _kvm_err(kd, kd->program, "%s: invalid vnet magic#", __func__);
2007cf8b4b9SBjoern A. Zeeb return (-1);
2017cf8b4b9SBjoern A. Zeeb }
2027cf8b4b9SBjoern A. Zeeb kd->vnet_initialized = 1;
2037cf8b4b9SBjoern A. Zeeb kd->vnet_start = nl[NLIST_START_VNET].n_value;
2047cf8b4b9SBjoern A. Zeeb kd->vnet_stop = nl[NLIST_STOP_VNET].n_value;
2057cf8b4b9SBjoern A. Zeeb kd->vnet_current = (uintptr_t)prison.pr_vnet;
20687a61ebdSBjoern A. Zeeb kd->vnet_base = vnet.vnet_data_base;
2077cf8b4b9SBjoern A. Zeeb return (0);
2087cf8b4b9SBjoern A. Zeeb }
2097cf8b4b9SBjoern A. Zeeb
2107cf8b4b9SBjoern A. Zeeb /*
21175f46cf6SPedro F. Giffuni * Check whether the vnet module has been initialized successfully
2127f911abeSJohn Baldwin * or not, initialize it if permitted.
2137cf8b4b9SBjoern A. Zeeb */
2147cf8b4b9SBjoern A. Zeeb int
_kvm_vnet_initialized(kvm_t * kd,int intialize)2157cf8b4b9SBjoern A. Zeeb _kvm_vnet_initialized(kvm_t *kd, int intialize)
2167cf8b4b9SBjoern A. Zeeb {
2177cf8b4b9SBjoern A. Zeeb
2187cf8b4b9SBjoern A. Zeeb if (kd->vnet_initialized || !intialize)
2197cf8b4b9SBjoern A. Zeeb return (kd->vnet_initialized);
2207cf8b4b9SBjoern A. Zeeb
2217cf8b4b9SBjoern A. Zeeb (void) _kvm_vnet_selectpid(kd, getpid());
2227cf8b4b9SBjoern A. Zeeb
2237cf8b4b9SBjoern A. Zeeb return (kd->vnet_initialized);
2247cf8b4b9SBjoern A. Zeeb }
2257cf8b4b9SBjoern A. Zeeb
2267cf8b4b9SBjoern A. Zeeb /*
2277cf8b4b9SBjoern A. Zeeb * Check whether the value is within the vnet symbol range and
2287cf8b4b9SBjoern A. Zeeb * only if so adjust the offset relative to the current base.
2297cf8b4b9SBjoern A. Zeeb */
2307f911abeSJohn Baldwin kvaddr_t
_kvm_vnet_validaddr(kvm_t * kd,kvaddr_t value)2317f911abeSJohn Baldwin _kvm_vnet_validaddr(kvm_t *kd, kvaddr_t value)
2327cf8b4b9SBjoern A. Zeeb {
2337cf8b4b9SBjoern A. Zeeb
2347cf8b4b9SBjoern A. Zeeb if (value == 0)
2357cf8b4b9SBjoern A. Zeeb return (value);
2367cf8b4b9SBjoern A. Zeeb
2377cf8b4b9SBjoern A. Zeeb if (!kd->vnet_initialized)
2387cf8b4b9SBjoern A. Zeeb return (value);
2397cf8b4b9SBjoern A. Zeeb
2407cf8b4b9SBjoern A. Zeeb if (value < kd->vnet_start || value >= kd->vnet_stop)
2417cf8b4b9SBjoern A. Zeeb return (value);
2427cf8b4b9SBjoern A. Zeeb
2437cf8b4b9SBjoern A. Zeeb return (kd->vnet_base + value);
2447cf8b4b9SBjoern A. Zeeb }
245