0

I need to copy curr_task->pid, a pid_t in kernel space, to a structure's field in user space that has space for a long. Since this is a widening conversion, I'm not expecting any issues.

However, I'm getting an annoying compiler warning (copy_long_to_user is for all intents and purposes the same as copy_to_user):

cs300/process_ancestors.c:31:3: warning: passing argument 2 of ‘copy_long_to_user’ from incompatible pointer type [enabled by default]
   if(copy_long_to_user(&info_array[num_filled_kernel].pid, &curr_task->pid)) {    
   ^
cs300/process_ancestors.c:9:5: note: expected ‘long int *’ but argument is of type ‘pid_t *’

Is this warning something I can safely ignore (will the compiler do the cast for me)? If I need to cast curr_task->pid to a long explicitly, how can I do that in the context of using copy_to_user? My guess would be that it's something like:(copy_long_to_user(&info_array[num_filled_kernel].pid, &((long)curr_task->pid)))

Adam
  • 8,752
  • 12
  • 54
  • 96
  • I hope you didn't just take part of @ChunleiMa's answer and make the type of the second parameter of `copy_long_to_user()` a `void*`. – Michael Burr Apr 16 '16 at 01:15
  • Nope, the answer made me realize what I was doing wrong though -- I was telling `copy_to_user` to copy 8 bytes when there was only 4 bytes of data in the source location. – Adam Apr 16 '16 at 01:18
  • I thought that perhaps a shortcut like I mentioned might have been what cause you other , related question: http://stackoverflow.com/questions/36658863/printing-pid-with-d-vs-ld-linux – Michael Burr Apr 16 '16 at 01:20

2 Answers2

4

You need a helper variable to do this correctly.

long curr_pid = curr_task->pid;
copy_long_to_user(&info_array[num_filled_kernel].pid, &curr_pid);

Taking the address of a helper variable is legal, address of a temporary (produced by the cast) isn't.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
2

In Linux kernel, the type of pid_t is equals to int, so the compiler warns you that int* cannot cast to long int*. I don't know how do you realize your copy_long_to_user function, if you write like this, you may get a wrong result. copy_long_to_user(long int* dest, long int* src){ copy_to_user(dest, src, sizeof(long int)); ...... } because sizeof(long) >= sizeof(int), if sizeof(long) > sizeof(int), support that sizeof(long) == 8, and sizeof(int) always 4, you will get a wrong result, because current_task->pid just occupy the 4 byte of dest, but copy_to_user(dest, src, sizeof(long int)) must copy 8 byte to dest, so the 4 bytes follow the current->pid are copied to dest, so dest can not equal to current->pid. so you'd better write a function named copy_pid_to_user and it codes like that: copy_pid_to_user(long int* dest, void* src){ copy_to_user(dest, src, sizeof(curent->pid)) ......

Chunlei Ma
  • 66
  • 2