/* * Set the PF_NOFREEZE flag on the given process to ensure it can run whilst we * are hibernating. */ static int nl_set_nofreeze(struct user_helper_data *uhd, __u32 pid) { struct task_struct *t; if (uhd->debug) printk(KERN_ERR "nl_set_nofreeze for pid %d.\n", pid); read_lock(&tasklist_lock); t = find_task_by_pid_type_ns(PIDTYPE_PID, pid, &init_pid_ns); if (!t) { read_unlock(&tasklist_lock); printk(KERN_INFO "Strange. Can't find the userspace task %d.\n", pid); return -EINVAL; } t->flags |= PF_NOFREEZE; read_unlock(&tasklist_lock); uhd->pid = pid; toi_send_netlink_message(uhd, NETLINK_MSG_NOFREEZE_ACK, NULL, 0); return 0; }
void toi_send_netlink_message(struct user_helper_data *uhd, int type, void *params, size_t len) { struct sk_buff *skb; struct nlmsghdr *nlh; void *dest; struct task_struct *t; if (uhd->pid == -1) return; if (uhd->debug) printk(KERN_ERR "toi_send_netlink_message: Send " "message type %d.\n", type); skb = toi_get_skb(uhd); if (!skb) { printk(KERN_INFO "toi_netlink: Can't allocate skb!\n"); return; } /* NLMSG_PUT contains a hidden goto nlmsg_failure */ nlh = NLMSG_PUT(skb, 0, uhd->sock_seq, type, len); uhd->sock_seq++; dest = NLMSG_DATA(nlh); if (params && len > 0) memcpy(dest, params, len); netlink_unicast(uhd->nl, skb, uhd->pid, 0); read_lock(&tasklist_lock); t = find_task_by_pid_type_ns(PIDTYPE_PID, uhd->pid, &init_pid_ns); if (!t) { read_unlock(&tasklist_lock); if (uhd->pid > -1) printk(KERN_INFO "Hmm. Can't find the userspace task" " %d.\n", uhd->pid); return; } wake_up_process(t); read_unlock(&tasklist_lock); yield(); return; nlmsg_failure: if (skb) put_skb(uhd, skb); if (uhd->debug) printk(KERN_ERR "toi_send_netlink_message: Failed to send " "message type %d.\n", type); }
void toi_netlink_close(struct user_helper_data *uhd) { struct task_struct *t; read_lock(&tasklist_lock); t = find_task_by_pid_type_ns(PIDTYPE_PID, uhd->pid, &init_pid_ns); if (t) t->flags &= ~PF_NOFREEZE; read_unlock(&tasklist_lock); toi_send_netlink_message(uhd, NETLINK_MSG_CLEANUP, NULL, 0); }
asmlinkage long sys_setsid(void) { struct task_struct *group_leader = current->group_leader; pid_t session; int err = -EPERM; write_lock_irq(&tasklist_lock); /* Fail if I am already a session leader */ if (group_leader->signal->leader) goto out; session = group_leader->pid; /* Fail if a process group id already exists that equals the * proposed session id. * * Don't check if session id == 1 because kernel threads use this * session id and so the check will always fail and make it so * init cannot successfully call setsid. */ if (session > 1 && find_task_by_pid_type_ns(PIDTYPE_PGID, session, &init_pid_ns)) goto out; group_leader->signal->leader = 1; __set_special_pids(session, session); spin_lock(&group_leader->sighand->siglock); group_leader->signal->tty = NULL; spin_unlock(&group_leader->sighand->siglock); err = task_pgrp_vnr(group_leader); out: write_unlock_irq(&tasklist_lock); return err; }
/* * This needs some heavy checking ... * I just haven't the stomach for it. I also don't fully * understand sessions/pgrp etc. Let somebody who does explain it. * * OK, I think I have the protection semantics right.... this is really * only important on a multi-user system anyway, to make sure one user * can't send a signal to a process owned by another. -TYT, 12/12/91 * * Auch. Had to add the 'did_exec' flag to conform completely to POSIX. * LBT 04.03.94 */ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) { struct task_struct *p; struct task_struct *group_leader = current->group_leader; int err = -EINVAL; struct pid_namespace *ns; if (!pid) pid = task_pid_vnr(group_leader); if (!pgid) pgid = pid; if (pgid < 0) return -EINVAL; /* From this point forward we keep holding onto the tasklist lock * so that our parent does not change from under us. -DaveM */ ns = current->nsproxy->pid_ns; write_lock_irq(&tasklist_lock); err = -ESRCH; p = find_task_by_pid_ns(pid, ns); if (!p) goto out; err = -EINVAL; if (!thread_group_leader(p)) goto out; if (p->real_parent->tgid == group_leader->tgid) { err = -EPERM; if (task_session(p) != task_session(group_leader)) goto out; err = -EACCES; if (p->did_exec) goto out; } else { err = -ESRCH; if (p != group_leader) goto out; } err = -EPERM; if (p->signal->leader) goto out; if (pgid != pid) { struct task_struct *g; g = find_task_by_pid_type_ns(PIDTYPE_PGID, pgid, ns); if (!g || task_session(g) != task_session(group_leader)) goto out; } err = security_task_setpgid(p, pgid); if (err) goto out; if (task_pgrp_nr_ns(p, ns) != pgid) { struct pid *pid; detach_pid(p, PIDTYPE_PGID); pid = find_vpid(pgid); attach_pid(p, PIDTYPE_PGID, pid); set_task_pgrp(p, pid_nr(pid)); } err = 0; out: /* All paths lead to here, thus we are safe. -DaveM */ write_unlock_irq(&tasklist_lock); return err; }