<div dir="ltr">Yes, it seems like it would be easiest to get the correct uids and gids for ghost files in this way. More on this in my other response, to [PATCH 1/4].</div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Mon, Aug 11, 2014 at 6:27 AM, Andrew Vagin <span dir="ltr"><<a href="mailto:avagin@parallels.com" target="_blank">avagin@parallels.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="">On Fri, Aug 08, 2014 at 10:23:09PM -0700, Sophie Blee-Goldman wrote:<br>
> Moves the dump of credentials to the parasite, in case the process<br>
> lives in a user namespace and has different uids, gids, or<br>
> capabilities inside it.<br>
<br>
</div>We save uid-s for ghost files, which should be remapped too.<br>
<br>
Can we remap uid-s and gid-s during dump according with uid_maps and<br>
gid_maps?<br>
<a href="https://github.com/avagin/criu/commit/9ae1b290bccc6d4add75107b95aca6b336aa3845" target="_blank">https://github.com/avagin/criu/commit/9ae1b290bccc6d4add75107b95aca6b336aa3845</a><br>
<div><div class="h5"><br>
><br>
> Signed-off-by: Sophie Blee-Goldman <<a href="mailto:ableegoldman@google.com">ableegoldman@google.com</a>><br>
><br>
> diff --git a/arch/arm/syscall.def b/arch/arm/syscall.def<br>
> index c539e3e..5df83cb 100644<br>
> --- a/arch/arm/syscall.def<br>
> +++ b/arch/arm/syscall.def<br>
> @@ -54,11 +54,14 @@ readlink 78 85 (const char *path, char *buf, int bufsize)<br>
> umask 166 60 (int mask)<br>
> getgroups 158 205 (int gsize, unsigned int *groups)<br>
> setresuid 147 164 (int uid, int euid, int suid)<br>
> +getresuid 148 165 (unsigned int *uid, unsigned int *euid, unsigned int *suid)<br>
> setresgid 149 170 (int gid, int egid, int sgid)<br>
> +getresgid 150 171 (unsigned int *uid, unsigned int *euid, unsigned int *suid)<br>
> getpgid 155 132 (pid_t pid)<br>
> setfsuid 151 138 (int fsuid)<br>
> setfsgid 152 139 (int fsgid)<br>
> getsid 156 147 (void)<br>
> +capget 90 184 (struct cap_header *h, struct cap_data *d)<br>
> capset 91 185 (struct cap_header *h, struct cap_data *d)<br>
> rt_sigqueueinfo 138 178 (pid_t pid, int sig, siginfo_t *info)<br>
> setpriority 140 97 (int which, int who, int nice)<br>
> diff --git a/arch/x86/syscall-x86-64.def b/arch/x86/syscall-x86-64.def<br>
> index 878cf79..112366b 100644<br>
> --- a/arch/x86/syscall-x86-64.def<br>
> +++ b/arch/x86/syscall-x86-64.def<br>
> @@ -54,11 +54,14 @@ __NR_readlink 89 sys_readlink (const char *path, char *buf, int bufsize)<br>
> __NR_umask 95 sys_umask (int mask)<br>
> __NR_getgroups 115 sys_getgroups (int gsize, unsigned int *groups)<br>
> __NR_setresuid 117 sys_setresuid (int uid, int euid, int suid)<br>
> +__NR_getresuid 118 sys_getresuid (unsigned int *uid, unsigned int *euid, unsigned int *suid)<br>
> __NR_setresgid 119 sys_setresgid (int gid, int egid, int sgid)<br>
> +__NR_getresgid 120 sys_getresgid (unsigned int *uid, unsigned int *euid, unsigned int *suid)<br>
> __NR_getpgid 121 sys_getpgid (pid_t pid)<br>
> __NR_setfsuid 122 sys_setfsuid (int fsuid)<br>
> __NR_setfsgid 123 sys_setfsgid (int fsgid)<br>
> __NR_getsid 124 sys_getsid (void)<br>
> +__NR_capget 125 sys_capget (struct cap_header *h, struct cap_data *d)<br>
> __NR_capset 126 sys_capset (struct cap_header *h, struct cap_data *d)<br>
> __NR_rt_sigqueueinfo 129 sys_rt_sigqueueinfo (pid_t pid, int sig, siginfo_t *info)<br>
> __NR_sigaltstack 131 sys_sigaltstack (const void *uss, void *uoss)<br>
> diff --git a/cr-dump.c b/cr-dump.c<br>
> index 1700d9d..b4bc8a8 100644<br>
> --- a/cr-dump.c<br>
> +++ b/cr-dump.c<br>
> @@ -497,8 +497,7 @@ err:<br>
> }<br>
><br>
> static int dump_task_creds(struct parasite_ctl *ctl,<br>
> - const struct cr_fdset *fds,<br>
> - struct proc_status_creds *cr)<br>
> + const struct cr_fdset *fds)<br>
> {<br>
> CredsEntry ce = CREDS_ENTRY__INIT;<br>
><br>
> @@ -506,26 +505,6 @@ static int dump_task_creds(struct parasite_ctl *ctl,<br>
> pr_info("Dumping creds for %d)\n", ctl->pid.real);<br>
> pr_info("----------------------------------------\n");<br>
><br>
> - ce.uid = cr->uids[0];<br>
> - ce.gid = cr->gids[0];<br>
> - ce.euid = cr->uids[1];<br>
> - ce.egid = cr->gids[1];<br>
> - ce.suid = cr->uids[2];<br>
> - ce.sgid = cr->gids[2];<br>
> - ce.fsuid = cr->uids[3];<br>
> - ce.fsgid = cr->gids[3];<br>
> -<br>
> - BUILD_BUG_ON(CR_CAP_SIZE != PROC_CAP_SIZE);<br>
> -<br>
> - ce.n_cap_inh = CR_CAP_SIZE;<br>
> - ce.cap_inh = cr->cap_inh;<br>
> - ce.n_cap_prm = CR_CAP_SIZE;<br>
> - ce.cap_prm = cr->cap_prm;<br>
> - ce.n_cap_eff = CR_CAP_SIZE;<br>
> - ce.cap_eff = cr->cap_eff;<br>
> - ce.n_cap_bnd = CR_CAP_SIZE;<br>
> - ce.cap_bnd = cr->cap_bnd;<br>
> -<br>
> if (parasite_dump_creds(ctl, &ce) < 0)<br>
> return -1;<br>
><br>
> @@ -1608,7 +1587,7 @@ static int dump_one_task(struct pstree_item *item)<br>
> goto err_cure;<br>
> }<br>
><br>
> - ret = dump_task_creds(parasite_ctl, cr_fdset, &cr);<br>
> + ret = dump_task_creds(parasite_ctl, cr_fdset);<br>
> if (ret) {<br>
> pr_err("Dump creds (pid: %d) failed with %d\n", pid, ret);<br>
> goto err;<br>
> diff --git a/include/parasite.h b/include/parasite.h<br>
> index af81d85..a6a60bb 100644<br>
> --- a/include/parasite.h<br>
> +++ b/include/parasite.h<br>
> @@ -166,10 +166,24 @@ struct parasite_dump_misc {<br>
> * Calculate how long we can make the groups array in parasite_dump_creds<br>
> * and still fit the struct in one page<br>
> */<br>
> -#define PARASITE_MAX_GROUPS \<br>
> - ((PAGE_SIZE - 2 * sizeof(unsigned int)) / sizeof(unsigned int))<br>
> +#define PARASITE_MAX_GROUPS \<br>
> + (PAGE_SIZE \<br>
> + - sizeof(unsigned int) /* cap_last_cap */ \<br>
> + - 8 * sizeof(unsigned int) /* uids + gids */ \<br>
> + - 4 * CR_CAP_SIZE * sizeof(u32) /* cap_{inh,prm,eff,bnd} */ \<br>
> + - 2 * sizeof(unsigned int) /* secbits, ngroups*/ \<br>
> + ) / sizeof(unsigned int) /* groups */<br>
><br>
> struct parasite_dump_creds {<br>
> + unsigned int cap_last_cap;<br>
> + unsigned int uids[4];<br>
> + unsigned int gids[4];<br>
> +<br>
> + u32 cap_inh[CR_CAP_SIZE];<br>
> + u32 cap_prm[CR_CAP_SIZE];<br>
> + u32 cap_eff[CR_CAP_SIZE];<br>
> + u32 cap_bnd[CR_CAP_SIZE];<br>
> +<br>
> unsigned int secbits;<br>
> unsigned int ngroups;<br>
> unsigned int groups[PARASITE_MAX_GROUPS];<br>
> diff --git a/include/prctl.h b/include/prctl.h<br>
> index b815b96..70db7b9 100644<br>
> --- a/include/prctl.h<br>
> +++ b/include/prctl.h<br>
> @@ -7,6 +7,9 @@<br>
> #ifndef PR_GET_NAME<br>
> # define PR_GET_NAME 16<br>
> #endif<br>
> +#ifndef PR_CAPBSET_READ<br>
> +# define PR_CAPBSET_READ 23<br>
> +#endif<br>
> #ifndef PR_CAPBSET_DROP<br>
> # define PR_CAPBSET_DROP 24<br>
> #endif<br>
> diff --git a/kerndat.c b/kerndat.c<br>
> index 0fee20b..3c87f6c 100644<br>
> --- a/kerndat.c<br>
> +++ b/kerndat.c<br>
> @@ -229,6 +229,8 @@ int kerndat_init(void)<br>
> ret = kerndat_get_dirty_track();<br>
> if (!ret)<br>
> ret = init_zero_page_pfn();<br>
> + if (!ret)<br>
> + ret = get_last_cap();<br>
><br>
> return ret;<br>
> }<br>
> diff --git a/parasite-syscall.c b/parasite-syscall.c<br>
> index dad2570..7e52108 100644<br>
> --- a/parasite-syscall.c<br>
> +++ b/parasite-syscall.c<br>
> @@ -738,9 +738,29 @@ int parasite_dump_creds(struct parasite_ctl *ctl, CredsEntry *ce)<br>
> BUILD_BUG_ON(sizeof(*pc) > PAGE_SIZE);<br>
><br>
> pc = parasite_args(ctl, struct parasite_dump_creds);<br>
> + pc->cap_last_cap = kern_last_cap;<br>
> +<br>
> if (parasite_execute_daemon(PARASITE_CMD_DUMP_CREDS, ctl) < 0)<br>
> return -1;<br>
><br>
> + ce->uid = pc->uids[0];<br>
> + ce->gid = pc->gids[0];<br>
> + ce->euid = pc->uids[1];<br>
> + ce->egid = pc->gids[1];<br>
> + ce->suid = pc->uids[2];<br>
> + ce->sgid = pc->gids[2];<br>
> + ce->fsuid = pc->uids[3];<br>
> + ce->fsgid = pc->gids[3];<br>
> +<br>
> + ce->n_cap_inh = CR_CAP_SIZE;<br>
> + ce->cap_inh = pc->cap_inh;<br>
> + ce->n_cap_prm = CR_CAP_SIZE;<br>
> + ce->cap_prm = pc->cap_prm;<br>
> + ce->n_cap_eff = CR_CAP_SIZE;<br>
> + ce->cap_eff = pc->cap_eff;<br>
> + ce->n_cap_bnd = CR_CAP_SIZE;<br>
> + ce->cap_bnd = pc->cap_bnd;<br>
> +<br>
> ce->secbits = pc->secbits;<br>
> ce->n_groups = pc->ngroups;<br>
><br>
> diff --git a/pie/parasite.c b/pie/parasite.c<br>
> index 92e7708..948718f 100644<br>
> --- a/pie/parasite.c<br>
> +++ b/pie/parasite.c<br>
> @@ -2,6 +2,7 @@<br>
> #include <errno.h><br>
> #include <signal.h><br>
> #include <linux/limits.h><br>
> +#include <linux/capability.h><br>
> #include <sys/mount.h><br>
> #include <stdarg.h><br>
> #include <sys/ioctl.h><br>
> @@ -177,7 +178,59 @@ static int dump_misc(struct parasite_dump_misc *args)<br>
><br>
> static int dump_creds(struct parasite_dump_creds *args)<br>
> {<br>
> - int ret;<br>
> + int ret, i, j;<br>
> + struct cap_data data[_LINUX_CAPABILITY_U32S_3];<br>
> + struct cap_header hdr = {_LINUX_CAPABILITY_VERSION_3, 0};<br>
> +<br>
> + ret = sys_getresuid(&args->uids[0], &args->uids[1], &args->uids[2]);<br>
> + if (ret < 0) {<br>
> + pr_err("Error calling getresuid (%d)\n", ret);<br>
> + return -1;<br>
> + }<br>
> +<br>
> + ret = sys_getresgid(&args->gids[0], &args->gids[1], &args->gids[2]);<br>
> + if (ret < 0) {<br>
> + pr_err("Error calling getresgid (%d)\n", ret);<br>
> + return -1;<br>
> + }<br>
> +<br>
> + /*<br>
> + * There is no getfsuid syscall, but setfsuid returns the existing<br>
> + * fsuid on failure, so just call it with an invalid uid.<br>
> + */<br>
> + args->uids[3] = sys_setfsuid(-1);<br>
> + args->gids[3] = sys_setfsgid(-1);<br>
> +<br>
> + ret = sys_capget(&hdr, data);<br>
> + if (ret < 0) {<br>
> + pr_err("Unable to get capabilities: %d\n", ret);<br>
> + return -1;<br>
> + }<br>
> +<br>
> + /*<br>
> + * Loop through the capability constants until we reach cap_last_cap.<br>
> + * The cap_bnd set is stored as a bitmask comprised of CR_CAP_SIZE number of<br>
> + * 32-bit uints, hence the inner loop from 0 to 32.<br>
> + */<br>
> + for (i = 0; i < CR_CAP_SIZE; i++) {<br>
> + args->cap_eff[i] = data[i].eff;<br>
> + args->cap_prm[i] = data[i].prm;<br>
> + args->cap_inh[i] = data[i].inh;<br>
> + args->cap_bnd[i] = 0;<br>
> +<br>
> + for (j = 0; j < 32; j++) {<br>
> + if (j + i * 32 > args->cap_last_cap)<br>
> + break;<br>
> + ret = sys_prctl(PR_CAPBSET_READ, j + i * 32, 0, 0, 0);<br>
> + if (ret < 0) {<br>
> + pr_err("Unable to read capability %d: %d\n",<br>
> + j + i * 32, ret);<br>
> + return -1;<br>
> + }<br>
> + if (ret)<br>
> + args->cap_bnd[i] |= (1 << j);<br>
> + }<br>
> + }<br>
><br>
> args->secbits = sys_prctl(PR_GET_SECUREBITS, 0, 0, 0, 0);<br>
><br>
> diff --git a/security.c b/security.c<br>
> index a801005..8a991d0 100644<br>
> --- a/security.c<br>
> +++ b/security.c<br>
> @@ -157,6 +157,12 @@ bool may_dump(struct proc_status_creds *creds)<br>
> check_caps(creds->cap_inh, creds->cap_eff, creds->cap_prm);<br>
> }<br>
><br>
> +/*<br>
> + * TODO: The check_ids calls may incorrectly fail if criu is started by a<br>
> + * non-root user on a process in a user namespace, whose uid/gid matches the<br>
> + * caller's outside the namespace but is mapped to a different uid/gid<br>
> + * inside it.<br>
> + */<br>
> bool may_restore(CredsEntry *creds)<br>
> {<br>
> return check_uids(creds->uid, creds->euid, creds->suid) &&<br>
> --<br>
> 2.0.0.526.g5318336<br>
><br>
</div></div>> _______________________________________________<br>
> CRIU mailing list<br>
> <a href="mailto:CRIU@openvz.org">CRIU@openvz.org</a><br>
> <a href="https://lists.openvz.org/mailman/listinfo/criu" target="_blank">https://lists.openvz.org/mailman/listinfo/criu</a><br>
</blockquote></div><br></div>