Accessing User Space

The first 2.1 versions of the kernel introduced a new (and better) way to access user space from kernel code. The change is meant to fix a long-standing misbehavior and to enhance system performance.

When you compile code for version 2.1 of the kernel and need to access user space, you need to include <asm/uaccess.h> instead of <asm/segment.h>. You must also use a different set of functions from those in 2.0. Needless to say, the header sysdep-2.1.h takes care of these differences as much as possible and allows you to use the 2.1 semantics when compiling with 2.0.

The most noticeable difference in user access is that verify_area is gone, as most of the verification is performed by the CPU instead. See Section 17.10 later in this chapter for more details on this subject.

The new set of functions that can be used to access user space is:

int access_ok (int type, unsigned long addr, ,                unsigned long size);

This function returns true (1) if the current process is allowed to access memory at address addr, false (0) otherwise. This function is a replacement for verify_area, although it does less checking. It receives the same arguments as the old verify_area, but is much faster. The function should be called to check a user-space address before you dereference it; if you fail to check, the user might be able to access and modify kernel memory. The section Section 17.9, later in the chapter, explains the issue in more detail. Fortunately, most of the functions described below take care of such checking for you, so you won’t need to actually call access_ok, unless you choose to.

int get_user (lvalue, address);

The get_user macro used by 2.1 kernels is different from the one we used in 2.0. The return value is 0 in case of success or a negative error code (always -EFAULT). The net effect of the function is to assign to lvalue data retrieved using the address pointer. The first argument of the macro must be an lvalue in the usual C-language meaning.[43] Similar to the 2.0 version of the function, the actual size of the data item depends on the type of the address argument. The function calls access_ok internally.

int __get_user (lvalue, address);

This function is exactly like get_user, but it doesn’t call access_ok internally. You should call __get_user when you access a user address that has already been checked from within the same kernel function.

get_user_ret (lvalue, address, retval);

This macro is a shortcut that calls get_user and returns retval if the function fails.

int put_user (expression, address); , int __put_user (expression, address); , put_user_ret (expression, address, retval);

These functions behave exactly like the get_ equivalents, but they write to user space instead of reading from it. In case of success, the value expression is written to address address.

unsigned long copy_from_user (unsigned long to, ,                               unsigned long from, ,                               unsigned long len);

This function copies data bytes from user space to kernel space. It replaces the old memcpy_fromfs call. The function calls access_ok internally. The return value is always the number of bytes not transferred. Thus, if an error occurs, the return value is greater than 0; in that case, the driver usually returns -EFAULT, because the error is caused by a faulty memory access.

unsigned long __copy_from_user (unsigned long to, ,                                 unsigned long from, ,                                 unsigned long len);

This function is identical to copy_from_user, but it doesn’t call access_ok internally.

copy_from_user_ret (to, from, len, retval);

This macro is a shortcut that calls copy_from_user and returns from the current function if it fails.

unsigned long copy_to_user (unsigned long to, ,                             unsigned long from, ,                             unsigned long len); , unsigned long __copy_to_user (unsigned long to, ,                               unsigned long from, ,                               unsigned long len); , copy_to_user_ret (to, from, len, retval);

These functions are used to copy data to user space, and they behave exactly like their copy_from counterparts.

Version 2.1 of the kernel defines other functions for accessing user space: clear_user, strncpy_from_user, and strlen_user. I won’t comment on them because they are not available in Linux 2.0, and because they are rarely needed by driver code. The interested reader is urged to browse <asm/uaccess.h>.

Using the New Interface

The new set of functions to access user space may look disappointing at first, but they are meant to ultimately make life easier for the programmer. With Linux 2.1, there’s no longer a need to explicitly check user space; access_ok won’t usually need to be called. The code using the new interface can just go ahead and transfer its data. The _ret functions, then, turn out to be very useful when implementing system calls, because a failure in user-space access usually results in a failure in the system call with -EFAULT.

The typical read implementation, therefore, will look like this:

long new_read(struct inode *inode, struct file *filp,
              char *buf, unsigned long count);
{
/* identify your data (device-specific code) */

if (__copy_to_user(buf, new_data, count))
    return -EFAULT;
return count;
}

Note that the non-checking __copy_to_user function is used because the caller already checked the user address before dispatching data transfer to the file operations. This is just like 2.0, where read and write didn’t need to call verify_area.

Similarly, the typical ioctl implementation will look like the following:

int new_ioctl(struct inode *inode, struct file *filp,
              unsigned int cmd, unsigned long arg);
{
/* device-specific checks, if needed */

switch(cmd) {
    case NEW_GETVALUE:
        put_user_ret(new_value,(int *)arg,-EFAULT);
        break;

    case NEW_SETVALUE:
        get_user_ret(new_value,(int *)arg,-EFAULT);
        break;
    default
        return -EINVAL;
    }
return 0;
}

Unlike the version 2.0 equivalent, this function doesn’t need to check its arguments before the switch statement, because each get_user or put_user does the checking. An alternative implementation is the following one:

int another_ioctl(struct inode *inode, struct file *filp,
              unsigned int cmd, unsigned long arg);
{
int retval = -EINVAL, size = _IOC_SIZE(cmd);

if (_IOC_DIR(cmd) & _IOC_READ) {
    if (!access_ok(VERIFY_WRITE, (void *)arg, size))
        retturn -EFAULT;
    }
else if (_IOC_DIR(cmd) & _IOC_WRITE) {
    if (!access_ok(VERIFY_READ, (void *)arg, size))
        return -EFAULT

switch(cmd) {
    case NEW_GETVALUE:
        retval = __put_user(another_value,arg);
        break;
    case NEW_SETVALUE:
        retval = __get_user(another_value,arg);
        break;
    }
return retval;
}

When you want to write code that compiles with both 2.0 and 2.1, on the other hand, things become slightly more complicated, as you can’t use the C preprocessor to fake the new behavior with older kernels. You can’t just #define a get_user macro that receives two arguments, because the actual get_user implementation in version 2.0 is already a macro.

My own choice for writing code that is both portable and efficient is to set up sysdep-2.1.h to provide source code with the following functions. Only the functions that read data are listed; functions that write data behave in exactly the same way.

int access_ok(type, address, size);

This function is implemented in terms of verify_area when compiling against 2.0.

int verify_area_20(type, address, size);

Usually, when writing code for Linux 2.1, you won’t call access_ok. On the other hand, verify_area is compulsory when compiling for Linux 2.0. This function tries to bridge the gap: it expands to nothing when compiling for Linux 2.1 and is the original verify_area when compiling against 2.0. The function can’t just be called verify_area, because 2.1 still has a macro with the same name as the 2.0 function. The verify_area macro as defined in 2.1 implements the old semantics in terms of access_ok and exists to ease transition of source code from 2.0 to 2.1. (You could, in theory, leave any verify_area in your modules and just rename your functions; the downside of this simple porting technique is that the new version wouldn’t compile with 2.0.)

int GET_USER(var, add); , int __GET_USER(var, add); , GET_USER_RET(var, add, ret);

When compiling with 2.1, these macros expand to the real get_user functions, the ones explained above. When they are compiled with 2.0, the 2.0 implementation of get_user is used to implement the same functionality as 2.1.

int copy_from_user(to, from, size); , int __copy_from_user(to, from, size); , copy_from_user_ret(to, from, size);

When compiled with 2.0, these expand to memcpy_fromfs; with 2.1, the native functions are used instead. The _ret flavor won’t ever return with 2.0, because the copying functions can’t fail.

This way of implementing compatibility is my personal preference, but it’s not the only way to do it. In my sample code, verify_area_20 must be called before any user-space access (excluding the buffer for read and write, which is already checked in advance). An alternative would be to be more faithful to 2.1 semantics and automatically generate a verify_area at each get_user or copy_from_user when 2.0 is used. This choice would be cleaner at the source level, but rather inefficient when compiled with version 2.0, both in code size and execution time.

Sample code that compiles with both 2.0 and 2.1 is, for example, the scull module, as found in the directory v2.1/scull. I don’t feel the code is interesting enough to show it here.



[43] An lvalue is an expression that can be the left operand of an assignment. For example, count, v[34+check()], and *((ptr+offset)->field) are lvalues; i++, 32, and cli() are not.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.51.117