# Is it necessary to copy int to kernel space before accessing



## bestwc (Feb 21, 2013)

Dear all,

I'm new to FreeBSD kernel programming, I've seen people talking about using copy to copy user space data to kernel space instead of accessing them directly. I tried copying strings with copyinstr(9) and there's no problem, but I seem can't copy an int value using copyin(9).

Then I realized that it might not even be necessary to do so, since I can just assign the int value to a kernel space variable.


```
/* The system call's arguments */
struct sysmonitor_args {
    int target;
    //char *target;
};

/* The system call function */
static int sysmonitor(struct thread *td, void *syscall_args)
{
    struct sysmonitor_args *args; /* local struct to receive syscall_args */
    args = (struct sysmonitor_args *)syscall_args; /* receive syscall_args with casting */

    /* Copy args to kernel space */
    int target = args->target;
    printf("target: %p\n", &target);
    printf("args target: %p\n", &args->target);

    return (0);
}
```

And I can see two different addresses. Not sure if this means it's okay to do such thing. Otherwise, I would like to know why my copyin(9) always return EFAULT.


```
int target;
size_t size = sizeof(int);
copyin(&args->target, &target, size);
```

Thank you very much.

Best Regards,
BestWC


----------



## trasz@ (Feb 28, 2013)

When your syscall runs, the arguments ('syscall_args' above) are already copied into the kernel; you can just use them directly.  That's why copyin(9) failed - you gave it a pointer that was a kernel address, while it expected userspace address.

You need to use copyin(9) for things other than the automatically copied syscall_args.  Take the string, for example - the pointer to the first char (syscall_args->target) was copied for you, but the data it points to wasn't.  That's why you need to use copyinstr(9) in that case.


----------

