diff options
-rw-r--r-- | include/linux/rfkill.h | 14 | ||||
-rw-r--r-- | net/rfkill/core.c | 10 |
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) |