bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd) { char canonic[SB_PATH_MAX]; char dirfd_path[SB_PATH_MAX]; save_errno(); /* Expand the dirfd path first */ switch (resolve_dirfd_path(dirfd, pathname, dirfd_path, sizeof(dirfd_path))) { case -1: sb_debug_dyn("EARLY FAIL: %s(%s) @ resolve_dirfd_path: %s\n", func, pathname, strerror(errno)); return false; case 0: pathname = dirfd_path; break; } /* Then break down any relative/symlink paths */ if (-1 == canonicalize(pathname, canonic)) /* see comments in check_syscall() */ if (ENAMETOOLONG != errno) { sb_debug_dyn("EARLY FAIL: %s(%s) @ canonicalize: %s\n", func, pathname, strerror(errno)); return false; } /* XXX: Hack to prevent errors if the directory exist, and are * not writable - we rather return EEXIST than fail. This can * occur if doing something like `mkdir -p /`. We certainly do * not want to pass this attempt up to the higher levels as those * will trigger a sandbox violation. */ struct stat st; if (0 == lstat(canonic, &st)) { int new_errno; sb_debug_dyn("EARLY FAIL: %s(%s[%s]) @ lstat: %s\n", func, pathname, canonic, strerror(errno)); new_errno = EEXIST; /* Hmm, is this a broken symlink we're trying to extend ? */ if (S_ISLNK(st.st_mode) && stat(pathname, &st) != 0) { /* XXX: This awful hack should probably be turned into a * common func that does a better job. For now, we have * enough crap to catch gnulib tests #297026. */ char *parent = strrchr(pathname, '/'); if (parent && (strcmp(parent, "/.") == 0 || strcmp(parent, "/..") == 0)) new_errno = ENOENT; } errno = new_errno; return false; } restore_errno(); return true; }
static inline bool sb_unlinkat_pre_check(WRAPPER_ARGS_PROTO) { char canonic[SB_PATH_MAX]; save_errno(); if (-1 == canonicalize(pathname, canonic)) /* see comments in check_syscall() */ if (ENAMETOOLONG != errno) goto error; /* XXX: Hack to make sure sandboxed process cannot remove * a device node, bug #79836. */ if (0 == strcmp(canonic, "/dev/null") || 0 == strcmp(canonic, "/dev/zero")) { errno = EACCES; goto error; } restore_errno(); return true; error: if (is_env_on(ENV_SANDBOX_DEBUG)) SB_EINFO("EARLY FAIL", " %s(%s): %s\n", STRING_NAME, pathname, strerror(errno)); return false; }
bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd) { char canonic[SB_PATH_MAX]; save_errno(); /* XXX: need to check pathname with dirfd */ if (-1 == canonicalize(pathname, canonic)) /* see comments in check_syscall() */ if (ENAMETOOLONG != errno) { if (is_env_on(ENV_SANDBOX_DEBUG)) SB_EINFO("EARLY FAIL", " %s(%s) @ canonicalize: %s\n", func, pathname, strerror(errno)); return false; } /* XXX: Hack to prevent errors if the directory exist, and are * not writable - we rather return EEXIST than fail. This can * occur if doing something like `mkdir -p /`. We certainly do * not want to pass this attempt up to the higher levels as those * will trigger a sandbox violation. */ struct stat st; if (0 == lstat(canonic, &st)) { if (is_env_on(ENV_SANDBOX_DEBUG)) SB_EINFO("EARLY FAIL", " %s(%s[%s]) @ lstat: %s\n", func, pathname, canonic, strerror(errno)); errno = EEXIST; return false; } restore_errno(); return true; }
bool sb_unlinkat_pre_check(const char *func, const char *pathname, int dirfd) { char canonic[SB_PATH_MAX]; save_errno(); /* XXX: need to check pathname with dirfd */ if (-1 == canonicalize(pathname, canonic)) /* see comments in check_syscall() */ if (ENAMETOOLONG != errno) goto error; /* XXX: Hack to make sure sandboxed process cannot remove * a device node, bug #79836. */ if (0 == strcmp(canonic, "/dev/null") || 0 == strcmp(canonic, "/dev/zero")) { errno = EACCES; goto error; } restore_errno(); return true; error: if (is_env_on(ENV_SANDBOX_DEBUG)) SB_EINFO("EARLY FAIL", " %s(%s): %s\n", func, pathname, strerror(errno)); return false; }
static inline bool PRE_CHECK_FUNC(WRAPPER_NAME)(_WRAPPER_ARGS_PROTO) { if (!(flags & O_CREAT)) { /* If we're not trying to create, fail normally if * file does not stat */ #if USE_AT if (dirfd == AT_FDCWD || pathname[0] == '/') #endif #undef USE_AT { struct stat st; save_errno(); if (-1 == stat(pathname, &st)) { if (is_env_on(ENV_SANDBOX_DEBUG)) SB_EINFO("EARLY FAIL", " %s(%s): %s\n", STRING_NAME, pathname, strerror(errno)); return false; } restore_errno(); } } return true; }
static void _get_sb_log(char *path, const char *env, const char *prefix) { char *sandbox_log_env = NULL; save_errno(); sandbox_log_env = getenv(env); if (sandbox_log_env && is_env_on(ENV_SANDBOX_TESTING)) { /* When testing, just use what the env says to */ strncpy(path, sandbox_log_env, SB_PATH_MAX); } else { /* THIS CHUNK BREAK THINGS BY DOING THIS: * SANDBOX_LOG=/tmp/sandbox-app-admin/superadduser-1.0.7-11063.log */ if ((NULL != sandbox_log_env) && (NULL != strchr(sandbox_log_env, '/'))) sandbox_log_env = NULL; snprintf(path, SB_PATH_MAX, "%s%s%s%s%d%s", SANDBOX_LOG_LOCATION, prefix, (sandbox_log_env == NULL ? "" : sandbox_log_env), (sandbox_log_env == NULL ? "" : "-"), getpid(), LOG_FILE_EXT); } restore_errno(); }
int u_console_write_ex(int err, const char* file, int line, const char *func, const char* fmt, ...) { err_type savederr; va_list ap; int rc; char strerr[STRERR_BUFSZ], errmsg[STRERR_BUFSZ]; /* when writing to console the following parameters are not used */ file = NULL, line = 0, func = NULL; save_errno(savederr); /* build the message to send to the log system */ va_start(ap, fmt); /* write the message to the standard error */ rc = vfprintf(stderr, fmt, ap); va_end(ap); if(rc < 0) goto err; /* init empty strings */ errmsg[0] = strerr[0] = 0; if(err) { u_strerror_r(err, strerr, sizeof(strerr)); snprintf(errmsg, sizeof(errmsg), "[errno: %d, %s]", err, strerr); errmsg[sizeof(errmsg) - 1] = 0; /* paranoid set */ fprintf(stderr, " %s\n", errmsg); } else fprintf(stderr, "\n"); restore_errno(savederr); return 0; err: restore_errno(savederr); return ~0; }
int u_log_write_ex(int fac, int lev, int flags, int err, const char* file, int line, const char *func, const char* fmt, ...) { va_list ap; err_type savederr; int rc; char msg[U_MAX_LOG_LENGTH], strerr[STRERR_BUFSZ], errmsg[STRERR_BUFSZ]; save_errno(savederr); /* build the message to send to the log system */ va_start(ap, fmt); rc = vsnprintf(msg, U_MAX_LOG_LENGTH, fmt, ap); va_end(ap); if(rc >= U_MAX_LOG_LENGTH) goto err; /* message too long */ /* init empty strings */ errmsg[0] = strerr[0] = 0; if(err) { u_strerror_r(err, strerr, sizeof(strerr)); snprintf(errmsg, sizeof(errmsg), "[errno: %d, %s]", err, strerr); errmsg[sizeof(errmsg) - 1] = 0; /* paranoid set */ } /* ok, send the msg to the logger */ if(flags & LOG_WRITE_FLAG_CTX) u_log(fac, lev, "[%s][%d:%s:%d:%s] %s %s", u_log_label(lev), getpid(), file, line, func, msg, errmsg); else u_log(fac, lev, "[%s][%d:::] %s %s", u_log_label(lev), getpid(), msg, errmsg); restore_errno(savederr); return 0; err: restore_errno(savederr); return ~0; }
char *get_sandbox_conf(void) { char *ret = SANDBOX_CONF_FILE; save_errno(); if (is_env_on(ENV_SANDBOX_TESTING)) { char *abs = getenv("abs_top_srcdir"); ret = xmalloc(strlen(abs) + strlen(LOCAL_SANDBOX_CONF_FILE) + 1); sprintf(ret, "%s%s", abs, LOCAL_SANDBOX_CONF_FILE); } restore_errno(); return ret; }
static void load_libc_handle(void) { save_errno(); /* #260765 */ libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY); restore_errno(); if (!libc_handle) { fprintf(stderr, "libsandbox: Can't dlopen libc: %s\n", dlerror()); exit(EXIT_FAILURE); } }
bool sb_fopen_pre_check(const char *func, const char *pathname, const char *mode) { if ((NULL != mode) && (mode[0] == 'r')) { save_errno(); /* If we're trying to read, fail normally if file does not stat */ struct stat st; if (-1 == stat(pathname, &st)) { if (is_env_on(ENV_SANDBOX_DEBUG)) SB_EINFO("EARLY FAIL", " %s(%s): %s\n", func, pathname, strerror(errno)); return false; } restore_errno(); } return true; }
static void *get_dlsym(const char *symname, const char *symver) { void *symaddr = NULL; #if defined(USE_RTLD_NEXT) libc_handle = RTLD_NEXT; #endif /* Checking for -1UL is significant on hardened! * USE_RTLD_NEXT returns it as a sign of being unusable. * However using !x or NULL checks does NOT pick it up! * That is also why we need to save/restore errno #260765. */ #define INVALID_LIBC_HANDLE(x) (!x || NULL == x || (void *)-1UL == x) if (INVALID_LIBC_HANDLE(libc_handle)) { save_errno(); libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY); restore_errno(); if (INVALID_LIBC_HANDLE(libc_handle)) { fprintf(stderr, "libsandbox: Can't dlopen libc: %s\n", dlerror()); exit(EXIT_FAILURE); } } #undef INVALID_LIBC_HANDLE if (NULL == symver) symaddr = dlsym(libc_handle, symname); else symaddr = dlvsym(libc_handle, symname, symver); if (!symaddr) { fprintf(stderr, "libsandbox: Can't resolve %s: %s\n", symname, dlerror()); exit(EXIT_FAILURE); } return symaddr; }
void sb_efunc(const char *color, const char *hilight, const char *format, ...) { save_errno(); int fd = STDERR_FILENO; if (!init_color) { nocolor = is_env_on(ENV_NOCOLOR); init_color = true; } if (!nocolor) sb_fdprintf(fd, "%s%s%s", color, hilight, COLOR_NORMAL); else sb_fdprintf(fd, "%s", hilight); va_list args; va_start(args, format); sb_vfdprintf(fd, format, args); va_end(args); restore_errno(); }