[CRIU] [PATCH 1/4] sk-unix: Save mnt_id for bindmounted entries
Andrey Vagin
avagin at virtuozzo.com
Wed Aug 30 02:24:04 MSK 2017
On Tue, Aug 08, 2017 at 02:25:07PM +0300, Cyrill Gorcunov wrote:
> Mount points might be beindmount to some resources (say unix binded
> sockets) thus when times come to do real bind mount call we need
> to prepare appropriate resource first.
>
> On dump procedure we walk over all bind-mounts and check if
> the mountpoint is a unix socket saving the mnt_id into the image
> then.
>
> Note at moment we support only DGRAM closed sockets.
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> criu/cr-dump.c | 3 +++
> criu/include/sockets.h | 1 +
> criu/sk-unix.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
> images/sk-unix.proto | 5 ++++
> 4 files changed, 78 insertions(+)
>
> diff --git a/criu/cr-dump.c b/criu/cr-dump.c
> index 06f3966c05cf..52857dc6c1c7 100644
> --- a/criu/cr-dump.c
> +++ b/criu/cr-dump.c
> @@ -1898,6 +1898,9 @@ int cr_dump_tasks(pid_t pid)
> if (collect_namespaces(true) < 0)
> goto err;
>
> + if (collect_unix_bindmounts() < 0)
> + goto err;
> +
> glob_imgset = cr_glob_imgset_open(O_DUMP);
> if (!glob_imgset)
> goto err;
> diff --git a/criu/include/sockets.h b/criu/include/sockets.h
> index 9881d5bf3bc1..64673c5e5dc8 100644
> --- a/criu/include/sockets.h
> +++ b/criu/include/sockets.h
> @@ -37,6 +37,7 @@ extern int collect_sockets(struct ns_id *);
> extern struct collect_image_info inet_sk_cinfo;
> extern struct collect_image_info unix_sk_cinfo;
> extern int fix_external_unix_sockets(void);
> +extern int collect_unix_bindmounts(void);
>
> extern struct collect_image_info netlink_sk_cinfo;
>
> diff --git a/criu/sk-unix.c b/criu/sk-unix.c
> index 765d9ae9bddc..bf013c5ca4de 100644
> --- a/criu/sk-unix.c
> +++ b/criu/sk-unix.c
> @@ -86,6 +86,10 @@ struct unix_sk_desc {
> struct list_head peer_node;
>
> UnixSkEntry *ue;
> +
> + /* To handle bindmounts over socks */
> + struct unix_diag_vfs uv; /* FIXME merge with rel_name_desc_t */
> + int mnt_id;
> };
>
> static LIST_HEAD(unix_sockets);
> @@ -314,6 +318,11 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
> ue->opts = skopts;
> ue->uflags = 0;
>
> + if (sk->mnt_id) {
> + ue->has_mnt_id = true;
> + ue->mnt_id = sk->mnt_id;
> + }
> +
> if (sk->rel_name) {
> if (resolve_rel_name(sk, p))
> goto err;
> @@ -533,6 +542,8 @@ static int unix_process_name(struct unix_sk_desc *d, const struct unix_diag_msg
> }
>
> uv = RTA_DATA(tb[UNIX_DIAG_VFS]);
> + memcpy(&d->uv, uv, sizeof(d->uv));
> +
> if (name[0] != '/') {
> /*
> * Relative names are be resolved later at first
> @@ -787,6 +798,64 @@ int fix_external_unix_sockets(void)
> return -1;
> }
>
> +int collect_unix_bindmounts(void)
> +{
> + int mntns_fd, old_ns = -1;
> + struct mount_info *mi;
> + struct stat st = {};
> + int ret = 0;
> +
> + for (mi = mntinfo; mi; mi = mi->next) {
> + if (list_empty(&mi->mnt_bind))
> + continue;
> +
> + mntns_fd = open_proc(mi->nsid->ns_pid, "ns/mnt");
> + if (mntns_fd < 0) {
> + pr_err("Can't open %d/ns/mnt\n", mi->nsid->ns_pid);
> + return -1;
> + }
> +
> + if (switch_ns_by_fd(mntns_fd, &mnt_ns_desc, &old_ns)) {
> + pr_err("Can't switch mount ns for %d\n", mi->nsid->ns_pid);
> + return -1;
> + }
> +
> + if (stat(mi->mountpoint, &st)) {
> + pr_perror("Can't stat on %s", mi->mountpoint);
> + return switch_ns_by_fd(old_ns, &mnt_ns_desc, NULL);
> + }
> +
> + if (S_ISSOCK(st.st_mode)) {
> + struct unix_sk_desc *sk;
> +
> + list_for_each_entry(sk, &unix_sockets, list) {
> + if (sk->uv.udiag_vfs_ino == (int)st.st_ino &&
> + sk->uv.udiag_vfs_dev == (int)st.st_dev) {
> + pr_debug("Found sock s_dev %#x ino %#x bindmounted mnt_id %d %s\n",
> + (int)st.st_dev, (int)st.st_ino, mi->mnt_id, mi->mountpoint);
> + sk->mnt_id = mi->mnt_id;
> + if (sk->type != SOCK_DGRAM && sk->state != TCP_CLOSE) {
> + pr_err("Unsupported bindmounted socket ino %#x at %s\n",
> + (int)st.st_ino, mi->mountpoint);
> + ret = -1;
> + break;
> + }
> + }
> + }
You have to report an error, if you can't find a socker.
> + }
> +
> + if (switch_ns_by_fd(old_ns, &mnt_ns_desc, NULL)) {
> + pr_err("Can't switch mount ns back from %d\n", mi->nsid->ns_pid);
> + return -1;
> + }
> +
> + if (ret)
> + break;
> + }
> +
> + return ret;
> +}
> +
> struct unix_sk_info {
> UnixSkEntry *ue;
> struct list_head list;
> diff --git a/images/sk-unix.proto b/images/sk-unix.proto
> index 2a33fe220d1e..9186e23f4062 100644
> --- a/images/sk-unix.proto
> +++ b/images/sk-unix.proto
> @@ -50,4 +50,9 @@ message unix_sk_entry {
> optional bool deleted = 15;
>
> optional uint32 ns_id = 16;
> +
> + /*
> + * Bind-mounted sockets.
> + */
> + optional uint32 mnt_id = 17;
A socket can be bind-mounted in a few places.
> }
> --
> 2.7.5
>
More information about the CRIU
mailing list