1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright 2015, Joyent, Inc. 27 * Copyright 2023 Oxide Computer Company 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <fcntl.h> 34 #include <string.h> 35 #include <limits.h> 36 #include <sys/secflags.h> 37 38 #include "Pcontrol.h" 39 40 /* 41 * These several routines simply get the indicated /proc structures 42 * for a process identified by process ID. They are convenience 43 * functions for one-time operations. They do the mechanics of 44 * open() / read() / close() of the necessary /proc files so the 45 * caller's code can look relatively less cluttered. 46 */ 47 48 /* 49 * 'ngroups' is the number of supplementary group entries allocated in 50 * the caller's cred structure. It should equal zero or one unless extra 51 * space has been allocated for the group list by the caller, like this: 52 * credp = malloc(sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t)); 53 */ 54 int 55 proc_get_cred(pid_t pid, prcred_t *credp, int ngroups) 56 { 57 char fname[PATH_MAX]; 58 int fd; 59 int rv = -1; 60 ssize_t minsize = sizeof (*credp) - sizeof (gid_t); 61 size_t size = minsize + ngroups * sizeof (gid_t); 62 63 (void) snprintf(fname, sizeof (fname), "%s/%d/cred", 64 procfs_path, (int)pid); 65 if ((fd = open(fname, O_RDONLY)) >= 0) { 66 if (read(fd, credp, size) >= minsize) 67 rv = 0; 68 (void) close(fd); 69 } 70 return (rv); 71 } 72 73 int 74 proc_get_secflags(pid_t pid, prsecflags_t **psf) 75 { 76 char fname[PATH_MAX]; 77 int fd; 78 int rv = -1; 79 80 if ((*psf = calloc(1, sizeof (prsecflags_t))) == NULL) 81 return (-1); 82 83 (void) snprintf(fname, sizeof (fname), "%s/%d/secflags", 84 procfs_path, (int)pid); 85 if ((fd = open(fname, O_RDONLY)) >= 0) { 86 if (read(fd, *psf, sizeof (prsecflags_t)) == 87 sizeof (prsecflags_t)) 88 rv = 0; 89 (void) close(fd); 90 } 91 return (rv); 92 } 93 94 void 95 proc_free_priv(prpriv_t *prv) 96 { 97 free(prv); 98 } 99 100 /* 101 * Malloc and return a properly sized structure. 102 */ 103 prpriv_t * 104 proc_get_priv(pid_t pid) 105 { 106 char fname[PATH_MAX]; 107 int fd; 108 struct stat statb; 109 prpriv_t *rv = NULL; 110 111 (void) snprintf(fname, sizeof (fname), "%s/%d/priv", 112 procfs_path, (int)pid); 113 if ((fd = open(fname, O_RDONLY)) >= 0) { 114 if (fstat(fd, &statb) != 0 || 115 (rv = malloc(statb.st_size)) == NULL || 116 read(fd, rv, statb.st_size) != statb.st_size) { 117 free(rv); 118 rv = NULL; 119 } 120 (void) close(fd); 121 } 122 return (rv); 123 } 124 125 #if defined(__i386) || defined(__amd64) 126 /* 127 * Fill in a pointer to a process LDT structure. 128 * The caller provides a buffer of size 'nldt * sizeof (struct ssd)'; 129 * If pldt == NULL or nldt == 0, we return the number of existing LDT entries. 130 * Otherwise we return the actual number of LDT entries fetched (<= nldt). 131 */ 132 int 133 proc_get_ldt(pid_t pid, struct ssd *pldt, int nldt) 134 { 135 char fname[PATH_MAX]; 136 int fd; 137 struct stat statb; 138 size_t size; 139 ssize_t ssize; 140 141 (void) snprintf(fname, sizeof (fname), "%s/%d/ldt", 142 procfs_path, (int)pid); 143 if ((fd = open(fname, O_RDONLY)) < 0) 144 return (-1); 145 146 if (pldt == NULL || nldt == 0) { 147 nldt = 0; 148 if (fstat(fd, &statb) == 0) 149 nldt = statb.st_size / sizeof (struct ssd); 150 (void) close(fd); 151 return (nldt); 152 } 153 154 size = nldt * sizeof (struct ssd); 155 if ((ssize = read(fd, pldt, size)) < 0) 156 nldt = -1; 157 else 158 nldt = ssize / sizeof (struct ssd); 159 160 (void) close(fd); 161 return (nldt); 162 } 163 #endif /* __i386 || __amd64 */ 164 165 int 166 proc_get_psinfo(pid_t pid, psinfo_t *psp) 167 { 168 char fname[PATH_MAX]; 169 int fd; 170 int rv = -1; 171 172 (void) snprintf(fname, sizeof (fname), "%s/%d/psinfo", 173 procfs_path, (int)pid); 174 if ((fd = open(fname, O_RDONLY)) >= 0) { 175 if (read(fd, psp, sizeof (*psp)) == sizeof (*psp)) 176 rv = 0; 177 (void) close(fd); 178 } 179 return (rv); 180 } 181 182 int 183 proc_get_status(pid_t pid, pstatus_t *psp) 184 { 185 char fname[PATH_MAX]; 186 int fd; 187 int rv = -1; 188 189 (void) snprintf(fname, sizeof (fname), "%s/%d/status", 190 procfs_path, (int)pid); 191 if ((fd = open(fname, O_RDONLY)) >= 0) { 192 if (read(fd, psp, sizeof (*psp)) == sizeof (*psp)) 193 rv = 0; 194 (void) close(fd); 195 } 196 return (rv); 197 } 198 199 /* 200 * Get the process's aux vector. 201 * 'naux' is the number of aux entries in the caller's buffer. 202 * We return the number of aux entries actually fetched from 203 * the process (less than or equal to 'naux') or -1 on failure. 204 */ 205 int 206 proc_get_auxv(pid_t pid, auxv_t *pauxv, int naux) 207 { 208 char fname[PATH_MAX]; 209 int fd; 210 int rv = -1; 211 212 (void) snprintf(fname, sizeof (fname), "%s/%d/auxv", 213 procfs_path, (int)pid); 214 if ((fd = open(fname, O_RDONLY)) >= 0) { 215 if ((rv = read(fd, pauxv, naux * sizeof (auxv_t))) >= 0) 216 rv /= sizeof (auxv_t); 217 (void) close(fd); 218 } 219 return (rv); 220 } 221 222 int 223 proc_get_lwpsinfo(pid_t pid, uint_t thr, lwpsinfo_t *lwpip) 224 { 225 char fname[PATH_MAX]; 226 int fd; 227 int rv = -1; 228 229 (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%u/lwpsinfo", 230 procfs_path, (int)pid, thr); 231 if ((fd = open(fname, O_RDONLY)) >= 0) { 232 if (read(fd, lwpip, sizeof (*lwpip)) == sizeof (*lwpip)) 233 rv = 0; 234 (void) close(fd); 235 } 236 return (rv); 237 } 238 239 int 240 proc_get_lwpstatus(pid_t pid, uint_t thr, lwpstatus_t *lwp) 241 { 242 char fname[PATH_MAX]; 243 int fd; 244 int rv = -1; 245 246 (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%u/lwpstatus", 247 procfs_path, (int)pid, thr); 248 if ((fd = open(fname, O_RDONLY)) >= 0) { 249 if (read(fd, lwp, sizeof (*lwp)) == sizeof (*lwp)) 250 rv = 0; 251 (void) close(fd); 252 } 253 return (rv); 254 } 255