diff options
Diffstat (limited to 'kernel/livepatch/core.c')
-rw-r--r-- | kernel/livepatch/core.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 88766bd91803..1c3c9b27c916 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c | |||
@@ -455,6 +455,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch); | |||
455 | * /sys/kernel/livepatch/<patch>/enabled | 455 | * /sys/kernel/livepatch/<patch>/enabled |
456 | * /sys/kernel/livepatch/<patch>/transition | 456 | * /sys/kernel/livepatch/<patch>/transition |
457 | * /sys/kernel/livepatch/<patch>/signal | 457 | * /sys/kernel/livepatch/<patch>/signal |
458 | * /sys/kernel/livepatch/<patch>/force | ||
458 | * /sys/kernel/livepatch/<patch>/<object> | 459 | * /sys/kernel/livepatch/<patch>/<object> |
459 | * /sys/kernel/livepatch/<patch>/<object>/<function,sympos> | 460 | * /sys/kernel/livepatch/<patch>/<object>/<function,sympos> |
460 | */ | 461 | */ |
@@ -556,13 +557,42 @@ static ssize_t signal_store(struct kobject *kobj, struct kobj_attribute *attr, | |||
556 | return count; | 557 | return count; |
557 | } | 558 | } |
558 | 559 | ||
560 | static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr, | ||
561 | const char *buf, size_t count) | ||
562 | { | ||
563 | struct klp_patch *patch; | ||
564 | int ret; | ||
565 | bool val; | ||
566 | |||
567 | patch = container_of(kobj, struct klp_patch, kobj); | ||
568 | |||
569 | /* | ||
570 | * klp_mutex lock is not grabbed here intentionally. It is not really | ||
571 | * needed. The race window is harmless and grabbing the lock would only | ||
572 | * hold the action back. | ||
573 | */ | ||
574 | if (patch != klp_transition_patch) | ||
575 | return -EINVAL; | ||
576 | |||
577 | ret = kstrtobool(buf, &val); | ||
578 | if (ret) | ||
579 | return ret; | ||
580 | |||
581 | if (val) | ||
582 | klp_force_transition(); | ||
583 | |||
584 | return count; | ||
585 | } | ||
586 | |||
559 | static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled); | 587 | static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled); |
560 | static struct kobj_attribute transition_kobj_attr = __ATTR_RO(transition); | 588 | static struct kobj_attribute transition_kobj_attr = __ATTR_RO(transition); |
561 | static struct kobj_attribute signal_kobj_attr = __ATTR_WO(signal); | 589 | static struct kobj_attribute signal_kobj_attr = __ATTR_WO(signal); |
590 | static struct kobj_attribute force_kobj_attr = __ATTR_WO(force); | ||
562 | static struct attribute *klp_patch_attrs[] = { | 591 | static struct attribute *klp_patch_attrs[] = { |
563 | &enabled_kobj_attr.attr, | 592 | &enabled_kobj_attr.attr, |
564 | &transition_kobj_attr.attr, | 593 | &transition_kobj_attr.attr, |
565 | &signal_kobj_attr.attr, | 594 | &signal_kobj_attr.attr, |
595 | &force_kobj_attr.attr, | ||
566 | NULL | 596 | NULL |
567 | }; | 597 | }; |
568 | 598 | ||