Exemplo 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);

	toi_read_lock_tasklist();
	t = find_task_by_pid_ns(pid, &init_pid_ns);
	if (!t) {
		toi_read_unlock_tasklist();
		printk(KERN_INFO "Strange. Can't find the userspace task %d.\n",
				pid);
		return -EINVAL;
	}

	t->flags |= PF_NOFREEZE;

	toi_read_unlock_tasklist();
	uhd->pid = pid;

	toi_send_netlink_message(uhd, NETLINK_MSG_NOFREEZE_ACK, NULL, 0);

	return 0;
}
Exemplo n.º 2
0
static struct task_struct *getthread(struct pt_regs *regs, int tid)
{
	/*
	 * Non-positive TIDs are remapped to the cpu shadow information
	 */
	if (tid == 0 || tid == -1)
		tid = -atomic_read(&kgdb_active) - 2;
	if (tid < -1 && tid > -NR_CPUS - 2) {
		if (kgdb_info[-tid - 2].task)
			return kgdb_info[-tid - 2].task;
		else
			return idle_task(-tid - 2);
	}
	if (tid <= 0) {
		printk(KERN_ERR "KGDB: Internal thread select error\n");
		dump_stack();
		return NULL;
	}

	/*
	 * find_task_by_pid_ns() does not take the tasklist lock anymore
	 * but is nicely RCU locked - hence is a pretty resilient
	 * thing to use:
	 */
	return find_task_by_pid_ns(tid, &init_pid_ns);
}
Exemplo n.º 3
0
static noinline void __init_refok rest_init(void)
{
	int pid;

	rcu_scheduler_starting();
	/*
	 * We need to spawn init first so that it obtains pid 1, however
	 * the init task will end up wanting to create kthreads, which, if
	 * we schedule it before we create kthreadd, will OOPS.
	 */
	kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
	numa_default_policy();
	pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
	rcu_read_lock();
	kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
	rcu_read_unlock();
	complete(&kthreadd_done);

	/*
	 * The boot idle thread must execute schedule()
	 * at least once to get things moving:
	 */
	init_idle_bootup_task(current);
	preempt_enable_no_resched();
	schedule();

	/* Call into cpu_idle with preempt disabled */
	preempt_disable();
	cpu_idle();
}
Exemplo n.º 4
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;
	}

	nlh = nlmsg_put(skb, 0, uhd->sock_seq, type, len, 0);
	uhd->sock_seq++;

	dest = NLMSG_DATA(nlh);
	if (params && len > 0)
		memcpy(dest, params, len);

	netlink_unicast(uhd->nl, skb, uhd->pid, 0);

	toi_read_lock_tasklist();
	t = find_task_by_pid_ns(uhd->pid, &init_pid_ns);
	if (!t) {
		toi_read_unlock_tasklist();
		if (uhd->pid > -1)
			printk(KERN_INFO "Hmm. Can't find the userspace task"
				" %d.\n", uhd->pid);
		return;
	}
	wake_up_process(t);
	toi_read_unlock_tasklist();

	yield();
}
Exemplo n.º 5
0
static struct task_struct *getthread(struct pt_regs *regs, int tid)
{
	/*
	 * Non-positive TIDs are remapped to the cpu shadow information
	 */
	if (tid == 0 || tid == -1)
		tid = -atomic_read(&kgdb_active) - 2;
	if (tid < 0) {
		if (kgdb_info[-tid - 2].task)
			return kgdb_info[-tid - 2].task;
		else
			return idle_task(-tid - 2);
	}

	/*
	 * find_task_by_pid_ns() does not take the tasklist lock anymore
	 * but is nicely RCU locked - hence is a pretty resilient
	 * thing to use:
	 */
	return find_task_by_pid_ns(tid, &init_pid_ns);
}
Exemplo n.º 6
0
struct file *get_task_file(pid_t pid, int fd)
{
	int err;
	struct task_struct *tsk;
	struct files_struct *fs;
	struct file *file = NULL;

	err = -ESRCH;
	read_lock(&tasklist_lock);
	tsk = find_task_by_pid_ns(pid, get_exec_env()->ve_ns->pid_ns);
	if (tsk == NULL) {
		read_unlock(&tasklist_lock);
		goto out;
	}

	get_task_struct(tsk);
	read_unlock(&tasklist_lock);

	err = -EINVAL;
	fs = get_files_struct(tsk);
	if (fs == NULL)
		goto out_put;

	rcu_read_lock();
	err = -EBADF;
	file = fcheck_files(fs, fd);
	if (file == NULL)
		goto out_unlock;

	err = 0;
	get_file(file);

out_unlock:
	rcu_read_unlock();
	put_files_struct(fs);
out_put:
	put_task_struct(tsk);
out:
	return err ? ERR_PTR(err) : file;
}
Exemplo n.º 7
0
//Ä£¿éŒÓÔغ¯Êý¶šÒå
static int __init find_task_by_pid_ns_init(void)
{	
	int result;	
	printk("<0> into find_task_by_pid_ns_init.\n");		
	result=kernel_thread(my_function,NULL,CLONE_KERNEL); //ŽŽœšÐÂœø³Ì
	struct pid * kpid=find_get_pid(result);	 //»ñÈ¡œø³ÌÃèÊö·û

       //µ÷Óú¯Êý»ñµÃÓë²ÎÊýÐÅÏ¢¶ÔÓŠµÄÈÎÎñÃèÊö·ûÐÅÏ¢
	struct task_struct * task=find_task_by_pid_ns(kpid->numbers[kpid->level].nr,kpid->numbers[kpid->level].ns);

       //ÏÔÊŸfind_get_pid()º¯Êý·µ»ØµÄœø³ÌÃèÊö·ûµÄœø³ÌºÅ
	printk("<0>the pid of the find_get_pid is :%d\n",kpid->numbers[kpid->level].nr);

       //ÏÔÊŸº¯Êýµ÷ÓÃœá¹ûÈÎÎñÃèÊö·ûµÄÐÅÏ¢
	printk("<0>the pid of the task of the function find_task_by_pid_ns is:%d\n",task->pid);
	printk("<0>the tgid of the task of the function find_task_by_pid_ns is:%d\n",task->tgid);

	//ÏÔÊŸkernel_thread()º¯Êýµ÷ÓÃœá¹û
	printk("<0>the result of the kernel_thread is :%d\n",result);
	printk("<0> out find_task_by_pid_ns_init.\n");
	return 0;
}
Exemplo n.º 8
0
asmlinkage long sys_getpgid(pid_t pid)
{
	if (!pid)
		return task_pgrp_vnr(current);
	else {
		int retval;
		struct task_struct *p;
		struct pid_namespace *ns;

		ns = current->nsproxy->pid_ns;

		read_lock(&tasklist_lock);
		p = find_task_by_pid_ns(pid, ns);
		retval = -ESRCH;
		if (p) {
			retval = security_task_getpgid(p);
			if (!retval)
				retval = task_pgrp_nr_ns(p, ns);
		}
		read_unlock(&tasklist_lock);
		return retval;
	}
}
Exemplo n.º 9
0
static void create_kthread(struct kthread_create_info *create)
{
	int pid;

	/* We want our own signal handler (we take no signals by default). */
	pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
	if (pid < 0) {
		create->result = ERR_PTR(pid);
	} else {
		struct sched_param param = { .sched_priority = 0 };
		wait_for_completion(&create->started);
		read_lock(&tasklist_lock);
		create->result = find_task_by_pid_ns(pid, &init_pid_ns);
		read_unlock(&tasklist_lock);
		/*
		 * root may have changed our (kthreadd's) priority or CPU mask.
		 * The kernel thread should not inherit these properties.
		 */
		sched_setscheduler(create->result, SCHED_NORMAL, &param);
		set_user_nice(create->result, KTHREAD_NICE_LEVEL);
		set_cpus_allowed_ptr(create->result, CPU_MASK_ALL_PTR);
	}
	complete(&create->done);
}

/**
 * kthread_create - create a kthread.
 * @threadfn: the function to run until signal_pending(current).
 * @data: data ptr for @threadfn.
 * @namefmt: printf-style name for the thread.
 *
 * Description: This helper function creates and names a kernel
 * thread.  The thread will be stopped: use wake_up_process() to start
 * it.  See also kthread_run(), kthread_create_on_cpu().
 *
 * When woken, the thread will run @threadfn() with @data as its
 * argument. @threadfn() can either call do_exit() directly if it is a
 * standalone thread for which noone will call kthread_stop(), or
 * return when 'kthread_should_stop()' is true (which means
 * kthread_stop() has been called).  The return value should be zero
 * or a negative error number; it will be passed to kthread_stop().
 *
 * Returns a task_struct or ERR_PTR(-ENOMEM).
 */
struct task_struct *kthread_create(int (*threadfn)(void *data),
				   void *data,
				   const char namefmt[],
				   ...)
{
	struct kthread_create_info create;

	create.threadfn = threadfn;
	create.data = data;
	init_completion(&create.started);
	init_completion(&create.done);

	spin_lock(&kthread_create_lock);
	list_add_tail(&create.list, &kthread_create_list);
	spin_unlock(&kthread_create_lock);

	wake_up_process(kthreadd_task);
	wait_for_completion(&create.done);

	if (!IS_ERR(create.result)) {
		va_list args;
		va_start(args, namefmt);
		vsnprintf(create.result->comm, sizeof(create.result->comm),
			  namefmt, args);
		va_end(args);
	}
	return create.result;
}
EXPORT_SYMBOL(kthread_create);

/**
 * kthread_bind - bind a just-created kthread to a cpu.
 * @k: thread created by kthread_create().
 * @cpu: cpu (might not be online, must be possible) for @k to run on.
 *
 * Description: This function is equivalent to set_cpus_allowed(),
 * except that @cpu doesn't need to be online, and the thread must be
 * stopped (i.e., just returned from kthread_create()).
 */
void kthread_bind(struct task_struct *k, unsigned int cpu)
{
	if (k->state != TASK_UNINTERRUPTIBLE) {
		WARN_ON(1);
		return;
	}
	/* Must have done schedule() in kthread() before we set_task_cpu */
	wait_task_inactive(k, 0);
	set_task_cpu(k, cpu);
	k->cpus_allowed = cpumask_of_cpu(cpu);
	k->flags |= PF_THREAD_BOUND;
}
EXPORT_SYMBOL(kthread_bind);

/**
 * kthread_stop - stop a thread created by kthread_create().
 * @k: thread created by kthread_create().
 *
 * Sets kthread_should_stop() for @k to return true, wakes it, and
 * waits for it to exit.  Your threadfn() must not call do_exit()
 * itself if you use this function!  This can also be called after
 * kthread_create() instead of calling wake_up_process(): the thread
 * will exit without calling threadfn().
 *
 * Returns the result of threadfn(), or %-EINTR if wake_up_process()
 * was never called.
 */
int kthread_stop(struct task_struct *k)
{
	int ret;

	mutex_lock(&kthread_stop_lock);

	/* It could exit after stop_info.k set, but before wake_up_process. */
	get_task_struct(k);

	/* Must init completion *before* thread sees kthread_stop_info.k */
	init_completion(&kthread_stop_info.done);
	smp_wmb();

	/* Now set kthread_should_stop() to true, and wake it up. */
	kthread_stop_info.k = k;
	wake_up_process(k);

	/* Once it dies, reset stop ptr, gather result and we're done. */
	wait_for_completion(&kthread_stop_info.done);
	kthread_stop_info.k = NULL;
	ret = kthread_stop_info.err;
	put_task_struct(k);
	mutex_unlock(&kthread_stop_lock);

	return ret;
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
/* tid is the actual task/thread id (née pid, stored as ->pid),
   pid/tgid is that 2.6 thread group id crap (stored as ->tgid) */
asmlinkage long sys_vperfctr_open(int tid, int creat)
{
	struct file *filp;
	struct task_struct *tsk;
	struct vperfctr *perfctr;
	int err;
	int fd;

	if (!vperfctr_fs_init_done())
		return -ENODEV;
	filp = vperfctr_get_filp();
	if (!filp)
		return -ENOMEM;
	err = fd = get_unused_fd();
	if (err < 0)
		goto err_filp;
	perfctr = NULL;
	if (creat) {
		perfctr = get_empty_vperfctr(); /* may sleep */
		if (IS_ERR(perfctr)) {
			err = PTR_ERR(perfctr);
			goto err_fd;
		}
	}
	tsk = current;

	if (tid != 0 && tid != tsk->pid) { /* remote? */
		// tasklist_lock is to access the linked list of task_struct structures exclusively
		read_lock(&tasklist_lock);
		//tsk = find_task_by_pid(tid);
		tsk = find_task_by_pid_ns(tid, current->nsproxy->pid_ns);
		if (tsk)
			get_task_struct(tsk);
		read_unlock(&tasklist_lock);
		err = -ESRCH;
		if (!tsk)
			goto err_perfctr;
		err = ptrace_check_attach(tsk, 0);
		if (err < 0)
			goto err_tsk;
	}
	if (creat) {
		/* check+install must be atomic to prevent remote-control races */
		task_lock(tsk);
		if (!tsk->thread.perfctr) {
			perfctr->owner = tsk;
			tsk->thread.perfctr = perfctr;
			err = 0;
		} else
			err = -EEXIST;
		task_unlock(tsk);
		if (err)
			goto err_tsk;
	} else {
		perfctr = tsk->thread.perfctr;
		/* XXX: Old API needed to allow NULL perfctr here.
		   Do we want to keep or change that rule? */
	}
	filp->private_data = perfctr;
	if (perfctr)
		atomic_inc(&perfctr->count);
	if (tsk != current)
		put_task_struct(tsk);
	#if 0
	if (perfctr) {
    	printk ("sys_vperfctr_open(): fd = %d, perfctr is NOT null\n", fd);
	}
	else {
    	printk ("sys_vperfctr_open(): fd = %d, perfctr is null\n", fd);
	}
	#endif
	fd_install(fd, filp);
	return fd;
 err_tsk:
	if (tsk != current)
		put_task_struct(tsk);
 err_perfctr:
	if (perfctr)	/* can only occur if creat != 0 */
		put_vperfctr(perfctr);
 err_fd:
	put_unused_fd(fd);
 err_filp:
	fput(filp);
	return err;
}
Exemplo n.º 12
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;
}