aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-05 08:51:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:02:29 -0400
commit1be491fca12ff599c37ceaf7e9042ebee9f0068e (patch)
tree96033bde1ed8561201c42574ec716f7cfd033697
parent3355443ad7601991affa5992b0d53870335af765 (diff)
rfkill: prep for rfkill API changes
We've designed the /dev/rfkill API in a way that we can increase the event struct by adding members at the end, should it become necessary. To validate the events, userspace and the kernel need to have the proper event size to check for -- when reading from the other end they need to verify that it's at least version 1 of the event API, with the current struct size, so define a constant for that and make the code a little more 'future proof'. Not that I expect that we'll have to change the event size any time soon, but it's better to write the code in a way that lends itself to extending. Due to the current size of the event struct, the code is currently equivalent, but should the event struct ever need to be increased the new code might not need changing. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/rfkill.h14
-rw-r--r--net/rfkill/core.c10
2 files changed, 22 insertions, 2 deletions
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index 2ce29831feb..f3d5812693d 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -82,6 +82,20 @@ struct rfkill_event {
82 __u8 soft, hard; 82 __u8 soft, hard;
83} __packed; 83} __packed;
84 84
85/*
86 * We are planning to be backward and forward compatible with changes
87 * to the event struct, by adding new, optional, members at the end.
88 * When reading an event (whether the kernel from userspace or vice
89 * versa) we need to accept anything that's at least as large as the
90 * version 1 event size, but might be able to accept other sizes in
91 * the future.
92 *
93 * One exception is the kernel -- we already have two event sizes in
94 * that we've made the 'hard' member optional since our only option
95 * is to ignore it anyway.
96 */
97#define RFKILL_EVENT_SIZE_V1 8
98
85/* ioctl for turning off rfkill-input (if present) */ 99/* ioctl for turning off rfkill-input (if present) */
86#define RFKILL_IOC_MAGIC 'R' 100#define RFKILL_IOC_MAGIC 'R'
87#define RFKILL_IOC_NOINPUT 1 101#define RFKILL_IOC_NOINPUT 1
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 79693fe2001..47497c97c8d 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -1076,10 +1076,16 @@ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf,
1076 struct rfkill_event ev; 1076 struct rfkill_event ev;
1077 1077
1078 /* we don't need the 'hard' variable but accept it */ 1078 /* we don't need the 'hard' variable but accept it */
1079 if (count < sizeof(ev) - 1) 1079 if (count < RFKILL_EVENT_SIZE_V1 - 1)
1080 return -EINVAL; 1080 return -EINVAL;
1081 1081
1082 if (copy_from_user(&ev, buf, sizeof(ev) - 1)) 1082 /*
1083 * Copy as much data as we can accept into our 'ev' buffer,
1084 * but tell userspace how much we've copied so it can determine
1085 * our API version even in a write() call, if it cares.
1086 */
1087 count = min(count, sizeof(ev));
1088 if (copy_from_user(&ev, buf, count))
1083 return -EFAULT; 1089 return -EFAULT;
1084 1090
1085 if (ev.op != RFKILL_OP_CHANGE && ev.op != RFKILL_OP_CHANGE_ALL) 1091 if (ev.op != RFKILL_OP_CHANGE && ev.op != RFKILL_OP_CHANGE_ALL)