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 <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 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 130*75f46cf6SPedro 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 /* 211*75f46cf6SPedro 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 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 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