int main() { int pid; int fds[3]; int spair[2]; sys_chk(socketpair(AF_UNIX, SOCK_STREAM, 0, spair)); sys_chk(pid = fork()); if (pid == 0) { // Child. sys_chk(fds[0] = open("/etc/passwd", O_RDONLY)); sys_chk(lseek(fds[0], 5, SEEK_SET)); sys_chk(fds[1] = open("/etc/group", O_RDONLY)); sys_chk(lseek(fds[1], 10, SEEK_SET)); sys_chk(fds[2] = open("/bin/sh", O_RDONLY)); sys_chk(lseek(fds[2], 20, SEEK_SET)); send_fds(spair[0], fds, 3); return EXIT_SUCCESS; } else { // Parent. int *fds; int fds_len; recv_fds(spair[1], &fds, &fds_len); printf("parent: got fds:"); for (int i = 0; i < fds_len; ++i) { printf(" %d (fp=%lld)", fds[i], (long long)lseek(fds[i], 0, SEEK_CUR)); } printf("\n"); return EXIT_SUCCESS; } }
int parasite_drain_fds_seized(struct parasite_ctl *ctl, struct parasite_drain_fd *dfds, int *lfds, struct fd_opts *opts) { int ret = -1, size; struct parasite_drain_fd *args; size = drain_fds_size(dfds); args = parasite_args_s(ctl, size); memcpy(args, dfds, size); ret = parasite_execute(PARASITE_CMD_DRAIN_FDS, ctl); if (ret) { pr_err("Parasite failed to drain descriptors\n"); goto err; } ret = recv_fds(ctl->tsock, lfds, dfds->nr_fds, opts); if (ret) { pr_err("Can't retrieve FDs from socket\n"); goto err; } err: return ret; }
int do_recvmsg(message *dev_m_in, message *dev_m_out) { int minor; int rc; struct msg_control msg_ctrl; socklen_t controllen_avail = 0; socklen_t controllen_needed = 0; socklen_t controllen_desired = 0; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] do_sendmsg() call_count=%d\n", uds_minor(dev_m_in), ++call_count); #endif minor = uds_minor(dev_m_in); #if DEBUG == 1 printf("(uds) [%d] CREDENTIALS {pid:%d,uid:%d,gid:%d}\n", minor, uds_fd_table[minor].ancillary_data.cred.pid, uds_fd_table[minor].ancillary_data.cred.uid, uds_fd_table[minor].ancillary_data.cred.gid); #endif memset(&msg_ctrl, '\0', sizeof(struct msg_control)); /* get the msg_control from the user, it will include the * amount of space the user has allocated for control data. */ rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &msg_ctrl, sizeof(struct msg_control)); if (rc != OK) { return EIO; } controllen_avail = MIN(msg_ctrl.msg_controllen, MSG_CONTROL_MAX); if (uds_fd_table[minor].ancillary_data.nfiledes > 0) { controllen_needed = CMSG_LEN(sizeof(int) * (uds_fd_table[minor].ancillary_data.nfiledes)); } /* if there is room we also include credentials */ controllen_desired = controllen_needed + CMSG_LEN(sizeof(struct ucred)); if (controllen_needed > controllen_avail) { return EOVERFLOW; } rc = recv_fds(minor, &uds_fd_table[minor].ancillary_data, &msg_ctrl); if (rc != OK) { return rc; } if (controllen_desired <= controllen_avail) { rc = recv_cred(minor, &uds_fd_table[minor].ancillary_data, &msg_ctrl); if (rc != OK) { return rc; } } /* send the user the control data */ rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0, (vir_bytes) &msg_ctrl, sizeof(struct msg_control)); return rc ? EIO : OK; }