core.c (249677) | core.c (249679) |
---|---|
1/*- 2 * Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/lib/libprocstat/core.c 249677 2013-04-20 08:03:56Z trociny $ | 26 * $FreeBSD: head/lib/libprocstat/core.c 249679 2013-04-20 08:07:04Z trociny $ |
27 */ 28 29#include <sys/param.h> 30#include <sys/elf.h> | 27 */ 28 29#include <sys/param.h> 30#include <sys/elf.h> |
31#include <sys/exec.h> |
|
31#include <sys/user.h> 32 33#include <assert.h> 34#include <err.h> 35#include <fcntl.h> 36#include <gelf.h> 37#include <libelf.h> 38#include <stdbool.h> --- 12 unchanged lines hidden (view full) --- 51 int pc_fd; 52 Elf *pc_elf; 53 GElf_Ehdr pc_ehdr; 54 GElf_Phdr pc_phdr; 55}; 56 57static bool core_offset(struct procstat_core *core, off_t offset); 58static bool core_read(struct procstat_core *core, void *buf, size_t len); | 32#include <sys/user.h> 33 34#include <assert.h> 35#include <err.h> 36#include <fcntl.h> 37#include <gelf.h> 38#include <libelf.h> 39#include <stdbool.h> --- 12 unchanged lines hidden (view full) --- 52 int pc_fd; 53 Elf *pc_elf; 54 GElf_Ehdr pc_ehdr; 55 GElf_Phdr pc_phdr; 56}; 57 58static bool core_offset(struct procstat_core *core, off_t offset); 59static bool core_read(struct procstat_core *core, void *buf, size_t len); |
60static ssize_t core_read_mem(struct procstat_core *core, void *buf, 61 size_t len, vm_offset_t addr, bool readall); 62static void *get_args(struct procstat_core *core, vm_offset_t psstrings, 63 enum psc_type type, void *buf, size_t *lenp); |
|
59 60struct procstat_core * 61procstat_core_open(const char *filename) 62{ 63 struct procstat_core *core; 64 Elf *e; 65 GElf_Ehdr ehdr; 66 GElf_Phdr phdr; --- 74 unchanged lines hidden (view full) --- 141} 142 143void * 144procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf, 145 size_t *lenp) 146{ 147 Elf_Note nhdr; 148 off_t offset, eoffset; | 64 65struct procstat_core * 66procstat_core_open(const char *filename) 67{ 68 struct procstat_core *core; 69 Elf *e; 70 GElf_Ehdr ehdr; 71 GElf_Phdr phdr; --- 74 unchanged lines hidden (view full) --- 146} 147 148void * 149procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf, 150 size_t *lenp) 151{ 152 Elf_Note nhdr; 153 off_t offset, eoffset; |
154 vm_offset_t psstrings; |
|
149 void *freebuf; 150 size_t len; 151 u_int32_t n_type; 152 int cstructsize, structsize; 153 char nbuf[8]; 154 155 assert(core->pc_magic == PROCSTAT_CORE_MAGIC); 156 --- 21 unchanged lines hidden (view full) --- 178 case PSC_TYPE_RLIMIT: 179 n_type = NT_PROCSTAT_RLIMIT; 180 structsize = sizeof(struct rlimit) * RLIM_NLIMITS; 181 break; 182 case PSC_TYPE_OSREL: 183 n_type = NT_PROCSTAT_OSREL; 184 structsize = sizeof(int); 185 break; | 155 void *freebuf; 156 size_t len; 157 u_int32_t n_type; 158 int cstructsize, structsize; 159 char nbuf[8]; 160 161 assert(core->pc_magic == PROCSTAT_CORE_MAGIC); 162 --- 21 unchanged lines hidden (view full) --- 184 case PSC_TYPE_RLIMIT: 185 n_type = NT_PROCSTAT_RLIMIT; 186 structsize = sizeof(struct rlimit) * RLIM_NLIMITS; 187 break; 188 case PSC_TYPE_OSREL: 189 n_type = NT_PROCSTAT_OSREL; 190 structsize = sizeof(int); 191 break; |
192 case PSC_TYPE_PSSTRINGS: 193 case PSC_TYPE_ARGV: 194 case PSC_TYPE_ENVV: 195 n_type = NT_PROCSTAT_PSSTRINGS; 196 structsize = sizeof(vm_offset_t); 197 break; |
|
186 default: 187 warnx("unknown core stat type: %d", type); 188 return (NULL); 189 } 190 191 offset = core->pc_phdr.p_offset; 192 eoffset = offset + core->pc_phdr.p_filesz; 193 --- 39 unchanged lines hidden (view full) --- 233 warn("malloc(%zu)", len); 234 return (NULL); 235 } 236 } 237 if (!core_read(core, buf, len)) { 238 free(freebuf); 239 return (NULL); 240 } | 198 default: 199 warnx("unknown core stat type: %d", type); 200 return (NULL); 201 } 202 203 offset = core->pc_phdr.p_offset; 204 eoffset = offset + core->pc_phdr.p_filesz; 205 --- 39 unchanged lines hidden (view full) --- 245 warn("malloc(%zu)", len); 246 return (NULL); 247 } 248 } 249 if (!core_read(core, buf, len)) { 250 free(freebuf); 251 return (NULL); 252 } |
253 if (type == PSC_TYPE_ARGV || type == PSC_TYPE_ENVV) { 254 if (len < sizeof(psstrings)) { 255 free(freebuf); 256 return (NULL); 257 } 258 psstrings = *(vm_offset_t *)buf; 259 if (freebuf == NULL) 260 len = *lenp; 261 else 262 buf = NULL; 263 free(freebuf); 264 buf = get_args(core, psstrings, type, buf, &len); 265 } |
|
241 *lenp = len; 242 return (buf); 243 } 244 245 return (NULL); 246} 247 248static bool --- 22 unchanged lines hidden (view full) --- 271 return (false); 272 } 273 if (n < (ssize_t)len) { 274 warnx("core: short read"); 275 return (false); 276 } 277 return (true); 278} | 266 *lenp = len; 267 return (buf); 268 } 269 270 return (NULL); 271} 272 273static bool --- 22 unchanged lines hidden (view full) --- 296 return (false); 297 } 298 if (n < (ssize_t)len) { 299 warnx("core: short read"); 300 return (false); 301 } 302 return (true); 303} |
304 305static ssize_t 306core_read_mem(struct procstat_core *core, void *buf, size_t len, 307 vm_offset_t addr, bool readall) 308{ 309 GElf_Phdr phdr; 310 off_t offset; 311 int i; 312 313 assert(core->pc_magic == PROCSTAT_CORE_MAGIC); 314 315 for (i = 0; i < core->pc_ehdr.e_phnum; i++) { 316 if (gelf_getphdr(core->pc_elf, i, &phdr) != &phdr) { 317 warnx("gelf_getphdr: %s", elf_errmsg(-1)); 318 return (-1); 319 } 320 if (phdr.p_type != PT_LOAD) 321 continue; 322 if (addr < phdr.p_vaddr || addr > phdr.p_vaddr + phdr.p_memsz) 323 continue; 324 offset = phdr.p_offset + (addr - phdr.p_vaddr); 325 if ((phdr.p_vaddr + phdr.p_memsz) - addr < len) { 326 if (readall) { 327 warnx("format error: " 328 "attempt to read out of segment"); 329 return (-1); 330 } 331 len = (phdr.p_vaddr + phdr.p_memsz) - addr; 332 } 333 if (!core_offset(core, offset)) 334 return (-1); 335 if (!core_read(core, buf, len)) 336 return (-1); 337 return (len); 338 } 339 warnx("format error: address %ju not found", (uintmax_t)addr); 340 return (-1); 341} 342 343#define ARGS_CHUNK_SZ 256 /* Chunk size (bytes) for get_args operations. */ 344 345static void * 346get_args(struct procstat_core *core, vm_offset_t psstrings, enum psc_type type, 347 void *args, size_t *lenp) 348{ 349 struct ps_strings pss; 350 void *freeargs; 351 vm_offset_t addr; 352 char **argv, *p; 353 size_t chunksz, done, len, nchr, size; 354 ssize_t n; 355 u_int i, nstr; 356 357 assert(type == PSC_TYPE_ARGV || type == PSC_TYPE_ENVV); 358 359 if (core_read_mem(core, &pss, sizeof(pss), psstrings, true) == -1) 360 return (NULL); 361 if (type == PSC_TYPE_ARGV) { 362 addr = (vm_offset_t)pss.ps_argvstr; 363 nstr = pss.ps_nargvstr; 364 } else /* type == PSC_TYPE_ENVV */ { 365 addr = (vm_offset_t)pss.ps_envstr; 366 nstr = pss.ps_nenvstr; 367 } 368 if (addr == 0 || nstr == 0) 369 return (NULL); 370 if (nstr > ARG_MAX) { 371 warnx("format error"); 372 return (NULL); 373 } 374 size = nstr * sizeof(char *); 375 argv = malloc(size); 376 if (argv == NULL) { 377 warn("malloc(%zu)", size); 378 return (NULL); 379 } 380 done = 0; 381 freeargs = NULL; 382 if (core_read_mem(core, argv, size, addr, true) == -1) 383 goto fail; 384 if (args != NULL) { 385 nchr = MIN(ARG_MAX, *lenp); 386 } else { 387 nchr = ARG_MAX; 388 freeargs = args = malloc(nchr); 389 if (args == NULL) { 390 warn("malloc(%zu)", nchr); 391 goto fail; 392 } 393 } 394 p = args; 395 for (i = 0; ; i++) { 396 if (i == nstr) 397 goto done; 398 /* 399 * The program may have scribbled into its argv array, e.g. to 400 * remove some arguments. If that has happened, break out 401 * before trying to read from NULL. 402 */ 403 if (argv[i] == NULL) 404 goto done; 405 for (addr = (vm_offset_t)argv[i]; ; addr += chunksz) { 406 chunksz = MIN(ARGS_CHUNK_SZ, nchr - 1 - done); 407 if (chunksz <= 0) 408 goto done; 409 n = core_read_mem(core, p, chunksz, addr, false); 410 if (n == -1) 411 goto fail; 412 len = strnlen(p, chunksz); 413 p += len; 414 done += len; 415 if (len != chunksz) 416 break; 417 } 418 *p++ = '\0'; 419 done++; 420 } 421fail: 422 free(freeargs); 423 args = NULL; 424done: 425 *lenp = done; 426 free(argv); 427 return (args); 428} |
|