static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid, struct parasite_init_args *args) { int ssock = -1; socklen_t sk_len; struct sockaddr_un addr; pr_info("Putting tsock into pid %d\n", pid); args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid()); ssock = ctl->ictx.sock; sk_len = sizeof(addr); if (ssock == -1) { pr_err("No socket in ictx\n"); goto err; } if (getsockname(ssock, (struct sockaddr *) &addr, &sk_len) < 0) { pr_perror("Unable to get name for a socket"); return -1; } if (sk_len == sizeof(addr.sun_family)) { if (bind(ssock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) { pr_perror("Can't bind socket"); goto err; } if (listen(ssock, 1)) { pr_perror("Can't listen on transport socket"); goto err; } } /* Check a case when parasite can't initialize a command socket */ if (ctl->ictx.flags & INFECT_FAIL_CONNECT) args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid() + 1); /* * Set to -1 to prevent any accidental misuse. The * only valid user of it is accept_tsock(). */ ctl->tsock = -ssock; return 0; err: close_safe(&ssock); return -1; }
static int parasite_init(struct parasite_ctl *ctl, pid_t pid, int nr_threads) { struct parasite_init_args *args; static int sock = -1; args = parasite_args(ctl, struct parasite_init_args); pr_info("Putting tsock into pid %d\n", pid); args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid()); args->p_addr_len = gen_parasite_saddr(&args->p_addr, pid); args->nr_threads = nr_threads; if (sock == -1) { int rst = -1; if (current_ns_mask & CLONE_NEWNET) { pr_info("Switching to %d's net for tsock creation\n", pid); if (switch_ns(pid, &net_ns_desc, &rst)) return -1; } sock = socket(PF_UNIX, SOCK_DGRAM, 0); if (sock < 0) pr_perror("Can't create socket"); if (rst > 0 && restore_ns(rst, &net_ns_desc) < 0) return -1; if (sock < 0) return -1; if (bind(sock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) { pr_perror("Can't bind socket"); goto err; } } else { struct sockaddr addr = { .sa_family = AF_UNSPEC, }; /* * When the peer of a dgram socket dies the original socket * remains in connected state, thus denying any connections * from "other" sources. Unconnect the socket by hands thus * allowing for parasite to connect back. */ if (connect(sock, &addr, sizeof(addr)) < 0) { pr_perror("Can't unconnect"); goto err; } } if (parasite_execute(PARASITE_CMD_INIT, ctl) < 0) { pr_err("Can't init parasite\n"); goto err; } if (connect(sock, (struct sockaddr *)&args->p_addr, args->p_addr_len) < 0) { pr_perror("Can't connect a transport socket"); goto err; } ctl->tsock = sock; return 0; err: close_safe(&sock); return -1; }