aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/livepatch/core.c
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@redhat.com>2017-02-13 20:42:35 -0500
committerJiri Kosina <jkosina@suse.cz>2017-03-08 03:23:16 -0500
commit0dade9f374f1c15f9b43ab01ab75a3b459bba5f6 (patch)
tree2ce5e295256b7be0a39df16284d8800baacac1bb /kernel/livepatch/core.c
parent2f09ca60a56dd9c217d32d68340e1b08cbbe1ace (diff)
livepatch: separate enabled and patched states
Once we have a consistency model, patches and their objects will be enabled and disabled at different times. For example, when a patch is disabled, its loaded objects' funcs can remain registered with ftrace indefinitely until the unpatching operation is complete and they're no longer in use. It's less confusing if we give them different names: patches can be enabled or disabled; objects (and their funcs) can be patched or unpatched: - Enabled means that a patch is logically enabled (but not necessarily fully applied). - Patched means that an object's funcs are registered with ftrace and added to the klp_ops func stack. Also, since these states are binary, represent them with booleans instead of ints. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Acked-by: Miroslav Benes <mbenes@suse.cz> Reviewed-by: Petr Mladek <pmladek@suse.com> Reviewed-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'kernel/livepatch/core.c')
-rw-r--r--kernel/livepatch/core.c72
1 files changed, 36 insertions, 36 deletions
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 217b39d71176..2dbd355cee07 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -348,11 +348,11 @@ static unsigned long klp_get_ftrace_location(unsigned long faddr)
348} 348}
349#endif 349#endif
350 350
351static void klp_disable_func(struct klp_func *func) 351static void klp_unpatch_func(struct klp_func *func)
352{ 352{
353 struct klp_ops *ops; 353 struct klp_ops *ops;
354 354
355 if (WARN_ON(func->state != KLP_ENABLED)) 355 if (WARN_ON(!func->patched))
356 return; 356 return;
357 if (WARN_ON(!func->old_addr)) 357 if (WARN_ON(!func->old_addr))
358 return; 358 return;
@@ -378,10 +378,10 @@ static void klp_disable_func(struct klp_func *func)
378 list_del_rcu(&func->stack_node); 378 list_del_rcu(&func->stack_node);
379 } 379 }
380 380
381 func->state = KLP_DISABLED; 381 func->patched = false;
382} 382}
383 383
384static int klp_enable_func(struct klp_func *func) 384static int klp_patch_func(struct klp_func *func)
385{ 385{
386 struct klp_ops *ops; 386 struct klp_ops *ops;
387 int ret; 387 int ret;
@@ -389,7 +389,7 @@ static int klp_enable_func(struct klp_func *func)
389 if (WARN_ON(!func->old_addr)) 389 if (WARN_ON(!func->old_addr))
390 return -EINVAL; 390 return -EINVAL;
391 391
392 if (WARN_ON(func->state != KLP_DISABLED)) 392 if (WARN_ON(func->patched))
393 return -EINVAL; 393 return -EINVAL;
394 394
395 ops = klp_find_ops(func->old_addr); 395 ops = klp_find_ops(func->old_addr);
@@ -437,7 +437,7 @@ static int klp_enable_func(struct klp_func *func)
437 list_add_rcu(&func->stack_node, &ops->func_stack); 437 list_add_rcu(&func->stack_node, &ops->func_stack);
438 } 438 }
439 439
440 func->state = KLP_ENABLED; 440 func->patched = true;
441 441
442 return 0; 442 return 0;
443 443
@@ -448,36 +448,36 @@ err:
448 return ret; 448 return ret;
449} 449}
450 450
451static void klp_disable_object(struct klp_object *obj) 451static void klp_unpatch_object(struct klp_object *obj)
452{ 452{
453 struct klp_func *func; 453 struct klp_func *func;
454 454
455 klp_for_each_func(obj, func) 455 klp_for_each_func(obj, func)
456 if (func->state == KLP_ENABLED) 456 if (func->patched)
457 klp_disable_func(func); 457 klp_unpatch_func(func);
458 458
459 obj->state = KLP_DISABLED; 459 obj->patched = false;
460} 460}
461 461
462static int klp_enable_object(struct klp_object *obj) 462static int klp_patch_object(struct klp_object *obj)
463{ 463{
464 struct klp_func *func; 464 struct klp_func *func;
465 int ret; 465 int ret;
466 466
467 if (WARN_ON(obj->state != KLP_DISABLED)) 467 if (WARN_ON(obj->patched))
468 return -EINVAL; 468 return -EINVAL;
469 469
470 if (WARN_ON(!klp_is_object_loaded(obj))) 470 if (WARN_ON(!klp_is_object_loaded(obj)))
471 return -EINVAL; 471 return -EINVAL;
472 472
473 klp_for_each_func(obj, func) { 473 klp_for_each_func(obj, func) {
474 ret = klp_enable_func(func); 474 ret = klp_patch_func(func);
475 if (ret) { 475 if (ret) {
476 klp_disable_object(obj); 476 klp_unpatch_object(obj);
477 return ret; 477 return ret;
478 } 478 }
479 } 479 }
480 obj->state = KLP_ENABLED; 480 obj->patched = true;
481 481
482 return 0; 482 return 0;
483} 483}
@@ -488,17 +488,17 @@ static int __klp_disable_patch(struct klp_patch *patch)
488 488
489 /* enforce stacking: only the last enabled patch can be disabled */ 489 /* enforce stacking: only the last enabled patch can be disabled */
490 if (!list_is_last(&patch->list, &klp_patches) && 490 if (!list_is_last(&patch->list, &klp_patches) &&
491 list_next_entry(patch, list)->state == KLP_ENABLED) 491 list_next_entry(patch, list)->enabled)
492 return -EBUSY; 492 return -EBUSY;
493 493
494 pr_notice("disabling patch '%s'\n", patch->mod->name); 494 pr_notice("disabling patch '%s'\n", patch->mod->name);
495 495
496 klp_for_each_object(patch, obj) { 496 klp_for_each_object(patch, obj) {
497 if (obj->state == KLP_ENABLED) 497 if (obj->patched)
498 klp_disable_object(obj); 498 klp_unpatch_object(obj);
499 } 499 }
500 500
501 patch->state = KLP_DISABLED; 501 patch->enabled = false;
502 502
503 return 0; 503 return 0;
504} 504}
@@ -522,7 +522,7 @@ int klp_disable_patch(struct klp_patch *patch)
522 goto err; 522 goto err;
523 } 523 }
524 524
525 if (patch->state == KLP_DISABLED) { 525 if (!patch->enabled) {
526 ret = -EINVAL; 526 ret = -EINVAL;
527 goto err; 527 goto err;
528 } 528 }
@@ -540,12 +540,12 @@ static int __klp_enable_patch(struct klp_patch *patch)
540 struct klp_object *obj; 540 struct klp_object *obj;
541 int ret; 541 int ret;
542 542
543 if (WARN_ON(patch->state != KLP_DISABLED)) 543 if (WARN_ON(patch->enabled))
544 return -EINVAL; 544 return -EINVAL;
545 545
546 /* enforce stacking: only the first disabled patch can be enabled */ 546 /* enforce stacking: only the first disabled patch can be enabled */
547 if (patch->list.prev != &klp_patches && 547 if (patch->list.prev != &klp_patches &&
548 list_prev_entry(patch, list)->state == KLP_DISABLED) 548 !list_prev_entry(patch, list)->enabled)
549 return -EBUSY; 549 return -EBUSY;
550 550
551 pr_notice("enabling patch '%s'\n", patch->mod->name); 551 pr_notice("enabling patch '%s'\n", patch->mod->name);
@@ -554,12 +554,12 @@ static int __klp_enable_patch(struct klp_patch *patch)
554 if (!klp_is_object_loaded(obj)) 554 if (!klp_is_object_loaded(obj))
555 continue; 555 continue;
556 556
557 ret = klp_enable_object(obj); 557 ret = klp_patch_object(obj);
558 if (ret) 558 if (ret)
559 goto unregister; 559 goto unregister;
560 } 560 }
561 561
562 patch->state = KLP_ENABLED; 562 patch->enabled = true;
563 563
564 return 0; 564 return 0;
565 565
@@ -617,20 +617,20 @@ static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
617 if (ret) 617 if (ret)
618 return -EINVAL; 618 return -EINVAL;
619 619
620 if (val != KLP_DISABLED && val != KLP_ENABLED) 620 if (val > 1)
621 return -EINVAL; 621 return -EINVAL;
622 622
623 patch = container_of(kobj, struct klp_patch, kobj); 623 patch = container_of(kobj, struct klp_patch, kobj);
624 624
625 mutex_lock(&klp_mutex); 625 mutex_lock(&klp_mutex);
626 626
627 if (val == patch->state) { 627 if (patch->enabled == val) {
628 /* already in requested state */ 628 /* already in requested state */
629 ret = -EINVAL; 629 ret = -EINVAL;
630 goto err; 630 goto err;
631 } 631 }
632 632
633 if (val == KLP_ENABLED) { 633 if (val) {
634 ret = __klp_enable_patch(patch); 634 ret = __klp_enable_patch(patch);
635 if (ret) 635 if (ret)
636 goto err; 636 goto err;
@@ -655,7 +655,7 @@ static ssize_t enabled_show(struct kobject *kobj,
655 struct klp_patch *patch; 655 struct klp_patch *patch;
656 656
657 patch = container_of(kobj, struct klp_patch, kobj); 657 patch = container_of(kobj, struct klp_patch, kobj);
658 return snprintf(buf, PAGE_SIZE-1, "%d\n", patch->state); 658 return snprintf(buf, PAGE_SIZE-1, "%d\n", patch->enabled);
659} 659}
660 660
661static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled); 661static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled);
@@ -749,7 +749,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
749 return -EINVAL; 749 return -EINVAL;
750 750
751 INIT_LIST_HEAD(&func->stack_node); 751 INIT_LIST_HEAD(&func->stack_node);
752 func->state = KLP_DISABLED; 752 func->patched = false;
753 753
754 /* The format for the sysfs directory is <function,sympos> where sympos 754 /* The format for the sysfs directory is <function,sympos> where sympos
755 * is the nth occurrence of this symbol in kallsyms for the patched 755 * is the nth occurrence of this symbol in kallsyms for the patched
@@ -804,7 +804,7 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
804 if (!obj->funcs) 804 if (!obj->funcs)
805 return -EINVAL; 805 return -EINVAL;
806 806
807 obj->state = KLP_DISABLED; 807 obj->patched = false;
808 obj->mod = NULL; 808 obj->mod = NULL;
809 809
810 klp_find_object_module(obj); 810 klp_find_object_module(obj);
@@ -845,7 +845,7 @@ static int klp_init_patch(struct klp_patch *patch)
845 845
846 mutex_lock(&klp_mutex); 846 mutex_lock(&klp_mutex);
847 847
848 patch->state = KLP_DISABLED; 848 patch->enabled = false;
849 849
850 ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch, 850 ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch,
851 klp_root_kobj, "%s", patch->mod->name); 851 klp_root_kobj, "%s", patch->mod->name);
@@ -891,7 +891,7 @@ int klp_unregister_patch(struct klp_patch *patch)
891 goto out; 891 goto out;
892 } 892 }
893 893
894 if (patch->state == KLP_ENABLED) { 894 if (patch->enabled) {
895 ret = -EBUSY; 895 ret = -EBUSY;
896 goto out; 896 goto out;
897 } 897 }
@@ -978,13 +978,13 @@ int klp_module_coming(struct module *mod)
978 goto err; 978 goto err;
979 } 979 }
980 980
981 if (patch->state == KLP_DISABLED) 981 if (!patch->enabled)
982 break; 982 break;
983 983
984 pr_notice("applying patch '%s' to loading module '%s'\n", 984 pr_notice("applying patch '%s' to loading module '%s'\n",
985 patch->mod->name, obj->mod->name); 985 patch->mod->name, obj->mod->name);
986 986
987 ret = klp_enable_object(obj); 987 ret = klp_patch_object(obj);
988 if (ret) { 988 if (ret) {
989 pr_warn("failed to apply patch '%s' to module '%s' (%d)\n", 989 pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
990 patch->mod->name, obj->mod->name, ret); 990 patch->mod->name, obj->mod->name, ret);
@@ -1035,10 +1035,10 @@ void klp_module_going(struct module *mod)
1035 if (!klp_is_module(obj) || strcmp(obj->name, mod->name)) 1035 if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
1036 continue; 1036 continue;
1037 1037
1038 if (patch->state != KLP_DISABLED) { 1038 if (patch->enabled) {
1039 pr_notice("reverting patch '%s' on unloading module '%s'\n", 1039 pr_notice("reverting patch '%s' on unloading module '%s'\n",
1040 patch->mod->name, obj->mod->name); 1040 patch->mod->name, obj->mod->name);
1041 klp_disable_object(obj); 1041 klp_unpatch_object(obj);
1042 } 1042 }
1043 1043
1044 klp_free_object_loaded(obj); 1044 klp_free_object_loaded(obj);