LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   IOCTL locking kernel on Xeon E3-1270 v5 (https://www.linuxquestions.org/questions/linux-software-2/ioctl-locking-kernel-on-xeon-e3-1270-v5-4175585552/)

SignoEleven 07-26-2016 09:43 AM

IOCTL locking kernel on Xeon E3-1270 v5
 
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.

Here's is an example code:

Kernel Module Header:

#include <linux/ioctl.h>

#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)


Kernel Module Source:

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

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->test1, bufferPtr->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->ops = &fops;
kernel_cdev->owner = THIS_MODULE;
printk (" Inside init module\n");
ret = alloc_chrdev_region( &dev_no , 0, 1,"char_arr_dev");
if (ret < 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 < 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);

Test Code:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#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", &buffer, buffer.test1, buffer.test2);

ioctl(fd,IOCTL_BUFFER_TEST,&buffer);

close(fd);
}

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.

If I use the copy_to_user and copy_from_user, 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?

smallpond 07-28-2016 11:51 AM

Kernel and user are different virtual address spaces. If you have some reference to this "IOWR" I would be interested in hearing about it, but basically the segfault is expected.

SignoEleven 07-28-2016 04:21 PM

Thank you for your reply.

I have kernel modules which use the IOWR definition which seems allows the kernel module to directly access the user space address with no problem. It's been running on dozens of systems for years with fairly recent and 5-6 year old CPUs. However, for some reason only this new Xeon E3-1270 v5 seems to lock up hard if I use the exact same method. It only works if I use the copy_from_user macro. I just don't understand why. Was I just lucky in the past on those older systems or is there something new in the Xeon which is forcing this? Maybe a new MMU? It just seems odd.


All times are GMT -5. The time now is 11:12 AM.