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 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <fcntl.h> 33 #include <string.h> 34 #include <limits.h> 35 36 #include "Pcontrol.h" 37 38 /* 39 * These several routines simply get the indicated /proc structures 40 * for a process identified by process ID. They are convenience 41 * functions for one-time operations. They do the mechanics of 42 * open() / read() / close() of the necessary /proc files so the 43 * caller's code can look relatively less cluttered. 44 */ 45 46 /* 47 * 'ngroups' is the number of supplementary group entries allocated in 48 * the caller's cred structure. It should equal zero or one unless extra 49 * space has been allocated for the group list by the caller, like this: 50 * credp = malloc(sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t)); 51 */ 52 int 53 proc_get_cred(pid_t pid, prcred_t *credp, int ngroups) 54 { 55 char fname[PATH_MAX]; 56 int fd; 57 int rv = -1; 58 ssize_t minsize = sizeof (*credp) - sizeof (gid_t); 59 size_t size = minsize + ngroups * sizeof (gid_t); 60 61 (void) snprintf(fname, sizeof (fname), "%s/%d/cred", 62 procfs_path, (int)pid); 63 if ((fd = open(fname, O_RDONLY)) >= 0) { 64 if (read(fd, credp, size) >= minsize) 65 rv = 0; 66 (void) close(fd); 67 } 68 return (rv); 69 } 70 71 void 72 proc_free_priv(prpriv_t *prv) 73 { 74 free(prv); 75 } 76 77 /* 78 * Malloc and return a properly sized structure. 79 */ 80 prpriv_t * 81 proc_get_priv(pid_t pid) 82 { 83 char fname[PATH_MAX]; 84 int fd; 85 struct stat statb; 86 prpriv_t *rv = NULL; 87 88 (void) snprintf(fname, sizeof (fname), "%s/%d/priv", 89 procfs_path, (int)pid); 90 if ((fd = open(fname, O_RDONLY)) >= 0) { 91 if (fstat(fd, &statb) != 0 || 92 (rv = malloc(statb.st_size)) == NULL || 93 read(fd, rv, statb.st_size) != statb.st_size) { 94 free(rv); 95 rv = NULL; 96 } 97 (void) close(fd); 98 } 99 return (rv); 100 } 101 102 #if defined(__i386) || defined(__amd64) 103 /* 104 * Fill in a pointer to a process LDT structure. 105 * The caller provides a buffer of size 'nldt * sizeof (struct ssd)'; 106 * If pldt == NULL or nldt == 0, we return the number of existing LDT entries. 107 * Otherwise we return the actual number of LDT entries fetched (<= nldt). 108 */ 109 int 110 proc_get_ldt(pid_t pid, struct ssd *pldt, int nldt) 111 { 112 char fname[PATH_MAX]; 113 int fd; 114 struct stat statb; 115 size_t size; 116 ssize_t ssize; 117 118 (void) snprintf(fname, sizeof (fname), "%s/%d/ldt", 119 procfs_path, (int)pid); 120 if ((fd = open(fname, O_RDONLY)) < 0) 121 return (-1); 122 123 if (pldt == NULL || nldt == 0) { 124 nldt = 0; 125 if (fstat(fd, &statb) == 0) 126 nldt = statb.st_size / sizeof (struct ssd); 127 (void) close(fd); 128 return (nldt); 129 } 130 131 size = nldt * sizeof (struct ssd); 132 if ((ssize = read(fd, pldt, size)) < 0) 133 nldt = -1; 134 else 135 nldt = ssize / sizeof (struct ssd); 136 137 (void) close(fd); 138 return (nldt); 139 } 140 #endif /* __i386 || __amd64 */ 141 142 int 143 proc_get_psinfo(pid_t pid, psinfo_t *psp) 144 { 145 char fname[PATH_MAX]; 146 int fd; 147 int rv = -1; 148 149 (void) snprintf(fname, sizeof (fname), "%s/%d/psinfo", 150 procfs_path, (int)pid); 151 if ((fd = open(fname, O_RDONLY)) >= 0) { 152 if (read(fd, psp, sizeof (*psp)) == sizeof (*psp)) 153 rv = 0; 154 (void) close(fd); 155 } 156 return (rv); 157 } 158 159 int 160 proc_get_status(pid_t pid, pstatus_t *psp) 161 { 162 char fname[PATH_MAX]; 163 int fd; 164 int rv = -1; 165 166 (void) snprintf(fname, sizeof (fname), "%s/%d/status", 167 procfs_path, (int)pid); 168 if ((fd = open(fname, O_RDONLY)) >= 0) { 169 if (read(fd, psp, sizeof (*psp)) == sizeof (*psp)) 170 rv = 0; 171 (void) close(fd); 172 } 173 return (rv); 174 } 175 176 /* 177 * Get the process's aux vector. 178 * 'naux' is the number of aux entries in the caller's buffer. 179 * We return the number of aux entries actually fetched from 180 * the process (less than or equal to 'naux') or -1 on failure. 181 */ 182 int 183 proc_get_auxv(pid_t pid, auxv_t *pauxv, int naux) 184 { 185 char fname[PATH_MAX]; 186 int fd; 187 int rv = -1; 188 189 (void) snprintf(fname, sizeof (fname), "%s/%d/auxv", 190 procfs_path, (int)pid); 191 if ((fd = open(fname, O_RDONLY)) >= 0) { 192 if ((rv = read(fd, pauxv, naux * sizeof (auxv_t))) >= 0) 193 rv /= sizeof (auxv_t); 194 (void) close(fd); 195 } 196 return (rv); 197 }