Mercurial > gub
view librestrict/restrict.c @ 6511:728bffca309a
librestrict: build fix for gcc-5.2.
author | Jan Nieuwenhuizen <janneke@gnu.org> |
---|---|
date | Mon, 14 Mar 2016 23:03:50 +0100 |
parents | e1181d222682 |
children |
line wrap: on
line source
/* restrict.c -- override open(2), stat(2), execve(2), etc. to make sure the build system doesn't leak into cross builds. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #ifndef __RESTRICT_C__ #define __RESTRICT_C__ static char *executable_name; static int verbosity = 0; static struct allow_file_name { char *prefix; int prefix_len; } *allowed; static int allowed_len; static int allowed_count; #if defined (__FreeBSD__) char const *SELF = "/proc/curproc/file"; #else char const *SELF = "/proc/self/exe"; #endif static void add_allowed_file (char const *name) { if (allowed_count >= allowed_len) { int newlen = (2*allowed_len+1); allowed = realloc (allowed, sizeof (struct allow_file_name)*newlen); allowed_len = newlen; } allowed[allowed_count].prefix = strdup (name); allowed[allowed_count].prefix_len = strlen (name); allowed_count ++; } static void add_allowed_path (char const *path) { char *p = strchr (path, ':'); while (p) { char c = *p; *p = '\0'; add_allowed_file (strdup (path)); *p = c; path = p + 1; p = strchr (path, ':'); } add_allowed_file (path); } static int is_in_path (char const *path, char const *name) { char *p = strchr (path, ':'); int len = strlen (name); while (p) { if (p - path == len && !strncmp (path, name, len)) return 1; path = p + 1; p = strchr (path, ':'); } if (!strcmp (path, name)) return 1; return 0; } /* prepend cwd if necessary. Leaks memory. */ static char const * expand_file_name (char const *p) { if (*p == '/') return p; else { char s[1024]; getcwd (s, sizeof (s)); strncat (s, "/", 1); // ugh. strcat (s, p); return strdup (s); } } static int is_allowed (char const *file_name, char const *call) { int i; char const *abs_file_name; if (allowed_count == 0) return 1; abs_file_name = expand_file_name (file_name); for (i = 0; i < allowed_count; i++) if (0 == strncmp (abs_file_name, allowed[i].prefix, allowed[i].prefix_len)) return 1; fprintf (stderr, "librestrict:error:%s: tried to %s () file %s\n", executable_name, call, abs_file_name); fprintf (stderr, "librestrict:allowed:%s\n", ""); for (i = 0; i < allowed_count; i++) fprintf (stderr, " %s\n", allowed[i].prefix); return 0; } static char * get_executable_name (void) { int const MAXLEN = 1024; char s[MAXLEN+1]; ssize_t ss = readlink (SELF, s, MAXLEN); if (ss < 0) { fprintf (stderr, "librestrict:error: cannot open: %s\n", SELF); abort (); } s[ss] = '\0'; return strdup (s); } static char const * strrstr (char const *haystack, char const *needle) { char const *p = haystack; char const *last_match = NULL; while ((p = strstr (p, needle)) != NULL) { last_match = p; p ++; } return last_match; } static char * get_allowed_prefix (char const *exe_name) { int prefix_len; char *allowed_prefix; // can't add bin/ due to libexec. char *cross_suffix = "/root/usr/cross/"; char *tools_suffix = "/tools/root/usr/"; char *ignore = getenv ("LIBRESTRICT_IGNORE"); char const *last_found = strrstr (exe_name, cross_suffix); if (last_found == NULL) last_found = strrstr (exe_name, tools_suffix); if (last_found == NULL) return NULL; if (ignore && is_in_path (ignore, exe_name)) { if (verbosity) fprintf (stderr, "librestrict:warning:%s: lifting restrictions for %s\n", __PRETTY_FUNCTION__, exe_name); return NULL; } prefix_len = last_found - exe_name; allowed_prefix = malloc (sizeof (char) * (prefix_len + 1)); strncpy (allowed_prefix, exe_name, prefix_len); allowed_prefix[prefix_len] = '\0'; return allowed_prefix; } static void initialize (void) __attribute__ ((constructor)); static void initialize (void) { char *restr; char *verbosity_string = getenv ("LIBRESTRICT_VERBOSE"); if (verbosity_string) { verbosity = atoi (verbosity_string); if (!verbosity) verbosity = 1; } executable_name = get_executable_name (); restr = get_allowed_prefix (executable_name); if (restr) { char *allow = getenv ("LIBRESTRICT_ALLOW"); if (verbosity > 1) fprintf (stderr, "librestrict:warning:%s: allow: %s\n", __PRETTY_FUNCTION__, allow); add_allowed_file (restr); if (allow) add_allowed_path (allow); add_allowed_file ("/tmp"); add_allowed_file ("/dev/null"); add_allowed_file ("/dev/urandom"); add_allowed_file ("/proc/self"); add_allowed_file ("/proc/stat"); } } #ifdef TEST_SELF int main () { int i; char const *h = "aabbaabba"; char const *n = "bb"; char *exe = "/home/hanwen/vc/gub/target/mingw/usr/cross/bin/foo"; printf ("%s\n", get_executable_name ()); printf ("strrstr %s %s: %s\n", h,n, strrstr (h, n)); printf ("allowed for %s : %s\n", exe, get_allowed_prefix (exe)); puts ("librestrict:allowed:"); for (i = 0; i < allowed_count; i++) fprintf (stderr, " %s\n", allowed[i].prefix); return 0; } #endif #endif /* __RESTRICT_C__ */