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