From: Andrei Vagin <ava...@virtuozzo.com> ucred in a netlink message contains the same pid and it doesn't metter from which pidns it is read.
https://jira.sw.ru/browse/PSBM-59339 Cc: Kirill Tkhai <ktk...@virtuozzo.com> Signed-off-by: Andrei Vagin <ava...@virtuozzo.com> --- criu/include/sk-queue.h | 5 ++- criu/sk-netlink.c | 2 +- criu/sk-queue.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++--- criu/sk-unix.c | 2 +- images/sk-packet.proto | 7 +++++ 5 files changed, 91 insertions(+), 7 deletions(-) diff --git a/criu/include/sk-queue.h b/criu/include/sk-queue.h index 295a227..d03eb95 100644 --- a/criu/include/sk-queue.h +++ b/criu/include/sk-queue.h @@ -2,7 +2,10 @@ #define __CR_SK_QUEUE_H__ extern struct collect_image_info sk_queues_cinfo; -extern int dump_sk_queue(int sock_fd, int sock_id, bool dump_addr); + +#define SK_QUEUE_REAL_PID 0x1 /* scm creds contains a real pid */ +#define SK_QUEUE_DUMP_ADDR 0x2 /* save a sender address for messages */ +extern int dump_sk_queue(int sock_fd, int sock_id, int flags); extern int restore_sk_queue(int fd, unsigned int peer_id); #endif /* __CR_SK_QUEUE_H__ */ diff --git a/criu/sk-netlink.c b/criu/sk-netlink.c index 4b8ed72..89a5d9c 100644 --- a/criu/sk-netlink.c +++ b/criu/sk-netlink.c @@ -178,7 +178,7 @@ static int dump_one_netlink_fd(int lfd, u32 id, const struct fd_parms *p) if (dump_socket_opts(lfd, &skopts)) goto err; - if (kdat.has_nl_repair && dump_sk_queue(lfd, id, true)) + if (kdat.has_nl_repair && dump_sk_queue(lfd, id, SK_QUEUE_DUMP_ADDR)) goto err; if (pb_write_one(img_from_set(glob_imgset, CR_FD_NETLINK_SK), &ne, PB_NETLINK_SK)) diff --git a/criu/sk-queue.c b/criu/sk-queue.c index e4ecf80..be33ca1 100644 --- a/criu/sk-queue.c +++ b/criu/sk-queue.c @@ -19,6 +19,9 @@ #include "util.h" #include "util-pie.h" #include "sockets.h" +#include "namespaces.h" +#include "pstree.h" +#include "util.h" #include "sk-queue.h" @@ -65,11 +68,63 @@ struct collect_image_info sk_queues_cinfo = { * */ #define CMSG_MAX_SIZE 1024 -static int dump_packet_cmsg(struct msghdr *mh, SkPacketEntry *pe) +static int dump_sk_creds(struct ucred *ucred, SkPacketEntry *pe, int flags) +{ + SkUcredEntry *ent; + + ent = xmalloc(sizeof(*ent)); + if (!ent) + return -1; + + sk_ucred_entry__init(ent); + ent->uid = userns_uid(ucred->uid); + ent->gid = userns_gid(ucred->gid); + if (flags & SK_QUEUE_REAL_PID) { + /* + * It is impossible to conver pid from real to virt, + * because virt pid-s are known for dumped task only + */ + pr_err("ucred-s for unix sockets aren't supported yet"); + return -1; + } else { + int pidns = root_ns_mask & CLONE_NEWPID; + char path[64]; + int ret; + + /* Does a process exist? */ + if (pidns) { + snprintf(path, sizeof(path), "%d", ucred->pid); + ret = faccessat(get_service_fd(CR_PROC_FD_OFF), + path, R_OK, 0); + } else { + snprintf(path, sizeof(path), "/proc/%d", ucred->pid); + ret = access(path, R_OK); + } + if (ret) { + pr_err("Unable to dump ucred for a dead process %d\n", ucred->pid); + return -1; + } + ent->pid = ucred->pid; + } + pe->ucred = ent; + + return 0; +} + +static int dump_packet_cmsg(struct msghdr *mh, SkPacketEntry *pe, int flags) { struct cmsghdr *ch; for (ch = CMSG_FIRSTHDR(mh); ch; ch = CMSG_NXTHDR(mh, ch)) { + if (ch->cmsg_len == CMSG_LEN(sizeof(struct ucred)) && + ch->cmsg_type == SCM_CREDENTIALS && + ch->cmsg_level == SOL_SOCKET) { + struct ucred *ucred = CMSG_DATA(ch); + + if (dump_sk_creds(ucred, pe, flags)) + return -1; + continue; + } pr_err("Control messages in queue, not supported\n"); return -1; } @@ -77,7 +132,7 @@ static int dump_packet_cmsg(struct msghdr *mh, SkPacketEntry *pe) return 0; } -int dump_sk_queue(int sock_fd, int sock_id, bool dump_addr) +int dump_sk_queue(int sock_fd, int sock_id, int flags) { SkPacketEntry pe = SK_PACKET_ENTRY__INIT; int ret, size, orig_peek_off; @@ -140,7 +195,7 @@ int dump_sk_queue(int sock_fd, int sock_id, bool dump_addr) .msg_controllen = sizeof(cmsg), }; - if (dump_addr) { + if (flags & SK_QUEUE_DUMP_ADDR) { msg.msg_name = addr; msg.msg_namelen = _K_SS_MAXSIZE; } @@ -168,7 +223,7 @@ int dump_sk_queue(int sock_fd, int sock_id, bool dump_addr) goto err_set_sock; } - if (dump_packet_cmsg(&msg, &pe)) + if (dump_packet_cmsg(&msg, &pe, flags)) goto err_set_sock; if (msg.msg_namelen) { @@ -229,6 +284,7 @@ int restore_sk_queue(int fd, unsigned int peer_id) .msg_iov = &iov, .msg_iovlen = 1, }; + char cmsg[1024]; if (entry->id_for != peer_id) continue; @@ -264,6 +320,24 @@ int restore_sk_queue(int fd, unsigned int peer_id) goto err; } + if (entry->ucred) { + struct ucred *ucred; + struct cmsghdr *ch; + + msg.msg_control = cmsg; + msg.msg_controllen = sizeof(cmsg); + + ch = CMSG_FIRSTHDR(&msg); + ch->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + ch->cmsg_level = SOL_SOCKET; + ch->cmsg_type = SCM_CREDENTIALS; + ucred = (struct ucred *) CMSG_DATA(ch); + ucred->pid = entry->ucred->pid; + ucred->uid = entry->ucred->uid; + ucred->gid = entry->ucred->gid; + msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); + } + ret = sendmsg(fd, &msg, 0); xfree(buf); if (ret < 0) { diff --git a/criu/sk-unix.c b/criu/sk-unix.c index edd9d0b..0cf10b0 100644 --- a/criu/sk-unix.c +++ b/criu/sk-unix.c @@ -464,7 +464,7 @@ dump: */ if (sk->rqlen != 0 && !(sk->type == SOCK_STREAM && sk->state == TCP_LISTEN)) - if (dump_sk_queue(lfd, id, false)) + if (dump_sk_queue(lfd, id, SK_QUEUE_REAL_PID)) goto err; pr_info("Dumping unix socket at %d\n", p->fd); diff --git a/images/sk-packet.proto b/images/sk-packet.proto index 59c0e79..4bfc774 100644 --- a/images/sk-packet.proto +++ b/images/sk-packet.proto @@ -1,7 +1,14 @@ syntax = "proto2"; +message sk_ucred_entry { + required uint32 uid = 1; + required uint32 gid = 2; + required uint32 pid = 3; +} + message sk_packet_entry { required uint32 id_for = 1; required uint32 length = 2; optional bytes addr = 3; + optional sk_ucred_entry ucred = 128; } -- 1.8.3.1 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel