diff options
Diffstat (limited to 'arch/sandbox/os/common.c')
-rw-r--r-- | arch/sandbox/os/common.c | 138 |
1 files changed, 88 insertions, 50 deletions
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c index 4eb6d37fff..3446074f99 100644 --- a/arch/sandbox/os/common.c +++ b/arch/sandbox/os/common.c @@ -40,7 +40,6 @@ #include <sys/ioctl.h> #include <linux/fs.h> #include <sys/time.h> -#include <signal.h> /* * ...except the ones needed to connect with barebox */ @@ -76,6 +75,15 @@ static void cookmode(void) tcsetattr(0, TCSANOW, &term_orig); } +static char *stickypage_path; + +static void prepare_exit(void) +{ + cookmode(); + if (stickypage_path) + remove(stickypage_path); +} + int linux_tstc(int fd) { struct timeval tv = { @@ -123,13 +131,27 @@ uint64_t linux_get_time(void) void __attribute__((noreturn)) linux_exit(void) { - cookmode(); + prepare_exit(); exit(0); } -static size_t saved_argv_len; static char **saved_argv; +static int selfpath(char *buf, size_t len) +{ + int ret; + + /* we must follow the symlink, so we can exec an updated executable */ + ret = readlink("/proc/self/exe", buf, len - 1); + if (ret < 0) + return ret; + + if (0 < ret && ret < len - 1) + buf[ret] = '\0'; + + return ret; +} + void linux_reexec(void) { char buf[4097]; @@ -138,9 +160,8 @@ void linux_reexec(void) cookmode(); /* we must follow the symlink, so we can exec an updated executable */ - ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1); - if (0 < ret && ret < sizeof(buf) - 1) { - buf[ret] = '\0'; + ret = selfpath(buf, sizeof(buf)); + if (ret > 0) { execv(buf, saved_argv); if (!strcmp(&buf[ret - DELETED_OFFSET], " (deleted)")) { printf("barebox image on disk changed. Loading new.\n"); @@ -155,7 +176,7 @@ void linux_reexec(void) void linux_hang(void) { - cookmode(); + prepare_exit(); /* falls through to generic hang() */ } @@ -317,55 +338,76 @@ static int add_image(const char *_str, char *devname_template, int *devname_numb return ret; } -int linux_open_hostfile(struct hf_info *hf) +extern uint8_t stickypage[4096]; + +char *linux_get_stickypage_path(void) { - char *buf = NULL; - struct stat s; - int fd = -1; + size_t nwritten; + ssize_t ret; + int fd; - printf("add %s %sbacked by file %s%s\n", hf->devname, - hf->filename ? "" : "initially un", hf->filename ?: "", - hf->is_readonly ? "(ro)" : ""); + ret = asprintf(&stickypage_path, "%s/barebox/stickypage.%lu", + getenv("XDG_RUNTIME_DIR") ?: "/run", (long)getpid()); + if (ret < 0) + goto err_asprintf; - if (hf->filename) { - fd = hf->fd = open(hf->filename, (hf->is_readonly ? O_RDONLY : O_RDWR) | O_CLOEXEC); - } else { - char *filename; - int ret; + ret = mkdir(dirname(stickypage_path), 0755); + if (ret < 0 && errno != EEXIST) { + perror("mkdir"); + goto err_creat; + } + + stickypage_path[strlen(stickypage_path)] = '/'; + + fd = open(stickypage_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644); + if (fd < 0) { + if (errno == EEXIST) + return stickypage_path; + + perror("open"); + goto err_creat; + } - ret = asprintf(&buf, "--image=%s=/tmp/barebox-hostfileXXXXXX", hf->devname); + for (nwritten = 0; nwritten < sizeof(stickypage); ) { + ret = write(fd, &stickypage[nwritten], sizeof(stickypage) - nwritten); if (ret < 0) { - perror("asprintf"); - goto err_out; + if (errno == EINTR || errno == EAGAIN) + continue; + perror("write"); + goto err_write; } - filename = buf + strlen("--image==") + strlen(hf->devname); + nwritten += ret; + } - fd = hf->fd = mkstemp(filename); - if (fd >= 0) { - ret = fcntl(fd, F_SETFD, FD_CLOEXEC); - if (ret < 0) { - perror("fcntl"); - goto err_out; - } + close(fd); - ret = ftruncate(fd, hf->size); - if (ret < 0) { - perror("ftruncate"); - goto err_out; - } + return stickypage_path; - hf->filename = filename; +err_write: + close(fd); +err_creat: + free(stickypage_path); +err_asprintf: + stickypage_path = NULL; - saved_argv = realloc(saved_argv, - ++saved_argv_len * sizeof(*saved_argv)); - if (!saved_argv) - exit(1); - saved_argv[saved_argv_len - 2] = buf; - saved_argv[saved_argv_len - 1] = NULL; - } - } + return NULL; +} + +int linux_open_hostfile(struct hf_info *hf) +{ + char *buf = NULL; + struct stat s; + int fd = -1; + printf("add %s %sbacked by file %s%s\n", hf->devname, + hf->filename ? "" : "initially un", hf->filename ?: "", + hf->is_readonly ? "(ro)" : ""); + + if (!hf->filename) + return -ENOENT; + + fd = hf->fd = open(hf->filename, (hf->is_readonly ? O_RDONLY : O_RDWR) | O_CLOEXEC); if (fd < 0) { perror("open"); goto err_out; @@ -477,7 +519,7 @@ int main(int argc, char *argv[]) char *aux; #ifdef CONFIG_ASAN - __sanitizer_set_death_callback(cookmode); + __sanitizer_set_death_callback(prepare_exit); #endif while (1) { @@ -517,11 +559,7 @@ int main(int argc, char *argv[]) } } - saved_argv_len = argc + 1; - saved_argv = calloc(saved_argv_len, sizeof(*saved_argv)); - if (!saved_argv) - exit(1); - memcpy(saved_argv, argv, saved_argv_len * sizeof(*saved_argv)); + saved_argv = argv; ram = malloc(malloc_size); if (!ram) { |