• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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@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 
device_release(struct device * dev)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 
sys_result(struct device * dev,struct device_attribute * attr,char * buf)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 
sys_tcase(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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 
uaccess_init(void)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 }
module_init(uaccess_init)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