1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/*
$Id: maps.c,v 1.16 2007-06-05 01:45:35+01 taviso Exp $
Copyright (C) 2006,2007 Tavis Ormandy <taviso@sdf.lonestar.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <stdio.h>
#include <sys/types.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <alloca.h>
#include <stdbool.h>
#include "list.h"
#include "maps.h"
#include "scanmem.h"
bool readmaps(pid_t target, list_t * regions)
{
FILE *maps;
char name[32], *line = NULL;
size_t len = 0;
/* check if target is valid */
if (target == 0)
return false;
/* construct the maps filename */
snprintf(name, sizeof(name), "/proc/%u/maps", target);
/* attempt to open the maps file */
if ((maps = fopen(name, "r")) == NULL) {
fprintf(stderr, "error: failed to open maps file %s.\n", name);
return false;
}
eprintf("info: maps file located at %s opened.\n", name);
/* read every line of the maps file */
while (getline(&line, &len, maps) != -1) {
unsigned start, end;
region_t *map = NULL;
char read, write, exec, cow, *filename;
/* slight overallocation */
if ((filename = alloca(len)) == NULL) {
fprintf(stderr, "error: failed to allocate %u bytes for filename.\n", len);
goto error;
}
/* initialise to zero */
memset(filename, '\0', len);
/* parse each line */
if (sscanf(line, "%x-%x %c%c%c%c %*x %*s %*u %s", &start, &end, &read,
&write, &exec, &cow, filename) >= 6) {
/* must have permissions to read and write, and be non-zero size */
if (write == 'w' && read == 'r' && (end - start) > 0) {
/* allocate a new region structure */
if ((map = calloc(1, sizeof(region_t) + strlen(filename))) == NULL) {
fprintf(stderr, "error: failed to allocate memory for region.\n");
goto error;
}
/* initialise this region */
map->flags.read = true;
map->flags.write = true;
map->start = start;
map->size = (unsigned) (end - start);
/* setup other permissions */
map->flags.exec = (exec == 'x');
map->flags.shared = (cow == 's');
map->flags.private = (cow == 'p');
/* save pathname */
if (strlen(filename) != 0) {
/* the pathname is concatenated with the structure */
if ((map = realloc(map, sizeof(*map) + strlen(filename))) == NULL) {
fprintf(stderr, "error: failed to allocate memory.\n");
goto error;
}
strcpy(map->filename, filename);
}
/* add a unique identifier */
map->id = regions->size;
/* okay, add this guy to our list */
if (l_append(regions, regions->tail, map) == -1) {
fprintf(stderr, "error: failed to save region.\n");
goto error;
}
}
}
}
eprintf("info: %d suitable regions found.\n", regions->size);
/* release memory allocated */
free(line);
fclose(maps);
return true;
error:
free(line);
fclose(maps);
return false;
}
int compare_region_id(const region_t *a, const region_t *b)
{
return (int) (a->id - b->id);
}
|