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