diff --git a/cr-dump.c b/cr-dump.c index 6d641c443..5581d5ae8 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -50,6 +50,7 @@ #include "protobuf/fdinfo.pb-c.h" #include "protobuf/fs.pb-c.h" #include "protobuf/mm.pb-c.h" +#include "protobuf/creds.pb-c.h" #ifndef CONFIG_X86_64 # error No x86-32 support yet @@ -452,9 +453,9 @@ err: static int dump_task_creds(pid_t pid, const struct parasite_dump_misc *misc, const struct cr_fdset *fds) { - int ret, i; + int ret; struct proc_status_creds cr; - struct creds_entry ce; + CredsEntry ce = CREDS_ENTRY__INIT; pr_info("\n"); pr_info("Dumping creds for %d)\n", pid); @@ -475,20 +476,18 @@ static int dump_task_creds(pid_t pid, const struct parasite_dump_misc *misc, BUILD_BUG_ON(CR_CAP_SIZE != PROC_CAP_SIZE); - for (i = 0; i < CR_CAP_SIZE; i++) { - ce.cap_inh[i] = cr.cap_inh[i]; - ce.cap_prm[i] = cr.cap_prm[i]; - ce.cap_eff[i] = cr.cap_eff[i]; - ce.cap_bnd[i] = cr.cap_bnd[i]; - } + ce.n_cap_inh = CR_CAP_SIZE; + ce.cap_inh = cr.cap_inh; + ce.n_cap_prm = CR_CAP_SIZE; + ce.cap_prm = cr.cap_prm; + ce.n_cap_eff = CR_CAP_SIZE; + ce.cap_eff = cr.cap_eff; + ce.n_cap_bnd = CR_CAP_SIZE; + ce.cap_bnd = cr.cap_bnd; ce.secbits = misc->secbits; - ret = write_img(fdset_fd(fds, CR_FD_CREDS), &ce); - if (ret < 0) - return ret; - - return 0; + return pb_write(fdset_fd(fds, CR_FD_CREDS), &ce, creds_entry); } #define assign_reg(dst, src, e) dst.e = (__typeof__(dst.e))src.e diff --git a/cr-restore.c b/cr-restore.c index a0eea4bcc..11e7e411a 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -1015,21 +1015,44 @@ out: return ret; } +static inline int verify_cap_size(CredsEntry *ce) +{ + return ((ce->n_cap_inh == CR_CAP_SIZE) && (ce->n_cap_eff == CR_CAP_SIZE) && + (ce->n_cap_prm == CR_CAP_SIZE) && (ce->n_cap_bnd == CR_CAP_SIZE)); +} + static int prepare_creds(int pid, struct task_restore_core_args *args) { int fd, ret; + CredsEntry *ce; fd = open_image_ro(CR_FD_CREDS, pid); if (fd < 0) return fd; - ret = read_img(fd, &args->creds); - + ret = pb_read(fd, &ce, creds_entry); close_safe(&fd); + if (ret < 0) + return ret; + if (!verify_cap_size(ce)) + return -1; + + args->creds = *ce; + args->creds.cap_inh = args->cap_inh; + memcpy(args->cap_inh, ce->cap_inh, sizeof(args->cap_inh)); + args->creds.cap_eff = args->cap_eff; + memcpy(args->cap_eff, ce->cap_eff, sizeof(args->cap_eff)); + args->creds.cap_prm = args->cap_prm; + memcpy(args->cap_prm, ce->cap_prm, sizeof(args->cap_prm)); + args->creds.cap_bnd = args->cap_bnd; + memcpy(args->cap_bnd, ce->cap_bnd, sizeof(args->cap_bnd)); + + creds_entry__free_unpacked(ce, NULL); + /* XXX -- validate creds here? */ - return ret > 0 ? 0 : -1; + return 0; } static struct vma_entry *vma_list_remap(void *addr, unsigned long len, struct list_head *vmas) diff --git a/cr-show.c b/cr-show.c index b7d1fd426..ad034e9db 100644 --- a/cr-show.c +++ b/cr-show.c @@ -38,6 +38,7 @@ #include "protobuf/sa.pb-c.h" #include "protobuf/itimer.pb-c.h" #include "protobuf/mm.pb-c.h" +#include "protobuf/creds.pb-c.h" #define DEF_PAGES_PER_LINE 6 @@ -298,35 +299,37 @@ out: pr_img_tail(CR_FD_ITIMERS); } -static void show_cap(char *name, u32 *v) +static void show_cap(char *name, int nr, uint32_t *v) { int i; pr_msg("%s: ", name); - for (i = CR_CAP_SIZE - 1; i >= 0; i--) + for (i = nr - 1; i >= 0; i--) pr_msg("0x%08x", v[i]); pr_msg("\n"); } void show_creds(int fd, struct cr_options *o) { - struct creds_entry ce; + CredsEntry *ce; pr_img_head(CR_FD_CREDS); - if (read_img(fd, &ce) < 0) + if (pb_read(fd, &ce, creds_entry) < 0) goto out; pr_msg("uid %u euid %u suid %u fsuid %u\n", - ce.uid, ce.euid, ce.suid, ce.fsuid); + ce->uid, ce->euid, ce->suid, ce->fsuid); pr_msg("gid %u egid %u sgid %u fsgid %u\n", - ce.gid, ce.egid, ce.sgid, ce.fsgid); + ce->gid, ce->egid, ce->sgid, ce->fsgid); - show_cap("Inh", ce.cap_inh); - show_cap("Eff", ce.cap_eff); - show_cap("Prm", ce.cap_prm); - show_cap("Bnd", ce.cap_bnd); + show_cap("Inh", ce->n_cap_inh, ce->cap_inh); + show_cap("Eff", ce->n_cap_eff, ce->cap_eff); + show_cap("Prm", ce->n_cap_prm, ce->cap_prm); + show_cap("Bnd", ce->n_cap_bnd, ce->cap_bnd); - pr_msg("secbits: %#x\n", ce.secbits); + pr_msg("secbits: %#x\n", ce->secbits); + + creds_entry__free_unpacked(ce, NULL); out: pr_img_tail(CR_FD_CREDS); } diff --git a/include/image.h b/include/image.h index 0dc23ad39..f92369cc4 100644 --- a/include/image.h +++ b/include/image.h @@ -91,24 +91,6 @@ struct page_entry { #define CR_CAP_SIZE 2 -struct creds_entry { - u32 uid; - u32 gid; - u32 euid; - u32 egid; - u32 suid; - u32 sgid; - u32 fsuid; - u32 fsgid; - - u32 cap_inh[CR_CAP_SIZE]; - u32 cap_prm[CR_CAP_SIZE]; - u32 cap_eff[CR_CAP_SIZE]; - u32 cap_bnd[CR_CAP_SIZE]; - - u32 secbits; -} __packed; - #define HEADER_VERSION 1 #define HEADER_ARCH_X86_64 1 diff --git a/include/proc_parse.h b/include/proc_parse.h index 6ce6b3a72..db699a66d 100644 --- a/include/proc_parse.h +++ b/include/proc_parse.h @@ -83,10 +83,10 @@ struct proc_status_creds { unsigned int uids[4]; unsigned int gids[4]; - unsigned int cap_inh[PROC_CAP_SIZE]; - unsigned int cap_prm[PROC_CAP_SIZE]; - unsigned int cap_eff[PROC_CAP_SIZE]; - unsigned int cap_bnd[PROC_CAP_SIZE]; + uint32_t cap_inh[PROC_CAP_SIZE]; + uint32_t cap_prm[PROC_CAP_SIZE]; + uint32_t cap_eff[PROC_CAP_SIZE]; + uint32_t cap_bnd[PROC_CAP_SIZE]; }; struct mount_info { diff --git a/include/restorer.h b/include/restorer.h index 39367b2fd..c6777a3dd 100644 --- a/include/restorer.h +++ b/include/restorer.h @@ -12,6 +12,7 @@ #include "crtools.h" #include "../protobuf/mm.pb-c.h" +#include "../protobuf/creds.pb-c.h" #ifndef CONFIG_X86_64 # error Only x86-64 is supported @@ -85,7 +86,11 @@ struct task_restore_core_args { struct itimerval itimers[3]; - struct creds_entry creds; + CredsEntry creds; + uint32_t cap_inh[CR_CAP_SIZE]; + uint32_t cap_prm[CR_CAP_SIZE]; + uint32_t cap_eff[CR_CAP_SIZE]; + uint32_t cap_bnd[CR_CAP_SIZE]; MmEntry mm; u64 mm_saved_auxv[AT_VECTOR_SIZE]; diff --git a/protobuf/Makefile b/protobuf/Makefile index 8e4b87fe4..341fc99de 100644 --- a/protobuf/Makefile +++ b/protobuf/Makefile @@ -47,6 +47,7 @@ PROTO_FILES += ipc-desc.proto PROTO_FILES += ipc-shm.proto PROTO_FILES += ipc-msg.proto PROTO_FILES += ipc-sem.proto +PROTO_FILES += creds.proto HDRS := $(patsubst %.proto,%.pb-c.h,$(PROTO_FILES)) SRCS := $(patsubst %.proto,%.pb-c.c,$(PROTO_FILES)) diff --git a/protobuf/creds.proto b/protobuf/creds.proto new file mode 100644 index 000000000..a3e756f0a --- /dev/null +++ b/protobuf/creds.proto @@ -0,0 +1,17 @@ +message creds_entry { + required uint32 uid = 1; + required uint32 gid = 2; + required uint32 euid = 3; + required uint32 egid = 4; + required uint32 suid = 5; + required uint32 sgid = 6; + required uint32 fsuid = 7; + required uint32 fsgid = 8; + + repeated uint32 cap_inh = 9; + repeated uint32 cap_prm = 10; + repeated uint32 cap_eff = 11; + repeated uint32 cap_bnd = 12; + + required uint32 secbits = 13; +} diff --git a/restorer.c b/restorer.c index eb41e974b..2cb8c5466 100644 --- a/restorer.c +++ b/restorer.c @@ -23,6 +23,8 @@ #include "lock.h" #include "restorer.h" +#include "protobuf/creds.pb-c.h" + #define sys_prctl_safe(opcode, val1, val2, val3) \ ({ \ long __ret = sys_prctl(opcode, val1, val2, val3, 0); \ @@ -50,7 +52,7 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data) sys_exit_group(1); } -static void restore_creds(struct creds_entry *ce) +static void restore_creds(CredsEntry *ce) { int b, i; struct cap_header hdr;