Commit 1be491fca12ff599c37ceaf7e9042ebee9f0068e

Authored by Johannes Berg
Committed by John W. Linville
1 parent 3355443ad7

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>

Showing 2 changed files with 22 additions and 2 deletions Side-by-side Diff

include/linux/rfkill.h
... ... @@ -82,6 +82,20 @@
82 82 __u8 soft, hard;
83 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 99 /* ioctl for turning off rfkill-input (if present) */
86 100 #define RFKILL_IOC_MAGIC 'R'
87 101 #define RFKILL_IOC_NOINPUT 1
... ... @@ -1076,10 +1076,16 @@
1076 1076 struct rfkill_event ev;
1077 1077  
1078 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 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 1089 return -EFAULT;
1084 1090  
1085 1091 if (ev.op != RFKILL_OP_CHANGE && ev.op != RFKILL_OP_CHANGE_ALL)