aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 2ce29831feb6..f3d5812693d6 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 79693fe2001e..47497c97c8d9 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)