mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-17 16:47:50 +00:00
netlink: dump and restore ucred-s for netlink messages
ucred in a netlink message contains the same pid and it doesn't metter from which pidns it is read. Cc: Kirill Tkhai <ktkhai@virtuozzo.com> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com> Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com> (cherry picked from commit 66f8f7b2ae51a2cef4044df478389137735e1d6e) Ahmed Elaidy: - dropped the ENOBUFS bits (SK_QUEUE_TRACK_ENOBUFS and the int *val out-parameter): they belong to "netlink: save and generate ENOBUFS at restore", which needs a non-upstream kernel extension and is intentionally not ported. - SK_QUEUE_DUMP_ADDR / the int flags signature come from the preceding "sk-queue: use flags in dump_sk_queue" cherry-pick rather than being glued in here. Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com> Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
This commit is contained in:
parent
86a3c42dda
commit
832801cd81
4 changed files with 85 additions and 5 deletions
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
extern struct collect_image_info sk_queues_cinfo;
|
||||
|
||||
#define SK_QUEUE_REAL_PID 0x1 /* scm creds contains a real pid */
|
||||
extern int dump_sk_queue(int sock_fd, int sock_id, int flags);
|
||||
extern int restore_sk_queue(int fd, unsigned int peer_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
#include "util-pie.h"
|
||||
#include "sockets.h"
|
||||
#include "xmalloc.h"
|
||||
#include "namespaces.h"
|
||||
#include "pstree.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "sk-queue.h"
|
||||
#include "files.h"
|
||||
#include "protobuf.h"
|
||||
|
|
@ -132,7 +136,49 @@ static int dump_scm_rights(struct cmsghdr *ch, SkPacketEntry *pe)
|
|||
*/
|
||||
#define CMSG_MAX_SIZE 2048
|
||||
|
||||
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 convert 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\n");
|
||||
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;
|
||||
int n_rights = 0;
|
||||
|
|
@ -155,6 +201,16 @@ static int dump_packet_cmsg(struct msghdr *mh, SkPacketEntry *pe)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ch->cmsg_len == CMSG_LEN(sizeof(struct ucred)) &&
|
||||
ch->cmsg_type == SCM_CREDENTIALS &&
|
||||
ch->cmsg_level == SOL_SOCKET) {
|
||||
struct ucred *ucred = (struct 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;
|
||||
}
|
||||
|
|
@ -270,7 +326,7 @@ int dump_sk_queue(int sock_fd, int sock_id, int flags)
|
|||
goto err_set_sock;
|
||||
}
|
||||
|
||||
if (dump_packet_cmsg(&msg, &pe))
|
||||
if (dump_packet_cmsg(&msg, &pe, flags))
|
||||
goto err_set_sock;
|
||||
|
||||
ret = pb_write_one(img_from_set(glob_imgset, CR_FD_SK_QUEUES), &pe, PB_SK_QUEUES);
|
||||
|
|
@ -311,6 +367,7 @@ static int send_one_pkt(int fd, struct sk_packet *pkt)
|
|||
SkPacketEntry *entry = pkt->entry;
|
||||
struct msghdr mh = {};
|
||||
struct iovec iov;
|
||||
char cmsg[CMSG_MAX_SIZE];
|
||||
|
||||
mh.msg_iov = &iov;
|
||||
mh.msg_iovlen = 1;
|
||||
|
|
@ -330,6 +387,23 @@ static int send_one_pkt(int fd, struct sk_packet *pkt)
|
|||
* boundaries messages should be saved.
|
||||
*/
|
||||
|
||||
if (entry->ucred) {
|
||||
struct ucred *ucred;
|
||||
struct cmsghdr *ch;
|
||||
|
||||
mh.msg_control = cmsg;
|
||||
mh.msg_controllen = sizeof(cmsg);
|
||||
|
||||
ch = CMSG_FIRSTHDR(&mh);
|
||||
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;
|
||||
mh.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
||||
}
|
||||
ret = sendmsg(fd, &mh, 0);
|
||||
xfree(pkt->data);
|
||||
xfree(pkt->scm);
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@ static int dump_one_unix_fd(int lfd, uint32_t id, const struct fd_parms *p)
|
|||
* (i stands for in-flight, cons -- for connections) things.
|
||||
*/
|
||||
if (sk->rqlen != 0 && sk->state != TCP_LISTEN) {
|
||||
if (dump_sk_queue(lfd, id, 0))
|
||||
if (dump_sk_queue(lfd, id, SK_QUEUE_REAL_PID))
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,17 @@ message scm_entry {
|
|||
repeated uint32 rights = 2;
|
||||
}
|
||||
|
||||
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;
|
||||
// Reserved for message address
|
||||
// optional bytes addr = 3;
|
||||
repeated scm_entry scm = 4;
|
||||
// Reserved for ucred restore
|
||||
// optional sk_ucred_entry ucred = 128;
|
||||
optional sk_ucred_entry ucred = 128;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue