Home | History | Annotate | Download | only in uaccess
      1 /*
      2  * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
      3  *
      4  * This program is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU General Public License as
      6  * published by the Free Software Foundation; either version 2 of
      7  * the License, or (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it would be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write the Free Software Foundation,
     16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17  *
     18  * Author: Alexey Kodanev <alexey.kodanev (at) oracle.com>
     19  *
     20  */
     21 
     22 #include <linux/module.h>
     23 #include <linux/device.h>
     24 #include <linux/uaccess.h>
     25 #include "ltp_uaccess.h"
     26 
     27 MODULE_AUTHOR("Alexey Kodanev <alexey.kodanev (at) oracle.com>");
     28 MODULE_DESCRIPTION("User-space access LTP test");
     29 MODULE_LICENSE("GPL");
     30 
     31 #define prk_err(fmt, ...) \
     32 	pr_err(DEV_NAME ": " fmt "\n", ##__VA_ARGS__)
     33 #define prk_info(fmt, ...) \
     34 	pr_info(DEV_NAME ": " fmt "\n", ##__VA_ARGS__)
     35 
     36 /*
     37  * Test-case result,
     38  * if test is passed, value will be set to 0
     39  */
     40 static int test_result;
     41 
     42 static void device_release(struct device *dev)
     43 {
     44 	prk_info("device released");
     45 }
     46 
     47 static struct device tdev = {
     48 	.init_name	= DEV_NAME,
     49 	.release	= device_release
     50 };
     51 
     52 static ssize_t sys_result(struct device *dev,
     53 	struct device_attribute *attr, char *buf)
     54 {
     55 	return scnprintf(buf, PAGE_SIZE, "%d\n", test_result);
     56 }
     57 static DEVICE_ATTR(result, S_IRUSR, sys_result, NULL);
     58 
     59 
     60 static ssize_t sys_tcase(struct device *dev,
     61 	struct device_attribute *attr,  const char *buf, size_t count)
     62 {
     63 	unsigned long ptr = 0;
     64 	int tc = 0;
     65 	char *str, ch, buffer[str_size];
     66 
     67 	sscanf(buf, "%d %lu", &tc, &ptr);
     68 	str = (char *) ptr;
     69 	test_result = 0;
     70 
     71 	switch (tc) {
     72 	case TC_READ_USER:
     73 		if (copy_from_user(buffer, str, str_size))
     74 			prk_err("copy_from_user() failed");
     75 		test_result = strncmp(test_str, buffer, str_size) ? 1 : 0;
     76 		if (get_user(ch, str))
     77 			prk_err("get_user() failed");
     78 		test_result |= ch != test_str[0];
     79 	break;
     80 	case TC_WRITE_USER:
     81 		if (copy_to_user(str + 1, test_str + 1, str_size - 1)) {
     82 			prk_err("copy_to_user() failed");
     83 			test_result = 1;
     84 		}
     85 		/* write the first skipped character */
     86 		if (put_user(test_str[0], str)) {
     87 			prk_err("put_user() failed");
     88 			test_result |= 1;
     89 		}
     90 	break;
     91 	}
     92 
     93 	return count;
     94 }
     95 static DEVICE_ATTR(tcase, S_IWUSR, NULL, sys_tcase);
     96 
     97 static int uaccess_init(void)
     98 {
     99 	int err = 0;
    100 	prk_info("Starting module");
    101 
    102 	err = device_register(&tdev);
    103 	if (err) {
    104 		prk_err("Unable to register device");
    105 		goto err0;
    106 	}
    107 	prk_info("device registered");
    108 
    109 	err = device_create_file(&tdev, &dev_attr_result);
    110 	if (err) {
    111 		prk_err("Can't create sysfs file 'result'");
    112 		goto err1;
    113 	}
    114 
    115 	err = device_create_file(&tdev, &dev_attr_tcase);
    116 	if (err) {
    117 		prk_err(": Can't create sysfs file 'tc'");
    118 		goto err2;
    119 	}
    120 
    121 	return 0;
    122 
    123 err2:
    124 	device_remove_file(&tdev, &dev_attr_result);
    125 err1:
    126 	device_unregister(&tdev);
    127 err0:
    128 	return err;
    129 }
    130 module_init(uaccess_init)
    131 
    132 static void uaccess_exit(void)
    133 {
    134 	prk_info("Unloading module");
    135 
    136 	device_remove_file(&tdev, &dev_attr_result);
    137 	device_remove_file(&tdev, &dev_attr_tcase);
    138 	device_unregister(&tdev);
    139 }
    140 module_exit(uaccess_exit)
    141