diff --git a/cr-restore.c b/cr-restore.c index 21ad798d8..2752ca9ac 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -2834,6 +2834,14 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) strncpy(lsm, rendered, lsm_profile_len); xfree(rendered); + + task_args->proc_fd = dup(get_service_fd(PROC_FD_OFF)); + if (task_args->proc_fd < 0) { + pr_perror("can't dup proc fd"); + goto err; + } + } else { + task_args->proc_fd = -1; } /* @@ -2879,18 +2887,10 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) #undef remap_array - if (lsm) { - task_args->proc_attr_current = open_proc_rw(PROC_SELF, "attr/current"); - if (task_args->proc_attr_current < 0) { - pr_perror("Can't open attr/current"); - goto err; - } - - task_args->lsm_profile = rst_mem_remap_ptr(lsm_pos, RM_PRIVATE); - task_args->lsm_profile_len = lsm_profile_len; - } else { - task_args->lsm_profile = NULL; - } + if (lsm) + task_args->creds.lsm_profile = rst_mem_remap_ptr(lsm_pos, RM_PRIVATE); + else + task_args->creds.lsm_profile = NULL; /* * Arguments for task restoration. diff --git a/include/restorer.h b/include/restorer.h index 54f416618..c82557cf5 100644 --- a/include/restorer.h +++ b/include/restorer.h @@ -160,9 +160,12 @@ struct task_restore_args { int fd_last_pid; /* sys.ns_last_pid for threads rst */ - int proc_attr_current; - char *lsm_profile; - int lsm_profile_len; + /* + * proc_fd is a handle to /proc that the restorer blob can use to open + * files there, because some of them can't be opened before the + * restorer blob is called. + */ + int proc_fd; #ifdef CONFIG_VDSO unsigned long vdso_rt_size; diff --git a/pie/restorer.c b/pie/restorer.c index c11c9c8b1..aff49bcb4 100644 --- a/pie/restorer.c +++ b/pie/restorer.c @@ -95,7 +95,39 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data) sys_exit_group(1); } -static int restore_creds(CredsEntry *ce) +static int lsm_set_label(char *label, int procfd) +{ + int ret = -1, len, lsmfd; + char path[LOG_SIMPLE_CHUNK]; + + if (!label) + return 0; + + pr_info("restoring lsm profile %s\n", label); + + simple_sprintf(path, "self/task/%ld/attr/current", sys_gettid()); + + lsmfd = sys_openat(procfd, path, O_WRONLY, 0); + sys_close(procfd); + if (lsmfd < 0) { + pr_err("failed openat %d\n", lsmfd); + return -1; + } + + for (len = 0; label[len]; len++) + ; + + ret = sys_write(lsmfd, label, len); + sys_close(lsmfd); + if (ret < 0) { + pr_err("can't write lsm profile %d\n", ret); + return -1; + } + + return 0; +} + +static int restore_creds(CredsEntry *ce, int procfd) { int b, i, ret; struct cap_header hdr; @@ -200,6 +232,9 @@ static int restore_creds(CredsEntry *ce) return -1; } + if (lsm_set_label(ce->lsm_profile, procfd) < 0) + return -1; + return 0; } @@ -366,7 +401,7 @@ long __export_restore_thread(struct thread_restore_args *args) if (restore_thread_common(rt_sigframe, args)) goto core_restore_end; - ret = restore_creds(&args->ta->creds); + ret = restore_creds(&args->ta->creds, args->ta->proc_fd); if (ret) goto core_restore_end; @@ -738,25 +773,6 @@ static int wait_helpers(struct task_restore_args *task_args) return 0; } -static int lsm_set_label(struct task_restore_args *args) -{ - int ret = -1; - - if (!args->lsm_profile) - return 0; - - pr_info("restoring lsm profile %s\n", args->lsm_profile); - - ret = sys_write(args->proc_attr_current, args->lsm_profile, args->lsm_profile_len); - sys_close(args->proc_attr_current); - if (ret < 0) { - pr_err("can't write lsm profile\n"); - return -1; - } - - return ret; -} - /* * The main routine to restore task via sigreturn. * This one is very special, we never return there @@ -1171,15 +1187,10 @@ long __export_restore_task(struct task_restore_args *args) * thus restore* creds _after_ all of the above. */ - ret = restore_creds(&args->creds); + ret = restore_creds(&args->creds, args->proc_fd); ret = ret || restore_dumpable_flag(&args->mm); ret = ret || restore_pdeath_sig(args->t); - if (lsm_set_label(args) < 0) { - pr_err("lsm_set_label failed\n"); - goto core_restore_end; - } - futex_set_and_wake(&thread_inprogress, args->nr_threads); restore_finish_stage(CR_STATE_RESTORE_CREDS);