q2ven
q2ven

Reputation: 187

When does copy_from/to_user returns a non-zero value

I read the source code of copy_from/to_user functions. It seems that they always return 0.

static inline int copy_from_user(void *to, const void __user volatile *from,
                 unsigned long n)
{
    __chk_user_ptr(from, n);
    volatile_memcpy(to, from, n);
    return 0;
}

https://github.com/torvalds/linux/blob/6f0d349d922ba44e4348a17a78ea51b7135965b1/tools/virtio/linux/uaccess.h#L37-L51

However, there is some code like below that checks the returned value of copy_from/to_user.

    if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
        return -EFAULT;

https://github.com/torvalds/linux/blob/db54615e21419c3cb4d699a0b0aa16cc44d0e9da/net/ipv4/netfilter/ip_tables.c#L1114-L1115

Then I have three questions.

  1. Where the code of copy_from/to_user which returns non-zero is defined?
  2. What causes the copy_from/to_user to return a non-zero value?
  3. What value is returned?

Upvotes: 3

Views: 874

Answers (2)

Ian Abbott
Ian Abbott

Reputation: 17403

  1. Where the code of copy_from/to_user which returns non-zero is defined?

In "include/linux/uaccess.h" in the Linux source tree. Note that these will do some initial checking before calling the arch-specific raw_copy_from/to_user functions.

  1. What causes the copy_from/to_user to return a non-zero value?

Possible causes are when the specified user memory range is invalid, or when unhandled faults occur when reading/writing the specified user memory range.

  1. What value is returned?

The number of uncopied bytes is returned. This will be between 0 and the specified length inclusive. Let's call the return value the "unsuccessful length".

Let's call the specified length minus the (returned) "unsuccessful length" the "successful length".

The caller can consider the "successful length" number of bytes to have been copied successfully.

Note that the number of bytes actually overwritten in the destination buffer will be somewhere between the "successful length" and the specified length inclusive, but only the initial "successful length" bytes should be considered usable.

Upvotes: 2

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215193

I'm pretty sure you're looking at the wrong file; tools/* is not part of the kernel but source for userspace tools to go with it. This code looks like it's stubs for linking code that was written for the kernel APIs in userspace programs.

The actual copy_from/to_user functions may also look like they always return 0, but as I understand it they have some fancy tricks with linker sections hooked up in their inline asm, so that when the cpu traps an access fault during the copy operation, the fault handler can resume execution at the caller with a fake -EFAULT return value. The definition of these functions is arch-specific and can probably be found somewhere in the arch/ tree.

Upvotes: 3

Related Questions