LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices

Reply
 
Search this Thread
Old 04-29-2013, 11:06 AM   #1
glipper
LQ Newbie
 
Registered: Apr 2013
Posts: 2

Rep: Reputation: Disabled
Is there any kill_proc() replacement for proprietary Linux kernel drivers?


I'm in the process of porting 4 proprietary (read: non-GPL) Linux kernel drivers (that I didn't write) from RHEL 5.x to RHEL 6.x (2.6.32 kernel). The drivers all use kill_proc() for signalling the user-space "session", but this function has been removed from the more recent kernels (somewhere between 2.6.18 and 2.6.32). I've seen this question asked many times here and elsewhere and I've searched fairly extensively, but of the many suggested solutions, none work due to either the functions no longer being exported, or requiring a GPL-only function (see below). Does anyone know of a solution that could work for a proprietary driver?

given: kill_proc(pid, sig, 1);

The simplest solution I found was to use: kill_proc_info(sig, SEND_SIG_PRIV, pid); however kill_proc_info is no longer exported so it can't be used.

kill_pid_info() has been suggested (this is called by kill_proc_info() after setting an rcu_read_lock()). kill_pid_info() requires a struct pid* so I could use: kill_pid_info(sig, SEND_SIG_PRIV, find_vpid(pid)); however find_vpid() is exported for GPL use only and this is a proprietary driver. Is there another way to get the struct pid*?

kill_pid_info() also sets up an rcu_read_lock() and then calls group_send_sig_info(). Unfortunately, group_send_siginfo() is not exported, and also it requires a struct task_struct*, but the required find_task_by_vpid() function is not exported either.

Another suggestion was kill_pid(), but this also requires a struct pid*, and again, the function find_vpid() is only exported for GPL.

There were also suggestions for send_sig() and send_sig_info(), but these also require a struct task_struct*, and again, find_task_by_pid() is not exported, and pid_task() requires the same (GPLd) find_vpid() to get a struct pid*. Also, these functions don't set an rcu_read_lock() and they also pass a FALSE value for the group flag (whereas kill_proc ended up using a TRUE value) - so there could be some subtle differences.

That's all that I could find. Does anyone have a suggestion that will work for my case? Thanks in advance.
 
Old 05-01-2013, 11:38 AM   #2
glipper
LQ Newbie
 
Registered: Apr 2013
Posts: 2

Original Poster
Rep: Reputation: Disabled
proposed solution

Since there have been no responses to my question, I've been reading much of the kernel code and I think I've found a solution.

It seems that the only exported function that provides the same semantics as kill_proc() is kill_pid(). We can't use the GPL find_vpid() function to get the needed struct pid*, but if we can get the struct task_struct*, then we can get the struct pid* from there as: task->pids[PIDTYPE_PID].pid

Since find_task_by_vpid() is no longer exported, it seems the only way to find the task is to go through the entire task list looking for it. So, the proposed solution is:

Code:
int my_kill_proc(pid_t pid, int sig) {
    int error = -ESRCH;              /* default return value */
    struct task_struct* p;
    struct task_struct* t = NULL; 
    struct pid* pspid;
    rcu_read_lock();
    p = &init_task;                  /* start at init */
    do {
        if (p->pid == pid) {         /* does the pid (not tgid) match? */
	    t = p;    
	    break;
        }
	p = next_task(p);    /* "this isn't the task you're looking for" */
    } while (p != &init_task);   /* stop when we get back to init */
    if (t != NULL) {
        pspid = t->pids[PIDTYPE_PID].pid;
        if (pspid != NULL) error = kill_pid(pspid,sig,1);
    }
    rcu_read_unlock();
    return error;
}
I know it will take a lot more time to search the whole task list rather than using the hash tables, but it's all I've got. Some concerns/questions that I have:
  1. Is the rcu_read_lock() sufficient for this? Would it be better to use something like preempt_disable() instead?
  2. Can the struct task_struct ever NOT have a PIDTYPE_PID entry in the pids array? And if so, is checking for NULL sufficient?
  3. I'm new to working with the kernel, are there any other suggestions to make this better?

Last edited by glipper; 05-01-2013 at 11:40 AM. Reason: fix formatting
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
AMD basically kills proprietary Linux drivers TobiSGD Linux - General 38 07-09-2012 12:27 PM
Problem With ATI Proprietary Linux x86 Display Drivers 8.29.6 ArizonaRedneck Linux - Newbie 10 10-31-2006 09:03 PM
Ati 64bit proprietary drivers crash linux slantoflight Linux - Hardware 7 07-30-2006 03:34 PM
ATI proprietary video drivers and 2.6 kernel vasudevadas Linux - Hardware 3 05-24-2004 06:55 AM


All times are GMT -5. The time now is 10:54 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration