[CRIU] [PATCH 2/2] creds: Allow to restore more restricted tasks
Andrew Vagin
avagin at virtuozzo.com
Thu Nov 26 11:51:30 PST 2015
On Thu, Nov 26, 2015 at 03:24:40PM +0300, Cyrill Gorcunov wrote:
> Currently we require the caps of children task
> (of threads) to be exactly the same as their parent
We require that all threads of one process have the same set of
capabilities, because we don't save capabilities per-thread.
Children and parent can have different capabilities.
> is havin, which doesn't allow more restircted tasks
> (which granted with less caps) to be dumped.
>
> Lets rename proc_status_creds_eq to proc_status_creds_dumpable
> and split it into two stages
>
> - compare non caps member to be the same
> - allow to proceed dumping if children are
> having less creds than a parent
>
> Note that here might be a situation when parent creates
> children/threads but then drops off own caps, for this
> scenario we will refuse to dump yet. It should be addressed
> separately.
>
> https://jira.sw.ru/PSBM-41416
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> include/proc_parse.h | 3 ++-
> proc_parse.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++----
> ptrace.c | 2 +-
> 3 files changed, 74 insertions(+), 7 deletions(-)
>
> diff --git a/include/proc_parse.h b/include/proc_parse.h
> index 6dc5e57de600..952b697dc64d 100644
> --- a/include/proc_parse.h
> +++ b/include/proc_parse.h
> @@ -103,7 +103,8 @@ struct proc_status_creds {
> u32 cap_bnd[PROC_CAP_SIZE];
> };
>
> -bool proc_status_creds_eq(struct proc_status_creds *o1, struct proc_status_creds *o2);
> +bool proc_status_creds_dumpable(struct proc_status_creds *parent,
> + struct proc_status_creds *child);
>
> struct fstype {
> char *name;
> diff --git a/proc_parse.c b/proc_parse.c
> index c479b0fa9b3c..19b8a2de0446 100644
> --- a/proc_parse.c
> +++ b/proc_parse.c
> @@ -2171,13 +2171,79 @@ int aufs_parse(struct mount_info *new)
> return ret;
> }
>
> -bool proc_status_creds_eq(struct proc_status_creds *o1, struct proc_status_creds *o2)
> +bool proc_status_creds_dumpable(struct proc_status_creds *parent,
> + struct proc_status_creds *child)
> {
> - /* FIXME: this is a little too strict, we should do semantic comparison
> - * of seccomp filters instead of forcing them to be exactly identical.
> - * It's not unsafe, though, so let's be lazy for now.
> + const size_t size = sizeof(struct proc_status_creds) -
> + offsetof(struct proc_status_creds, cap_inh);
> +
> + /*
> + * The comparision rules are the following
> + *
> + * - CAPs can be relaxed in children
> + * - seccomp filters should be passed via
> + * semantic comparision (FIXME) but for
> + * now we require them to be exactly
> + * identical
> + * - the rest of members must match
> */
> - return memcmp(o1, o2, sizeof(struct proc_status_creds)) == 0;
> +
> + if (memcmp(parent, child, size)) {
> + if (!pr_quelled(LOG_DEBUG)) {
> + pr_debug("Creds undumpable (parent:child)\n"
> + " uids: %d:%d %d:%d %d:%d %d:%d\n"
> + " gids: %d:%d %d:%d %d:%d %d:%d\n"
> + " state: %d:%d"
> + " ppid: %d:%d\n"
> + " sigpnd: %llu:%llu\n"
> + " shdpnd: %llu:%llu\n"
> + " seccomp_mode: %d:%d\n"
> + " last_filter: %u:%u\n",
> + parent->uids[0], child->uids[0],
> + parent->uids[1], child->uids[1],
> + parent->uids[2], child->uids[2],
> + parent->uids[3], child->uids[3],
> + parent->gids[0], child->gids[0],
> + parent->gids[1], child->gids[1],
> + parent->gids[2], child->gids[2],
> + parent->gids[3], child->gids[3],
> + parent->state, child->state,
> + parent->ppid, child->ppid,
> + parent->sigpnd, child->sigpnd,
> + parent->shdpnd, child->shdpnd,
> + parent->seccomp_mode, child->seccomp_mode,
> + parent->last_filter, child->last_filter);
> + }
> + return false;
> + }
> +
> + if ((child->cap_inh[0] > parent->cap_inh[0]) ||
> + (child->cap_inh[1] > parent->cap_inh[1]) ||
> + (child->cap_prm[0] > parent->cap_prm[0]) ||
> + (child->cap_prm[1] > parent->cap_prm[1]) ||
> + (child->cap_eff[0] > parent->cap_eff[0]) ||
> + (child->cap_eff[1] > parent->cap_eff[1]) ||
> + (child->cap_bnd[0] > parent->cap_bnd[0]) ||
> + (child->cap_bnd[1] > parent->cap_bnd[1])) {
> + if (!pr_quelled(LOG_DEBUG)) {
> + pr_debug("Caps undumpable (parent:child)\n"
> + " cap_inh: %#x:%#x %#x:%#x\n"
> + " cap_prm: %#x:%#x %#x:%#x\n"
> + " cap_eff: %#x:%#x %#x:%#x\n"
> + " cap_bnd: %#x:%#x %#x:%#x\n",
> + parent->cap_inh[0], child->cap_inh[0],
> + parent->cap_inh[1], child->cap_inh[1],
> + parent->cap_prm[0], child->cap_prm[0],
> + parent->cap_prm[1], child->cap_prm[1],
> + parent->cap_eff[0], child->cap_eff[0],
> + parent->cap_eff[1], child->cap_eff[1],
> + parent->cap_bnd[0], child->cap_bnd[0],
> + parent->cap_bnd[1], child->cap_bnd[1]);
> + }
> + return false;
> + }
> +
> + return true;
> }
>
> int parse_children(pid_t pid, pid_t **_c, int *_n)
> diff --git a/ptrace.c b/ptrace.c
> index 9c2b3cc80b7e..43b45bf70412 100644
> --- a/ptrace.c
> +++ b/ptrace.c
> @@ -235,7 +235,7 @@ try_again:
>
> **creds = cr;
>
> - } else if (!proc_status_creds_eq(*creds, &cr)) {
> + } else if (!proc_status_creds_dumpable(*creds, &cr)) {
> pr_err("creds don't match %d %d\n", pid, ppid);
> goto err;
> }
> --
> 2.5.0
>
More information about the CRIU
mailing list