Search code examples
ckernel-moduleioctl

ioct multiple arguments passing


I try to pass two arguments from user space program to change a buffer size and number of buffer on char device. I tried multiple cast I get always cast errors

 error: cannot convert to a pointer type copy_from_user((char *)msg, arg, sizeof(msg));

or

cannot convert to a pointer typecopy_from_user((char *)msg, (char *)arg, sizeof(msg));

header.h

struct ioctl_arguments {
         int block_number;
         int block_size;
 };

the kernel module and the c program include both the header.h

c program

#define DEVICE_PATH "/dev/driver"
#define MAGIC_NO 'k'
struct ioctl_arguments args;
#define IOCTL_CMD _IOWR(MAGIC_NO, 0, args)
int main()
{
    int fd;
    args.block_number = 10;
    args.block_size = 10;
    fd = open(DEVICE_PATH, O_RDWR);
    ioctl(fd, IOCTL_CMD,&args);
    close(fd);
    return 0;
}

device driver

static int BlockNumber = 20;
static int BlockSize = 5;
struct ioctl_arguments msg;

static int sample_ioctl (struct file *filp, unsigned int cmd, unsigned long arg);

static int sample_ioctl (struct file *filp, unsigned int cmd, unsigned long arg) 
{

  // copy two parameters from outside, we use struct
  copy_from_user((char *)msg, (char *)arg, sizeof(msg));

Solution

  • In your device-driver function arg is in reality a pointer so that cast is valid, but msg is not a pointer so the cast to pointer is not valid. You should use &msg (just like you use &args in the user-space code).