IOCTL locking kernel on Xeon E3-1270 v5
<p>Has anyone experienced an issue with a system lock up when using IOWR with IOCTL on an Intel Xeon E3-1270 CPU? I have 3 different distributions (Centos 7.2, Ubuntu 14.04, Ubuntu 16.04) on 3 different Dell boxes using the above CPU and every time I use IOCTL with an IOWR the system locks up as soon as I access the memory sent up in the arg variable of the ioctl call. </p>

<p>Here's is an example code:</p>

<p>Kernel Module Header:</p>

<pre><code>#include &lt;linux/ioctl.h&gt;

#define IOC_MAGIC 'k'

typedef struct
{
    int test1;
    int test2;
} bufferTest;

#define IOCTL_HELLO _IO(IOC_MAGIC,0)
#define IOCTL_BUFFER_TEST  _IOWR(IOC_MAGIC,1, bufferTest)
</code></pre>

<p>Kernel Module Source:</p>

<pre><code>#include &lt;linux/module.h&gt;
#include &lt;linux/kernel.h&gt;
#include &lt;linux/fs.h&gt; // required for various structures related to files liked fops.
#include &lt;linux/semaphore.h&gt;
#include &lt;linux/cdev.h&gt;
#include "ioctl_basic.h"    //ioctl header file
#include &lt;linux/version.h&gt;
#include &lt;asm/uaccess.h&gt;

int open(struct inode *inode, struct file *filp)
{
    printk(KERN_INFO "Inside open \n");
    return 0;
}

int release(struct inode *inode, struct file *filp)
{
    printk (KERN_INFO "Inside close \n");
     return 0;
}

long ioctl_funcs(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int ret=0;
    int index=0;
    bufferTest *bufferPtr = NULL;
    void *userPtr = NULL;

    printk(KERN_INFO "ioctl_func: %u\n", cmd);

    switch(cmd) {

    case IOCTL_HELLO:
        printk(KERN_INFO "Hello ioctl world\n");
        ret = 1;
        break;
    case IOCTL_BUFFER_TEST:
        bufferPtr = (bufferTest *)arg;
        userPtr = (void *)arg;

        if (access_ok(VERIFY_WRITE, userPtr, sizeof(bufferTest)))
        {
            printk(KERN_INFO "Success verify memory write\n");
            printk(KERN_INFO "test1: %d, test2: %d\n", bufferPtr-&gt;test1, bufferPtr-&gt;test2);
        }
        else
            printk(KERN_INFO "Failed to verify memory write\n");
        break;
    default:
        printk(KERN_INFO "Unknown command: %d\n", cmd);
        break;
     }

    return ret;
}

struct file_operations fops = {
 .open =   open,
 .unlocked_ioctl =  ioctl_funcs,
 .release = release
};


struct cdev *kernel_cdev;


int char_arr_init (void) {
    int ret;
    dev_t dev_no,dev;

    kernel_cdev = cdev_alloc();
    kernel_cdev-&gt;ops = &amp;fops;
    kernel_cdev-&gt;owner = THIS_MODULE;
    printk (" Inside init module\n");
    ret = alloc_chrdev_region( &amp;dev_no , 0, 1,"char_arr_dev");
    if (ret &lt; 0) {
        printk("Major number allocation is failed\n");
    return ret;
    }

    Major = MAJOR(dev_no);
    dev = MKDEV(Major,0);

    printk (" The major number for your device is %d\n", Major);
    ret = cdev_add( kernel_cdev,dev,1);
    if(ret &lt; 0 )
    {
        printk(KERN_INFO "Unable to allocate cdev");
        return ret;
    }

    return 0;
}

void char_arr_cleanup(void) {
    printk(KERN_INFO " Inside cleanup_module\n");
    cdev_del(kernel_cdev);
    unregister_chrdev_region(Major, 1);
}

MODULE_LICENSE("GPL");
module_init(char_arr_init);
module_exit(char_arr_cleanup);
</code></pre>

<p>Test Code:</p>

<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;unistd.h&gt;
#include "ioctl_basic.h"  //ioctl header file

main ( ) {
    int fd;
    bufferTest buffer;

    fd = open("/dev/temp", O_RDWR);

    if (fd == -1)
    {
        printf("Error in opening file \n");
        return;
    }

    ioctl(fd,IOCTL_HELLO);  //ioctl call

    buffer.test1 = 5;
    buffer.test2 = 10;

    printf("buffer ptr: %p, test1: %d, test2: %d\n", &amp;buffer, buffer.test1, buffer.test2);

    ioctl(fd,IOCTL_BUFFER_TEST,&amp;buffer);

    close(fd);
}
</code></pre>

<p>In the kernel module I cast (bufferTest *) to the arg parameter, as soon as I try to print "test1" or "test2" the system will lock up. This does not happen on any of my other systems not using this particular CPU. </p>

<p>If I use the copy_to_user and copy_from_user to copy the arg parameter to a local structure in the kernel module then things work fine, but I thought using the IOWR define I can access the memory directly. It seems like the Xeon E3-1270 processor is having some kind of issue, and I can't figure out what it is. Has anyone else experienced this issue? </p>