Esempio n. 1
0
/*
 * 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;
}
Esempio n. 2
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);
}
Esempio n. 3
0
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);
}
Esempio n. 4
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;
}
Esempio n. 5
0
/*
 * 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;
}