Welcome! Log In Create A New Profile

Advanced

How to pass variable size stuff from user to kernel in an ioctl() call?

Posted by markfarnell 
How to pass variable size stuff from user to kernel in an ioctl() call?
November 12, 2008 05:45PM
I think about passing an array (size known at runtime) from user space to kernel space in an ioctl() call. Is it possible to be done? If so, how?

Isn't it true that each ioctl call has an associated fixed-size struct for communication purpose? I am confused.

Thanks!

Mark
Maybe you could have a separate ioctl call which first tells the length of the array, and then a second call which passes the character pointer?
Here is the one-ioctl call sample

Common header for both kernel level and user space
struct data {
    the data here
};

struct my_evt {
    size_t number;
    struct data *array;
};

Code working in the kernel
static int f_on_ioctl(struct inode *inode,	/* linux/fs.h */
    struct file *file,	
    unsigned int ioctl_num,	/* number and param for ioctl */
    unsigned long ioctl_param
){
    int ret = -EINVAL;

    switch (ioctl_num) {
        /* Which command passed */
        case IOCTL_CTL_IN:
            ret = evts_push((struct my_evt*)ioctl_param);
            break;
        case IOCTL_CTL_OUT:
            ret = evts_pop((struct my_evt*)ioctl_param);
            break;
        default:
            printk(KERN_DEBUG" %s unknown command %d\n",
                __FUNCTION__,
                ioctl_num
            );
            break;
    }

    return ret;
}

int evts_push(struct my_evt *user)
{
    struct my_evt event;
    struct data *array_address;

    /* Copy the user info from user */
    CopyFromUser(&event, user, sizeof event);
    array_address = event.array;

    /* Once got the number and the address, copy the array from user */
    event.array = KAllocateData(event.number); 
    CopyFromUser(event.array, array_address, event.number * sizeof(*event.array));
    ...
}

User space code
int push(struct data *p, const size_t number)
{
    struct my_evt event = {
        .number = number,
        .array = p
    } ;
    /* Give the ioctl command and the address of the event as the param */
    IOCtrl(ioctl_cmd, &event);
    ...
}

Done!

If you had communication protocol sense, you'd get better solution than my example.

--The Effo Staff
Effo Project, [effo.sourceforge.net]
Author:

Your Email:


Subject:


Spam prevention:
Please, solve the mathematical question and enter the answer in the input field below. This is for blocking bots that try to post this form automatically.
Question: how much is 14 plus 6?
Message: