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(); }
static couchstore_error_t couch_advise(couchstore_error_info_t *errinfo, couch_file_handle handle, cs_off_t offset, cs_off_t len, couchstore_file_advice_t advice) { #ifdef POSIX_FADV_NORMAL int fd = handle_to_fd(handle); int error = posix_fadvise(fd, offset, len, (int) advice); if (error != 0) { save_errno(errinfo); } switch(error) { case EINVAL: case ESPIPE: return COUCHSTORE_ERROR_INVALID_ARGUMENTS; break; case EBADF: return COUCHSTORE_ERROR_OPEN_FILE; break; } #else (void) handle; (void)offset; (void)len; (void)advice; (void)errinfo; #endif return COUCHSTORE_SUCCESS; }
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 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; }
/*Initialization of group*/ void buxtond_set_group(char *group, char *layer) { client_connection(); save_errno(); if(_layer){ free(_layer); } if(_group){ free(_group); } _layer = strdup(layer); if(!_layer){ printf("Layer assignment failed. Aborting operation.\n"); return; } _group = strdup(group); if(!_group){ printf("Group assignment failed. Aborting operation.\n"); return; } BuxtonKey g = buxton_key_create(_group, NULL, _layer, STRING); int status; if (buxton_create_group(client, g, cg_cb, &status, true)){ printf("Create group call failed.\n"); } else { printf("Switched to group: %s, layer: %s.\n", buxton_key_get_group(g), buxton_key_get_layer(g)); errno = saved_errno; } buxton_key_free(g); }
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; }
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; }
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; }
static cs_off_t couch_goto_eof(couchstore_error_info_t *errinfo, couch_file_handle handle) { int fd = handle_to_fd(handle); cs_off_t rv = lseek(fd, 0, SEEK_END); if (rv < 0) { save_errno(errinfo); } return rv; }
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); } }
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 couchstore_error_t couch_sync(couchstore_error_info_t *errinfo, couch_file_handle handle) { int fd = handle_to_fd(handle); int rv; do { rv = fdatasync(fd); } while (rv == -1 && errno == EINTR); if (rv == -1) { save_errno(errinfo); return COUCHSTORE_ERROR_WRITE; } return COUCHSTORE_SUCCESS; }
static void couch_close(couchstore_error_info_t *errinfo, couch_file_handle handle) { int fd = handle_to_fd(handle); int rv = 0; if (fd != -1) { do { assert(fd >= 3); rv = close(fd); } while (rv == -1 && errno == EINTR); } if (rv < 0) { save_errno(errinfo); } }
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; }
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; }
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; }
static ssize_t couch_pwrite(couchstore_error_info_t *errinfo, couch_file_handle handle, const void *buf, size_t nbyte, cs_off_t offset) { #ifdef LOG_IO fprintf(stderr, "PWRITE %8llx -- %8llx (%6.1f kbytes)\n", offset, offset+nbyte, nbyte/1024.0); #endif int fd = handle_to_fd(handle); ssize_t rv; do { rv = pwrite(fd, buf, nbyte, offset); } while (rv == -1 && errno == EINTR); if (rv < 0) { save_errno(errinfo); return (ssize_t) COUCHSTORE_ERROR_WRITE; } return rv; }
void buxtond_set_bool(char *key, bool value) { /*make sure client connection is open*/ client_connection(); /*create key*/ BuxtonKey _key = buxton_key_create(_group, strdup(key), _layer, BOOLEAN); /*Return value and status*/ struct vstatus ret; ret.type = BOOLEAN; ret.bval = value; save_errno(); if(buxton_set_value(client, _key, &value, bs_cb, &ret, true)){ printf("Set bool call failed.\n"); } if (!ret.status){ errno = EACCES; } else { errno = saved_errno; } buxton_key_free(_key); }
bool buxtond_get_bool(char *key) { /*make sure client connection is open*/ client_connection(); /*create key*/ BuxtonKey _key = buxton_key_create(_group, strdup(key), _layer, BOOLEAN); /*return value*/ struct vstatus ret; ret.type = BOOLEAN; save_errno(); /*get value*/ if (buxton_get_value(client, _key, bgb_cb, &ret, true)){ printf("Get bool call failed.\n"); } if (!ret.status){ errno = EACCES; } else { errno = saved_errno; } buxton_key_free(_key); return ret.bval; }
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; }
static int add_db_file(pesigcheck_context *ctx, db_specifier which, const char *dbfile, db_f_type type) { dblist *db = calloc(1, sizeof (dblist)); if (!db) return -1; db->type = type; db->fd = open(dbfile, O_RDONLY); if (db->fd < 0) { save_errno(free(db)); return -1; } char *path = strdup(dbfile); if (!path) { save_errno(close(db->fd); free(db)); return -1; }
static couchstore_error_t couch_open(couchstore_error_info_t *errinfo, couch_file_handle* handle, const char *path, int oflag) { int fd; do { fd = open(path, oflag | O_LARGEFILE, 0666); } while (fd == -1 && errno == EINTR); if (fd < 0) { save_errno(errinfo); if (errno == ENOENT) { return COUCHSTORE_ERROR_NO_SUCH_FILE; } else { return COUCHSTORE_ERROR_OPEN_FILE; } } /* Tell the caller about the new handle (file descriptor) */ *handle = fd_to_handle(fd); return COUCHSTORE_SUCCESS; }
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(); }
void buxtond_set_int32(char *key, int32_t value) { /*make sure client connection is open*/ client_connection(); /*check if a key has been created*/ /*create key */ BuxtonKey _key = buxton_key_create(_group, strdup(key), _layer, INT32); /*Return value and status*/ struct vstatus ret; ret.type = INT32; ret.i32val = value; save_errno(); /*call buxton_set_value for type INT32*/ if (buxton_set_value(client, _key, &value, bs_cb, &ret, true)){ printf("Set int32_t call failed.\n"); return; } if (!ret.status){ errno = EACCES; } else { errno = saved_errno; } buxton_key_free(_key); }