Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

put_user() linux kernel

After doing put_user(message[i], buf+i); how can I access message from user space?

I really don't understand where the string message is to be accessed from and what I can do with it?

like image 811
Pawan Avatar asked Apr 04 '11 09:04

Pawan


2 Answers

put_user (x, ptr). Here x is the value to copy to user space, while ptr is the destination address, in user space.

So in user application the message can be accessed by buf+i.

like image 44
ZelluX Avatar answered Nov 20 '22 11:11

ZelluX


put_user() should only be called in the context of a process making a system call.

Consider an application calling ptrace(2) (see kernel/ptrace.c).

The kernel will call into an architecture-specific ptrace helper:

SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
            unsigned long, data) 
{
    /* arch-independent code */
    /* ... */
    ret = arch_ptrace(child, request, addr, data);

On the x86 platform, arch_ptrace() is defined in arch/x86/kernel/ptrace.c:

long arch_ptrace(struct task_struct *child, long request,
             unsigned long addr, unsigned long data)
{
    int ret;
    unsigned long __user *datap = (unsigned long __user *)data;

    switch (request) {
    /* read the word at location addr in the USER area. */
    case PTRACE_PEEKUSR: {
            unsigned long tmp;

            ret = -EIO;
            if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user))
                    break;

            tmp = 0;  /* Default return condition */
            if (addr < sizeof(struct user_regs_struct))
                    tmp = getreg(child, addr);
            else if (addr >= offsetof(struct user, u_debugreg[0]) &&
                     addr <= offsetof(struct user, u_debugreg[7])) {
                    addr -= offsetof(struct user, u_debugreg[0]);
                    tmp = ptrace_get_debugreg(child, addr / sizeof(data));
            }
            ret = put_user(tmp, datap);
            break;
    }

When a process calls ptrace(2) and asks to perform a PTRACE_PEEKUSR, the kernel needs to return information (ret) back to the user. The kernel uses the datap pointer to a user supplied buffer to know where in the process to write the value of tmp.

Almost every case of calling put_user() will be initiated by a userland process. Sending signals to userspace is an obvious difference, where the kernel initiates sending the signal, but the kernel has code (see arch/x86/kernel/signal.c function __setup_frame()) to find the stack frame and write into it the need to handle a signal.

So, after a long-winded discussion: You will access your data in your process via whatever buffer you gave to the kernel to write into -- it could be a buffer for a driver-specific ioctl(2), it could be a buffer argument to a new system call you create, you have a lot of choices.

like image 70
sarnold Avatar answered Nov 20 '22 10:11

sarnold