views:

110

answers:

3

For a class assignment, we are writing a custom syscall which pulls certain information about the existing process tree. The syscall is working fine for the most part and gets the appropriate information. However, a few processes it, in crashes with the error message, "Unable to handle kernel NULL pointer dereference at virtual address [address]". What I don't understand is that I'm testing if the pointer is NULL before accessing it, and yet, it still fails.

Example: In the code below, current_process is a valid pointer to a task_struct and k_buf is valid

printk("Setting parent process\n");
parent_process = current_process->real_parent;
printk("Parent process set\n");
if (parent_process != NULL) {
printk("Parent process is not null and getting pid\n");
    k_buf[i].parent_pid = parent_process->pid;
} else {
    k_buf[i].parent_pid = 0;
}
printk("Done with parent process\n");

When run, the program prints:

Setting parent process
Parent process set
Parent process is not null and getting pid
Done with parent process

a couple of times, and then

Setting parent process
Parent process set
Parent process is not null and getting pid

before throwing the error and going into kernel panic.

What am I doing wrong? Any thoughts?

EDIT:

For the time being, I commented out the above code so I could continue working on the rest of the system call. When I try to access the pid of a child process (again after a couple of successful attempts), it gives me a "Unable to handle kernel paging request at virtual address" error. As far as I understand, I have the correct locks in place for reading this data. However, is there something else I need to do to check the memory before I access it?

A: 

I have two questions. What are the possible values for real_parent? Is it possible that it is not NULL? Can you print this value and check what it is before the kernel panic?

Also, are you sure k_buf[i] dereferences properly? I am not sure, just trying to throw some ideas out there.

Edit: I agree with crypto
parent_process->pid is probably null.

0x90
In include\linux\sched.h, in the task_struct structure, you'll see that real_parent is a pointer to a task_struct.If I print the value of parent_process, it will print some integer. So I guess this means it is not NULL?However, if I try to print parent_process->pid, it will throw the error and go into kernel panic.k_buf[i] does dereference properly (tested by trying to assign a int and printing it).
achinda99
+1  A: 

I'm speculating here but could parent_process->pid being NULL be the cause of your "kernel panic"? If so, you could check for that too.

Its either that, or some issue with accessing the ith element of k_buf array ie. *(k_buf+i)

Kedar Soparkar
achinda99
Huh? `parent_process->pid` is not a pointer, so how can it be NULL?
Ben Voigt
I know it doesn't make sense, but right now, its parent_process->pid that is throwing the error (from my understanding). I know its not a pointer. I've been banging my head against a wall for a while now.
achinda99
+1  A: 

You don't seem to be testing kbuf of kbuf[i] before access. Also, you can printk these pointers, that way you'd catch non-null but obviously invalid addresses (such as 0xbfff0c3a)

TomMD
kbuf and kbuf[i] were valid and had been tested. Turned out the problem was with current_process. The way it was being set, it was valid in certain circumstances, invalid in others, but somehow got past the prior NULL checks.
achinda99