/* send(pfd, "x", sizeof(char), 0) */ if (data != 'x') {
log_err("recvmsg: data corruption"); return1;
}
if (parse_cmsg(&msg, &res)) {
log_err("CMSG parse: parse_cmsg() failed"); return1;
}
/* pidfd from SCM_PIDFD should point to the parent process PID */
parent_pid =
get_pid_from_fdinfo_file(*res.pidfd, "Pid:", sizeof("Pid:") - 1); if (parent_pid != getppid()) {
log_err("wrong SCM_PIDFD %d != %d", parent_pid, getppid());
close(*res.pidfd); return1;
}
close(*res.pidfd); return0;
}
staticint cmsg_check_dead(int fd, int expected_pid)
{ int err; struct msghdr msg = { 0 }; struct cmsg_data res; struct iovec iov; int data = 0; char control[CMSG_SPACE(sizeof(struct ucred)) +
CMSG_SPACE(sizeof(int))] = { 0 };
pid_t client_pid; struct pidfd_info info = {
.mask = PIDFD_INFO_EXIT,
};
/* send(cfd, "y", sizeof(char), 0) */ if (data != 'y') {
log_err("recvmsg: data corruption"); return1;
}
if (parse_cmsg(&msg, &res)) {
log_err("CMSG parse: parse_cmsg() failed"); return1;
}
/* * pidfd from SCM_PIDFD should point to the client_pid. * Let's read exit information and check if it's what * we expect to see.
*/ if (ioctl(*res.pidfd, PIDFD_GET_INFO, &info)) {
log_err("%s: ioctl(PIDFD_GET_INFO) failed", __func__);
close(*res.pidfd); return1;
}
if (!(info.mask & PIDFD_INFO_EXIT)) {
log_err("%s: No exit information from ioctl(PIDFD_GET_INFO)", __func__);
close(*res.pidfd); return1;
}
if (sk_enable_cred_pass(cfd)) {
log_err("sk_enable_cred_pass() failed");
child_die();
}
close(self->startup_pipe[1]);
if (cmsg_check(cfd)) {
log_err("cmsg_check failed");
child_die();
}
/* send something to the parent so it can receive SCM_PIDFD too and validate it */ if (send(cfd, "y", sizeof(char), 0) == -1) {
log_err("Failed to send(cfd, \"y\", sizeof(char), 0)");
child_die();
}
/* skip further for SOCK_DGRAM as it's not applicable */ if (variant->type == SOCK_DGRAM) return;
len = sizeof(peer_cred); if (getsockopt(cfd, SOL_SOCKET, SO_PEERCRED, &peer_cred, &len)) {
log_err("Failed to get SO_PEERCRED");
child_die();
}
len = sizeof(peer_pidfd); if (getsockopt(cfd, SOL_SOCKET, SO_PEERPIDFD, &peer_pidfd, &len)) {
log_err("Failed to get SO_PEERPIDFD");
child_die();
}
/* pid from SO_PEERCRED should point to the parent process PID */ if (peer_cred.pid != getppid()) {
log_err("peer_cred.pid != getppid(): %d != %d", peer_cred.pid, getppid());
child_die();
}
/* * It's a bit unusual, but in case of success we return non-zero * exit code (CHILD_EXIT_CODE_OK) and then we expect to read it * from ioctl(PIDFD_GET_INFO) in cmsg_check_dead().
*/ exit(CHILD_EXIT_CODE_OK);
}
close(self->startup_pipe[1]);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.