int toi_netlink_setup(struct user_helper_data *uhd) { /* In case userui didn't cleanup properly on us */ toi_netlink_close_complete(uhd); if (netlink_prepare(uhd) < 0) { printk(KERN_INFO "Netlink prepare failed.\n"); return 1; } if (toi_launch_userspace_program(uhd->program, uhd->netlink_id, UMH_WAIT_EXEC, uhd->debug) < 0) { printk(KERN_INFO "Launch userspace program failed.\n"); toi_netlink_close_complete(uhd); return 1; } /* Wait 2 seconds for the userspace process to make contact */ wait_for_completion_timeout(&uhd->wait_for_process, 2*HZ); if (uhd->pid == -1) { printk(KERN_INFO "%s: Failed to contact userspace process.\n", uhd->name); toi_netlink_close_complete(uhd); return 1; } return 0; }
static int toi_nl_gen_rcv_msg(struct user_helper_data *uhd, struct sk_buff *skb, struct nlmsghdr *nlh) { int type = nlh->nlmsg_type; int *data; int err; if (uhd->debug) printk(KERN_ERR "toi_user_rcv_skb: Received message %d.\n", type); /* Let the more specific handler go first. It returns * 1 for valid messages that it doesn't know. */ err = uhd->rcv_msg(skb, nlh); if (err != 1) return err; /* Only allow one task to receive NOFREEZE privileges */ if (type == NETLINK_MSG_NOFREEZE_ME && uhd->pid != -1) { printk(KERN_INFO "Received extra nofreeze me requests.\n"); return -EBUSY; } data = NLMSG_DATA(nlh); switch (type) { case NETLINK_MSG_NOFREEZE_ME: return nl_set_nofreeze(uhd, nlh->nlmsg_pid); case NETLINK_MSG_GET_DEBUGGING: send_whether_debugging(uhd); return 0; case NETLINK_MSG_READY: if (nlh->nlmsg_len != NLMSG_LENGTH(sizeof(u32))) { printk(KERN_INFO "Invalid ready mesage.\n"); if (uhd->not_ready) uhd->not_ready(); return -EINVAL; } return nl_ready(uhd, (u32) *data); case NETLINK_MSG_CLEANUP: toi_netlink_close_complete(uhd); return 0; } return -EINVAL; }
static int netlink_prepare(struct user_helper_data *uhd) { struct netlink_kernel_cfg cfg = { .groups = 0, .input = toi_user_rcv_skb, }; uhd->next = uhd_list; uhd_list = uhd; uhd->sock_seq = 0x42c0ffee; uhd->nl = netlink_kernel_create(&init_net, uhd->netlink_id, &cfg); if (!uhd->nl) { printk(KERN_INFO "Failed to allocate netlink socket for %s.\n", uhd->name); return -ENOMEM; } toi_fill_skb_pool(uhd); return 0; } void toi_netlink_close(struct user_helper_data *uhd) { struct task_struct *t; toi_read_lock_tasklist(); t = find_task_by_pid_ns(uhd->pid, &init_pid_ns); if (t) t->flags &= ~PF_NOFREEZE; toi_read_unlock_tasklist(); toi_send_netlink_message(uhd, NETLINK_MSG_CLEANUP, NULL, 0); } EXPORT_SYMBOL_GPL(toi_netlink_close); int toi_netlink_setup(struct user_helper_data *uhd) { /* In case userui didn't cleanup properly on us */ toi_netlink_close_complete(uhd); if (netlink_prepare(uhd) < 0) { printk(KERN_INFO "Netlink prepare failed.\n"); return 1; } if (toi_launch_userspace_program(uhd->program, uhd->netlink_id, UMH_WAIT_EXEC, uhd->debug) < 0) { printk(KERN_INFO "Launch userspace program failed.\n"); toi_netlink_close_complete(uhd); return 1; } /* Wait 2 seconds for the userspace process to make contact */ wait_for_completion_timeout(&uhd->wait_for_process, 2*HZ); if (uhd->pid == -1) { printk(KERN_INFO "%s: Failed to contact userspace process.\n", uhd->name); toi_netlink_close_complete(uhd); return 1; } return 0; }
void toi_usm_exit(void) { toi_netlink_close_complete(&usm_helper_data); toi_unregister_module(&usm_ops); }