aboutsummaryrefslogtreecommitdiffstats
path: root/net/rfkill/rfkill.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rfkill/rfkill.c')
-rw-r--r--net/rfkill/rfkill.c104
1 files changed, 70 insertions, 34 deletions
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 47e0b2d232e3..d5735799ccd9 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -37,7 +37,7 @@ MODULE_DESCRIPTION("RF switch support");
37MODULE_LICENSE("GPL"); 37MODULE_LICENSE("GPL");
38 38
39static LIST_HEAD(rfkill_list); /* list of registered rf switches */ 39static LIST_HEAD(rfkill_list); /* list of registered rf switches */
40static DEFINE_MUTEX(rfkill_mutex); 40static DEFINE_MUTEX(rfkill_global_mutex);
41 41
42static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED; 42static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED;
43module_param_named(default_state, rfkill_default_state, uint, 0444); 43module_param_named(default_state, rfkill_default_state, uint, 0444);
@@ -76,6 +76,7 @@ static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list);
76 */ 76 */
77int register_rfkill_notifier(struct notifier_block *nb) 77int register_rfkill_notifier(struct notifier_block *nb)
78{ 78{
79 BUG_ON(!nb);
79 return blocking_notifier_chain_register(&rfkill_notifier_list, nb); 80 return blocking_notifier_chain_register(&rfkill_notifier_list, nb);
80} 81}
81EXPORT_SYMBOL_GPL(register_rfkill_notifier); 82EXPORT_SYMBOL_GPL(register_rfkill_notifier);
@@ -91,6 +92,7 @@ EXPORT_SYMBOL_GPL(register_rfkill_notifier);
91 */ 92 */
92int unregister_rfkill_notifier(struct notifier_block *nb) 93int unregister_rfkill_notifier(struct notifier_block *nb)
93{ 94{
95 BUG_ON(!nb);
94 return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb); 96 return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb);
95} 97}
96EXPORT_SYMBOL_GPL(unregister_rfkill_notifier); 98EXPORT_SYMBOL_GPL(unregister_rfkill_notifier);
@@ -202,6 +204,9 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
202 * RFKILL_STATE_HARD_BLOCKED */ 204 * RFKILL_STATE_HARD_BLOCKED */
203 break; 205 break;
204 default: 206 default:
207 WARN(1, KERN_WARNING
208 "rfkill: illegal state %d passed as parameter "
209 "to rfkill_toggle_radio\n", state);
205 return -EINVAL; 210 return -EINVAL;
206 } 211 }
207 212
@@ -229,14 +234,18 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
229 * unless a specific switch is claimed by userspace (in which case, 234 * unless a specific switch is claimed by userspace (in which case,
230 * that switch is left alone) or suspended. 235 * that switch is left alone) or suspended.
231 * 236 *
232 * Caller must have acquired rfkill_mutex. 237 * Caller must have acquired rfkill_global_mutex.
233 */ 238 */
234static void __rfkill_switch_all(const enum rfkill_type type, 239static void __rfkill_switch_all(const enum rfkill_type type,
235 const enum rfkill_state state) 240 const enum rfkill_state state)
236{ 241{
237 struct rfkill *rfkill; 242 struct rfkill *rfkill;
238 243
239 if (unlikely(state >= RFKILL_STATE_MAX)) 244 if (WARN((state >= RFKILL_STATE_MAX || type >= RFKILL_TYPE_MAX),
245 KERN_WARNING
246 "rfkill: illegal state %d or type %d "
247 "passed as parameter to __rfkill_switch_all\n",
248 state, type))
240 return; 249 return;
241 250
242 rfkill_global_states[type].current_state = state; 251 rfkill_global_states[type].current_state = state;
@@ -254,14 +263,14 @@ static void __rfkill_switch_all(const enum rfkill_type type,
254 * @type: type of interfaces to be affected 263 * @type: type of interfaces to be affected
255 * @state: the new state 264 * @state: the new state
256 * 265 *
257 * Acquires rfkill_mutex and calls __rfkill_switch_all(@type, @state). 266 * Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state).
258 * Please refer to __rfkill_switch_all() for details. 267 * Please refer to __rfkill_switch_all() for details.
259 */ 268 */
260void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) 269void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
261{ 270{
262 mutex_lock(&rfkill_mutex); 271 mutex_lock(&rfkill_global_mutex);
263 __rfkill_switch_all(type, state); 272 __rfkill_switch_all(type, state);
264 mutex_unlock(&rfkill_mutex); 273 mutex_unlock(&rfkill_global_mutex);
265} 274}
266EXPORT_SYMBOL(rfkill_switch_all); 275EXPORT_SYMBOL(rfkill_switch_all);
267 276
@@ -269,7 +278,7 @@ EXPORT_SYMBOL(rfkill_switch_all);
269 * rfkill_epo - emergency power off all transmitters 278 * rfkill_epo - emergency power off all transmitters
270 * 279 *
271 * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED, 280 * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED,
272 * ignoring everything in its path but rfkill_mutex and rfkill->mutex. 281 * ignoring everything in its path but rfkill_global_mutex and rfkill->mutex.
273 * 282 *
274 * The global state before the EPO is saved and can be restored later 283 * The global state before the EPO is saved and can be restored later
275 * using rfkill_restore_states(). 284 * using rfkill_restore_states().
@@ -279,7 +288,8 @@ void rfkill_epo(void)
279 struct rfkill *rfkill; 288 struct rfkill *rfkill;
280 int i; 289 int i;
281 290
282 mutex_lock(&rfkill_mutex); 291 mutex_lock(&rfkill_global_mutex);
292
283 list_for_each_entry(rfkill, &rfkill_list, node) { 293 list_for_each_entry(rfkill, &rfkill_list, node) {
284 mutex_lock(&rfkill->mutex); 294 mutex_lock(&rfkill->mutex);
285 rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); 295 rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
@@ -291,7 +301,7 @@ void rfkill_epo(void)
291 rfkill_global_states[i].current_state = 301 rfkill_global_states[i].current_state =
292 RFKILL_STATE_SOFT_BLOCKED; 302 RFKILL_STATE_SOFT_BLOCKED;
293 } 303 }
294 mutex_unlock(&rfkill_mutex); 304 mutex_unlock(&rfkill_global_mutex);
295} 305}
296EXPORT_SYMBOL_GPL(rfkill_epo); 306EXPORT_SYMBOL_GPL(rfkill_epo);
297 307
@@ -306,10 +316,11 @@ void rfkill_restore_states(void)
306{ 316{
307 int i; 317 int i;
308 318
309 mutex_lock(&rfkill_mutex); 319 mutex_lock(&rfkill_global_mutex);
320
310 for (i = 0; i < RFKILL_TYPE_MAX; i++) 321 for (i = 0; i < RFKILL_TYPE_MAX; i++)
311 __rfkill_switch_all(i, rfkill_global_states[i].default_state); 322 __rfkill_switch_all(i, rfkill_global_states[i].default_state);
312 mutex_unlock(&rfkill_mutex); 323 mutex_unlock(&rfkill_global_mutex);
313} 324}
314EXPORT_SYMBOL_GPL(rfkill_restore_states); 325EXPORT_SYMBOL_GPL(rfkill_restore_states);
315 326
@@ -334,7 +345,11 @@ int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
334{ 345{
335 enum rfkill_state oldstate; 346 enum rfkill_state oldstate;
336 347
337 if (unlikely(state >= RFKILL_STATE_MAX)) 348 BUG_ON(!rfkill);
349 if (WARN((state >= RFKILL_STATE_MAX),
350 KERN_WARNING
351 "rfkill: illegal state %d passed as parameter "
352 "to rfkill_force_state\n", state))
338 return -EINVAL; 353 return -EINVAL;
339 354
340 mutex_lock(&rfkill->mutex); 355 mutex_lock(&rfkill->mutex);
@@ -402,12 +417,16 @@ static ssize_t rfkill_state_store(struct device *dev,
402 const char *buf, size_t count) 417 const char *buf, size_t count)
403{ 418{
404 struct rfkill *rfkill = to_rfkill(dev); 419 struct rfkill *rfkill = to_rfkill(dev);
405 unsigned int state = simple_strtoul(buf, NULL, 0); 420 unsigned long state;
406 int error; 421 int error;
407 422
408 if (!capable(CAP_NET_ADMIN)) 423 if (!capable(CAP_NET_ADMIN))
409 return -EPERM; 424 return -EPERM;
410 425
426 error = strict_strtoul(buf, 0, &state);
427 if (error)
428 return error;
429
411 /* RFKILL_STATE_HARD_BLOCKED is illegal here... */ 430 /* RFKILL_STATE_HARD_BLOCKED is illegal here... */
412 if (state != RFKILL_STATE_UNBLOCKED && 431 if (state != RFKILL_STATE_UNBLOCKED &&
413 state != RFKILL_STATE_SOFT_BLOCKED) 432 state != RFKILL_STATE_SOFT_BLOCKED)
@@ -427,7 +446,7 @@ static ssize_t rfkill_claim_show(struct device *dev,
427{ 446{
428 struct rfkill *rfkill = to_rfkill(dev); 447 struct rfkill *rfkill = to_rfkill(dev);
429 448
430 return sprintf(buf, "%d", rfkill->user_claim); 449 return sprintf(buf, "%d\n", rfkill->user_claim);
431} 450}
432 451
433static ssize_t rfkill_claim_store(struct device *dev, 452static ssize_t rfkill_claim_store(struct device *dev,
@@ -435,7 +454,8 @@ static ssize_t rfkill_claim_store(struct device *dev,
435 const char *buf, size_t count) 454 const char *buf, size_t count)
436{ 455{
437 struct rfkill *rfkill = to_rfkill(dev); 456 struct rfkill *rfkill = to_rfkill(dev);
438 bool claim = !!simple_strtoul(buf, NULL, 0); 457 unsigned long claim_tmp;
458 bool claim;
439 int error; 459 int error;
440 460
441 if (!capable(CAP_NET_ADMIN)) 461 if (!capable(CAP_NET_ADMIN))
@@ -444,11 +464,16 @@ static ssize_t rfkill_claim_store(struct device *dev,
444 if (rfkill->user_claim_unsupported) 464 if (rfkill->user_claim_unsupported)
445 return -EOPNOTSUPP; 465 return -EOPNOTSUPP;
446 466
467 error = strict_strtoul(buf, 0, &claim_tmp);
468 if (error)
469 return error;
470 claim = !!claim_tmp;
471
447 /* 472 /*
448 * Take the global lock to make sure the kernel is not in 473 * Take the global lock to make sure the kernel is not in
449 * the middle of rfkill_switch_all 474 * the middle of rfkill_switch_all
450 */ 475 */
451 error = mutex_lock_interruptible(&rfkill_mutex); 476 error = mutex_lock_interruptible(&rfkill_global_mutex);
452 if (error) 477 if (error)
453 return error; 478 return error;
454 479
@@ -463,7 +488,7 @@ static ssize_t rfkill_claim_store(struct device *dev,
463 rfkill->user_claim = claim; 488 rfkill->user_claim = claim;
464 } 489 }
465 490
466 mutex_unlock(&rfkill_mutex); 491 mutex_unlock(&rfkill_global_mutex);
467 492
468 return error ? error : count; 493 return error ? error : count;
469} 494}
@@ -583,10 +608,10 @@ static int rfkill_check_duplicity(const struct rfkill *rfkill)
583 memset(seen, 0, sizeof(seen)); 608 memset(seen, 0, sizeof(seen));
584 609
585 list_for_each_entry(p, &rfkill_list, node) { 610 list_for_each_entry(p, &rfkill_list, node) {
586 if (p == rfkill) { 611 if (WARN((p == rfkill), KERN_WARNING
587 WARN_ON(1); 612 "rfkill: illegal attempt to register "
613 "an already registered rfkill struct\n"))
588 return -EEXIST; 614 return -EEXIST;
589 }
590 set_bit(p->type, seen); 615 set_bit(p->type, seen);
591 } 616 }
592 617
@@ -598,7 +623,7 @@ static int rfkill_add_switch(struct rfkill *rfkill)
598{ 623{
599 int error; 624 int error;
600 625
601 mutex_lock(&rfkill_mutex); 626 mutex_lock(&rfkill_global_mutex);
602 627
603 error = rfkill_check_duplicity(rfkill); 628 error = rfkill_check_duplicity(rfkill);
604 if (error < 0) 629 if (error < 0)
@@ -619,16 +644,16 @@ static int rfkill_add_switch(struct rfkill *rfkill)
619 644
620 error = 0; 645 error = 0;
621unlock_out: 646unlock_out:
622 mutex_unlock(&rfkill_mutex); 647 mutex_unlock(&rfkill_global_mutex);
623 648
624 return error; 649 return error;
625} 650}
626 651
627static void rfkill_remove_switch(struct rfkill *rfkill) 652static void rfkill_remove_switch(struct rfkill *rfkill)
628{ 653{
629 mutex_lock(&rfkill_mutex); 654 mutex_lock(&rfkill_global_mutex);
630 list_del_init(&rfkill->node); 655 list_del_init(&rfkill->node);
631 mutex_unlock(&rfkill_mutex); 656 mutex_unlock(&rfkill_global_mutex);
632 657
633 mutex_lock(&rfkill->mutex); 658 mutex_lock(&rfkill->mutex);
634 rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); 659 rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
@@ -654,6 +679,12 @@ struct rfkill * __must_check rfkill_allocate(struct device *parent,
654 struct rfkill *rfkill; 679 struct rfkill *rfkill;
655 struct device *dev; 680 struct device *dev;
656 681
682 if (WARN((type >= RFKILL_TYPE_MAX),
683 KERN_WARNING
684 "rfkill: illegal type %d passed as parameter "
685 "to rfkill_allocate\n", type))
686 return NULL;
687
657 rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL); 688 rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL);
658 if (!rfkill) 689 if (!rfkill)
659 return NULL; 690 return NULL;
@@ -726,11 +757,12 @@ int __must_check rfkill_register(struct rfkill *rfkill)
726 struct device *dev = &rfkill->dev; 757 struct device *dev = &rfkill->dev;
727 int error; 758 int error;
728 759
729 if (!rfkill->toggle_radio) 760 if (WARN((!rfkill || !rfkill->toggle_radio ||
730 return -EINVAL; 761 rfkill->type >= RFKILL_TYPE_MAX ||
731 if (rfkill->type >= RFKILL_TYPE_MAX) 762 rfkill->state >= RFKILL_STATE_MAX),
732 return -EINVAL; 763 KERN_WARNING
733 if (rfkill->state >= RFKILL_STATE_MAX) 764 "rfkill: attempt to register a "
765 "badly initialized rfkill struct\n"))
734 return -EINVAL; 766 return -EINVAL;
735 767
736 snprintf(dev->bus_id, sizeof(dev->bus_id), 768 snprintf(dev->bus_id, sizeof(dev->bus_id),
@@ -765,6 +797,7 @@ EXPORT_SYMBOL(rfkill_register);
765 */ 797 */
766void rfkill_unregister(struct rfkill *rfkill) 798void rfkill_unregister(struct rfkill *rfkill)
767{ 799{
800 BUG_ON(!rfkill);
768 device_del(&rfkill->dev); 801 device_del(&rfkill->dev);
769 rfkill_remove_switch(rfkill); 802 rfkill_remove_switch(rfkill);
770 rfkill_led_trigger_unregister(rfkill); 803 rfkill_led_trigger_unregister(rfkill);
@@ -801,12 +834,15 @@ int rfkill_set_default(enum rfkill_type type, enum rfkill_state state)
801{ 834{
802 int error; 835 int error;
803 836
804 if (type >= RFKILL_TYPE_MAX || 837 if (WARN((type >= RFKILL_TYPE_MAX ||
805 (state != RFKILL_STATE_SOFT_BLOCKED && 838 (state != RFKILL_STATE_SOFT_BLOCKED &&
806 state != RFKILL_STATE_UNBLOCKED)) 839 state != RFKILL_STATE_UNBLOCKED)),
840 KERN_WARNING
841 "rfkill: illegal state %d or type %d passed as "
842 "parameter to rfkill_set_default\n", state, type))
807 return -EINVAL; 843 return -EINVAL;
808 844
809 mutex_lock(&rfkill_mutex); 845 mutex_lock(&rfkill_global_mutex);
810 846
811 if (!test_and_set_bit(type, rfkill_states_lockdflt)) { 847 if (!test_and_set_bit(type, rfkill_states_lockdflt)) {
812 rfkill_global_states[type].default_state = state; 848 rfkill_global_states[type].default_state = state;
@@ -814,7 +850,7 @@ int rfkill_set_default(enum rfkill_type type, enum rfkill_state state)
814 } else 850 } else
815 error = -EPERM; 851 error = -EPERM;
816 852
817 mutex_unlock(&rfkill_mutex); 853 mutex_unlock(&rfkill_global_mutex);
818 return error; 854 return error;
819} 855}
820EXPORT_SYMBOL_GPL(rfkill_set_default); 856EXPORT_SYMBOL_GPL(rfkill_set_default);