0

I have two functions:

one is a system call:

asmlinkage long sys_memstats(struct meminfo __user *info){

Where I modify the values in meminfo struct like so:

    info->mFree_pages = tempFreePages;
    info->mActive_pages =tempActivePages;
    info->mInactive_pages=tempInactivePages;

And it was not passing the correct values to the meminfo struct in this test file:

        int main (void){
          struct meminfo *newMemInfo;
          newMemInfo =(struct meminfo*) malloc(sizeof(struct meminfo* ));
          newwMemInfo->mFree_pages =0;
          newMemInfo->mActive_pages=0;
          newMemInfo->mInactive_pages=0;
          int status;
          status = syscall(335, newMemInfo);
         //testPointerParamFunc(newMemInfo);
         printf("Free Pages: %ld \n Active Pages:%ld \n Inactive Pages:%ld ", newMemInfo->mFree_pages, newMemInfo->mActive_pages, newMemInfo->mInactive_pages );
      free(newMemInfo);
      return 0;
    }

So I created a the following function inside my systemcall test file to see if I was modifying the struct correctly:

void testPointerParamFunc(struct meminfo*  temp){
  temp->mFree_pages =10;
  temp->mActive_pages=21;
  temp->mInactive_pages=12;
}

And called it (testPointerParamFunc(newMemInfo);) instead of the systemcall in my code and I get the correct output for those members in the meminfo struct when running the test function:

./test4
Free Pages: 10
 Active Pages:21
 Inactive Pages:12

I'm using the same pointer logic for both the system call and the function, but when using the system call, the newMemInfo isn't changed, I still get the same values I declared in main(): ./test4 Free Pages: 0 Active Pages:0 Inactive Pages:0

I know that the values for:

  info->mFree_pages = tempFreePages;
            info->mActive_pages =tempActivePages;
            info->mInactive_pages=tempInactivePages;
printk(KERN_INFO "TOTAL||||Free pages = %ld | Active Pages: %ld | Inactive Pages: %ld |\n", tempFreePages,tempActivePages,tempInactivePages);

Are all valid long types because I print out this in the kernel log from the system call:

Jul 30 12:14:54 localhost kernel: TOTAL||||Free pages = 831134 | Active Pages: 360990 | Inactive Pages: 715557 |

What is the difference between passing the struct pointer in testPointerParamFunc(newMemInfo) and passing the pointer in syscall(335, newMeminfo)?

I know the __user macro specified that the pointer *info exists in user space, but does it do more than that?

How do I change my systemcall parameters so that I pass those values to the struct of the pointer parameter?

EDIT: 1:18PM EST 7/30/20 I fixed the malloc only allocating for a pointer as @MikeCAT and @"Vlad from moscow" suggested, but that does not seem to be the cause for why systemcall doesn't change the struct's values, but the test function within the test file does.

C.A.R
  • 3
  • 3
  • 4
    Not reading your question well, `newMemInfo =(struct meminfo*) malloc(sizeof(struct meminfo* ));` is bad because only size of one pointer is allocated instead of the size of the structure. – MikeCAT Jul 30 '20 at 17:00
  • Check if the system call is successful. – MikeCAT Jul 30 '20 at 17:02
  • In your system, are address values to access user memory from user applications and ones to access user memory from the kernel same? – MikeCAT Jul 30 '20 at 17:05
  • @MikeCAT Ok I'll see if I allocate it as 'newMemInfo =(struct memInfo*) malloc(sizeof(struct meminfo));' To answer your second question: The system call is successful, I have it print to the kernel log, and it shows me all the values of 'tempFreePages', 'tempActivePages' and 'tempInactivePages'. – C.A.R Jul 30 '20 at 17:08
  • @MikeCAT " are address values to access user memory from user applications and ones to access user memory from the kernel same?", from what I understand, the kernel memory is separate from user memory, in the sense that they are stored in different sections within memory. – C.A.R Jul 30 '20 at 17:18

1 Answers1

1

you must not access __user memory directly but have to wrap it through copy_to_user() (or copy_from_user().

asmlinkage long sys_memstats(struct meminfo __user *info)
{
    struct meminfo res; 

    /* ... */

    res = (struct meminfo) {
        .mFree_pages = tempFreePages,
        /* ... */
    };

    if (copy_to_user(info, &res, sizeof res))
        return -EFAULT;
}
ensc
  • 6,704
  • 14
  • 22
  • I think you're answer is correct here. I am having trouble getting it to work. instead of 'res = (struct meminfo) { .mFree_pages = tempFreePages, /* ... */ }; ' Can I just declare the meminfo struct variables like: 'res.mFree_pages= tempFreePages' etc ? – C.A.R Jul 30 '20 at 18:24