livepatch: Convert error about unsupported reliable stacktrace into a warning
[sfrench/cifs-2.6.git] / kernel / livepatch / core.c
index 6f0d9095f662b75b79454a4bbd80dde2849c1170..14f33ab6c583ced8362e94b008893fdc7d075794 100644 (file)
  */
 DEFINE_MUTEX(klp_mutex);
 
-static LIST_HEAD(klp_patches);
+/*
+ * Actively used patches: enabled or in transition. Note that replaced
+ * or disabled patches are not listed even though the related kernel
+ * module still can be loaded.
+ */
+LIST_HEAD(klp_patches);
 
 static struct kobject *klp_root_kobj;
 
@@ -82,20 +87,43 @@ static void klp_find_object_module(struct klp_object *obj)
        mutex_unlock(&module_mutex);
 }
 
-static bool klp_is_patch_registered(struct klp_patch *patch)
+static bool klp_initialized(void)
 {
-       struct klp_patch *mypatch;
+       return !!klp_root_kobj;
+}
 
-       list_for_each_entry(mypatch, &klp_patches, list)
-               if (mypatch == patch)
-                       return true;
+static struct klp_func *klp_find_func(struct klp_object *obj,
+                                     struct klp_func *old_func)
+{
+       struct klp_func *func;
+
+       klp_for_each_func(obj, func) {
+               if ((strcmp(old_func->old_name, func->old_name) == 0) &&
+                   (old_func->old_sympos == func->old_sympos)) {
+                       return func;
+               }
+       }
 
-       return false;
+       return NULL;
 }
 
-static bool klp_initialized(void)
+static struct klp_object *klp_find_object(struct klp_patch *patch,
+                                         struct klp_object *old_obj)
 {
-       return !!klp_root_kobj;
+       struct klp_object *obj;
+
+       klp_for_each_object(patch, obj) {
+               if (klp_is_module(old_obj)) {
+                       if (klp_is_module(obj) &&
+                           strcmp(old_obj->name, obj->name) == 0) {
+                               return obj;
+                       }
+               } else if (!klp_is_module(obj)) {
+                       return obj;
+               }
+       }
+
+       return NULL;
 }
 
 struct klp_find_arg {
@@ -285,13 +313,11 @@ static int klp_write_object_relocations(struct module *pmod,
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/transition
- * /sys/kernel/livepatch/<patch>/signal
  * /sys/kernel/livepatch/<patch>/force
  * /sys/kernel/livepatch/<patch>/<object>
  * /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
  */
 static int __klp_disable_patch(struct klp_patch *patch);
-static int __klp_enable_patch(struct klp_patch *patch);
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
                             const char *buf, size_t count)
@@ -308,40 +334,32 @@ static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
 
        mutex_lock(&klp_mutex);
 
-       if (!klp_is_patch_registered(patch)) {
-               /*
-                * Module with the patch could either disappear meanwhile or is
-                * not properly initialized yet.
-                */
-               ret = -EINVAL;
-               goto err;
-       }
-
        if (patch->enabled == enabled) {
                /* already in requested state */
                ret = -EINVAL;
-               goto err;
+               goto out;
        }
 
-       if (patch == klp_transition_patch) {
+       /*
+        * Allow to reverse a pending transition in both ways. It might be
+        * necessary to complete the transition without forcing and breaking
+        * the system integrity.
+        *
+        * Do not allow to re-enable a disabled patch.
+        */
+       if (patch == klp_transition_patch)
                klp_reverse_transition();
-       } else if (enabled) {
-               ret = __klp_enable_patch(patch);
-               if (ret)
-                       goto err;
-       } else {
+       else if (!enabled)
                ret = __klp_disable_patch(patch);
-               if (ret)
-                       goto err;
-       }
+       else
+               ret = -EINVAL;
 
+out:
        mutex_unlock(&klp_mutex);
 
+       if (ret)
+               return ret;
        return count;
-
-err:
-       mutex_unlock(&klp_mutex);
-       return ret;
 }
 
 static ssize_t enabled_show(struct kobject *kobj,
@@ -363,35 +381,6 @@ static ssize_t transition_show(struct kobject *kobj,
                        patch == klp_transition_patch);
 }
 
-static ssize_t signal_store(struct kobject *kobj, struct kobj_attribute *attr,
-                           const char *buf, size_t count)
-{
-       struct klp_patch *patch;
-       int ret;
-       bool val;
-
-       ret = kstrtobool(buf, &val);
-       if (ret)
-               return ret;
-
-       if (!val)
-               return count;
-
-       mutex_lock(&klp_mutex);
-
-       patch = container_of(kobj, struct klp_patch, kobj);
-       if (patch != klp_transition_patch) {
-               mutex_unlock(&klp_mutex);
-               return -EINVAL;
-       }
-
-       klp_send_signals();
-
-       mutex_unlock(&klp_mutex);
-
-       return count;
-}
-
 static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
                           const char *buf, size_t count)
 {
@@ -423,16 +412,129 @@ static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
 
 static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled);
 static struct kobj_attribute transition_kobj_attr = __ATTR_RO(transition);
-static struct kobj_attribute signal_kobj_attr = __ATTR_WO(signal);
 static struct kobj_attribute force_kobj_attr = __ATTR_WO(force);
 static struct attribute *klp_patch_attrs[] = {
        &enabled_kobj_attr.attr,
        &transition_kobj_attr.attr,
-       &signal_kobj_attr.attr,
        &force_kobj_attr.attr,
        NULL
 };
 
+static void klp_free_object_dynamic(struct klp_object *obj)
+{
+       kfree(obj->name);
+       kfree(obj);
+}
+
+static struct klp_object *klp_alloc_object_dynamic(const char *name)
+{
+       struct klp_object *obj;
+
+       obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+       if (!obj)
+               return NULL;
+
+       if (name) {
+               obj->name = kstrdup(name, GFP_KERNEL);
+               if (!obj->name) {
+                       kfree(obj);
+                       return NULL;
+               }
+       }
+
+       INIT_LIST_HEAD(&obj->func_list);
+       obj->dynamic = true;
+
+       return obj;
+}
+
+static void klp_free_func_nop(struct klp_func *func)
+{
+       kfree(func->old_name);
+       kfree(func);
+}
+
+static struct klp_func *klp_alloc_func_nop(struct klp_func *old_func,
+                                          struct klp_object *obj)
+{
+       struct klp_func *func;
+
+       func = kzalloc(sizeof(*func), GFP_KERNEL);
+       if (!func)
+               return NULL;
+
+       if (old_func->old_name) {
+               func->old_name = kstrdup(old_func->old_name, GFP_KERNEL);
+               if (!func->old_name) {
+                       kfree(func);
+                       return NULL;
+               }
+       }
+
+       /*
+        * func->new_func is same as func->old_func. These addresses are
+        * set when the object is loaded, see klp_init_object_loaded().
+        */
+       func->old_sympos = old_func->old_sympos;
+       func->nop = true;
+
+       return func;
+}
+
+static int klp_add_object_nops(struct klp_patch *patch,
+                              struct klp_object *old_obj)
+{
+       struct klp_object *obj;
+       struct klp_func *func, *old_func;
+
+       obj = klp_find_object(patch, old_obj);
+
+       if (!obj) {
+               obj = klp_alloc_object_dynamic(old_obj->name);
+               if (!obj)
+                       return -ENOMEM;
+
+               list_add_tail(&obj->node, &patch->obj_list);
+       }
+
+       klp_for_each_func(old_obj, old_func) {
+               func = klp_find_func(obj, old_func);
+               if (func)
+                       continue;
+
+               func = klp_alloc_func_nop(old_func, obj);
+               if (!func)
+                       return -ENOMEM;
+
+               list_add_tail(&func->node, &obj->func_list);
+       }
+
+       return 0;
+}
+
+/*
+ * Add 'nop' functions which simply return to the caller to run
+ * the original function. The 'nop' functions are added to a
+ * patch to facilitate a 'replace' mode.
+ */
+static int klp_add_nops(struct klp_patch *patch)
+{
+       struct klp_patch *old_patch;
+       struct klp_object *old_obj;
+
+       klp_for_each_patch(old_patch) {
+               klp_for_each_object(old_patch, old_obj) {
+                       int err;
+
+                       err = klp_add_object_nops(patch, old_obj);
+                       if (err)
+                               return err;
+               }
+       }
+
+       return 0;
+}
+
 static void klp_kobj_release_patch(struct kobject *kobj)
 {
        struct klp_patch *patch;
@@ -449,6 +551,12 @@ static struct kobj_type klp_ktype_patch = {
 
 static void klp_kobj_release_object(struct kobject *kobj)
 {
+       struct klp_object *obj;
+
+       obj = container_of(kobj, struct klp_object, kobj);
+
+       if (obj->dynamic)
+               klp_free_object_dynamic(obj);
 }
 
 static struct kobj_type klp_ktype_object = {
@@ -458,6 +566,12 @@ static struct kobj_type klp_ktype_object = {
 
 static void klp_kobj_release_func(struct kobject *kobj)
 {
+       struct klp_func *func;
+
+       func = container_of(kobj, struct klp_func, kobj);
+
+       if (func->nop)
+               klp_free_func_nop(func);
 }
 
 static struct kobj_type klp_ktype_func = {
@@ -465,14 +579,22 @@ static struct kobj_type klp_ktype_func = {
        .sysfs_ops = &kobj_sysfs_ops,
 };
 
-static void klp_free_funcs(struct klp_object *obj)
+static void __klp_free_funcs(struct klp_object *obj, bool nops_only)
 {
-       struct klp_func *func;
+       struct klp_func *func, *tmp_func;
+
+       klp_for_each_func_safe(obj, func, tmp_func) {
+               if (nops_only && !func->nop)
+                       continue;
+
+               list_del(&func->node);
 
-       klp_for_each_func(obj, func) {
                /* Might be called from klp_init_patch() error path. */
-               if (func->kobj_added)
+               if (func->kobj_added) {
                        kobject_put(&func->kobj);
+               } else if (func->nop) {
+                       klp_free_func_nop(func);
+               }
        }
 }
 
@@ -483,23 +605,45 @@ static void klp_free_object_loaded(struct klp_object *obj)
 
        obj->mod = NULL;
 
-       klp_for_each_func(obj, func)
+       klp_for_each_func(obj, func) {
                func->old_func = NULL;
+
+               if (func->nop)
+                       func->new_func = NULL;
+       }
 }
 
-static void klp_free_objects(struct klp_patch *patch)
+static void __klp_free_objects(struct klp_patch *patch, bool nops_only)
 {
-       struct klp_object *obj;
+       struct klp_object *obj, *tmp_obj;
 
-       klp_for_each_object(patch, obj) {
-               klp_free_funcs(obj);
+       klp_for_each_object_safe(patch, obj, tmp_obj) {
+               __klp_free_funcs(obj, nops_only);
+
+               if (nops_only && !obj->dynamic)
+                       continue;
+
+               list_del(&obj->node);
 
                /* Might be called from klp_init_patch() error path. */
-               if (obj->kobj_added)
+               if (obj->kobj_added) {
                        kobject_put(&obj->kobj);
+               } else if (obj->dynamic) {
+                       klp_free_object_dynamic(obj);
+               }
        }
 }
 
+static void klp_free_objects(struct klp_patch *patch)
+{
+       __klp_free_objects(patch, false);
+}
+
+static void klp_free_objects_dynamic(struct klp_patch *patch)
+{
+       __klp_free_objects(patch, true);
+}
+
 /*
  * This function implements the free operations that can be called safely
  * under klp_mutex.
@@ -507,7 +651,7 @@ static void klp_free_objects(struct klp_patch *patch)
  * The operation must be completed by calling klp_free_patch_finish()
  * outside klp_mutex.
  */
-static void klp_free_patch_start(struct klp_patch *patch)
+void klp_free_patch_start(struct klp_patch *patch)
 {
        if (!list_empty(&patch->list))
                list_del(&patch->list);
@@ -535,13 +679,37 @@ static void klp_free_patch_finish(struct klp_patch *patch)
                kobject_put(&patch->kobj);
                wait_for_completion(&patch->finish);
        }
+
+       /* Put the module after the last access to struct klp_patch. */
+       if (!patch->forced)
+               module_put(patch->mod);
+}
+
+/*
+ * The livepatch might be freed from sysfs interface created by the patch.
+ * This work allows to wait until the interface is destroyed in a separate
+ * context.
+ */
+static void klp_free_patch_work_fn(struct work_struct *work)
+{
+       struct klp_patch *patch =
+               container_of(work, struct klp_patch, free_work);
+
+       klp_free_patch_finish(patch);
 }
 
 static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 {
        int ret;
 
-       if (!func->old_name || !func->new_func)
+       if (!func->old_name)
+               return -EINVAL;
+
+       /*
+        * NOPs get the address later. The patched module must be loaded,
+        * see klp_init_object_loaded().
+        */
+       if (!func->new_func && !func->nop)
                return -EINVAL;
 
        if (strlen(func->old_name) >= KSYM_NAME_LEN)
@@ -603,6 +771,9 @@ static int klp_init_object_loaded(struct klp_patch *patch,
                        return -ENOENT;
                }
 
+               if (func->nop)
+                       func->new_func = func->old_func;
+
                ret = kallsyms_lookup_size_offset((unsigned long)func->new_func,
                                                  &func->new_size, NULL);
                if (!ret) {
@@ -657,20 +828,30 @@ static int klp_init_patch_early(struct klp_patch *patch)
                return -EINVAL;
 
        INIT_LIST_HEAD(&patch->list);
+       INIT_LIST_HEAD(&patch->obj_list);
        patch->kobj_added = false;
        patch->enabled = false;
+       patch->forced = false;
+       INIT_WORK(&patch->free_work, klp_free_patch_work_fn);
        init_completion(&patch->finish);
 
-       klp_for_each_object(patch, obj) {
+       klp_for_each_object_static(patch, obj) {
                if (!obj->funcs)
                        return -EINVAL;
 
+               INIT_LIST_HEAD(&obj->func_list);
                obj->kobj_added = false;
+               list_add_tail(&obj->node, &patch->obj_list);
 
-               klp_for_each_func(obj, func)
+               klp_for_each_func_static(obj, func) {
                        func->kobj_added = false;
+                       list_add_tail(&func->node, &obj->func_list);
+               }
        }
 
+       if (!try_module_get(patch->mod))
+               return -ENODEV;
+
        return 0;
 }
 
@@ -679,116 +860,29 @@ static int klp_init_patch(struct klp_patch *patch)
        struct klp_object *obj;
        int ret;
 
-       mutex_lock(&klp_mutex);
-
-       ret = klp_init_patch_early(patch);
-       if (ret) {
-               mutex_unlock(&klp_mutex);
-               return ret;
-       }
-
        ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch,
                                   klp_root_kobj, "%s", patch->mod->name);
-       if (ret) {
-               mutex_unlock(&klp_mutex);
+       if (ret)
                return ret;
-       }
        patch->kobj_added = true;
 
+       if (patch->replace) {
+               ret = klp_add_nops(patch);
+               if (ret)
+                       return ret;
+       }
+
        klp_for_each_object(patch, obj) {
                ret = klp_init_object(patch, obj);
                if (ret)
-                       goto free;
+                       return ret;
        }
 
        list_add_tail(&patch->list, &klp_patches);
 
-       mutex_unlock(&klp_mutex);
-
        return 0;
-
-free:
-       klp_free_patch_start(patch);
-
-       mutex_unlock(&klp_mutex);
-
-       klp_free_patch_finish(patch);
-
-       return ret;
 }
 
-/**
- * klp_unregister_patch() - unregisters a patch
- * @patch:     Disabled patch to be unregistered
- *
- * Frees the data structures and removes the sysfs interface.
- *
- * Return: 0 on success, otherwise error
- */
-int klp_unregister_patch(struct klp_patch *patch)
-{
-       int ret;
-
-       mutex_lock(&klp_mutex);
-
-       if (!klp_is_patch_registered(patch)) {
-               ret = -EINVAL;
-               goto err;
-       }
-
-       if (patch->enabled) {
-               ret = -EBUSY;
-               goto err;
-       }
-
-       klp_free_patch_start(patch);
-
-       mutex_unlock(&klp_mutex);
-
-       klp_free_patch_finish(patch);
-
-       return 0;
-err:
-       mutex_unlock(&klp_mutex);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(klp_unregister_patch);
-
-/**
- * klp_register_patch() - registers a patch
- * @patch:     Patch to be registered
- *
- * Initializes the data structure associated with the patch and
- * creates the sysfs interface.
- *
- * There is no need to take the reference on the patch module here. It is done
- * later when the patch is enabled.
- *
- * Return: 0 on success, otherwise error
- */
-int klp_register_patch(struct klp_patch *patch)
-{
-       if (!patch || !patch->mod)
-               return -EINVAL;
-
-       if (!is_livepatch_module(patch->mod)) {
-               pr_err("module %s is not marked as a livepatch module\n",
-                      patch->mod->name);
-               return -EINVAL;
-       }
-
-       if (!klp_initialized())
-               return -ENODEV;
-
-       if (!klp_have_reliable_stack()) {
-               pr_err("This architecture doesn't have support for the livepatch consistency model.\n");
-               return -ENOSYS;
-       }
-
-       return klp_init_patch(patch);
-}
-EXPORT_SYMBOL_GPL(klp_register_patch);
-
 static int __klp_disable_patch(struct klp_patch *patch)
 {
        struct klp_object *obj;
@@ -799,11 +893,6 @@ static int __klp_disable_patch(struct klp_patch *patch)
        if (klp_transition_patch)
                return -EBUSY;
 
-       /* enforce stacking: only the last enabled patch can be disabled */
-       if (!list_is_last(&patch->list, &klp_patches) &&
-           list_next_entry(patch, list)->enabled)
-               return -EBUSY;
-
        klp_init_transition(patch, KLP_UNPATCHED);
 
        klp_for_each_object(patch, obj)
@@ -820,44 +909,12 @@ static int __klp_disable_patch(struct klp_patch *patch)
        smp_wmb();
 
        klp_start_transition();
-       klp_try_complete_transition();
        patch->enabled = false;
+       klp_try_complete_transition();
 
        return 0;
 }
 
-/**
- * klp_disable_patch() - disables a registered patch
- * @patch:     The registered, enabled patch to be disabled
- *
- * Unregisters the patched functions from ftrace.
- *
- * Return: 0 on success, otherwise error
- */
-int klp_disable_patch(struct klp_patch *patch)
-{
-       int ret;
-
-       mutex_lock(&klp_mutex);
-
-       if (!klp_is_patch_registered(patch)) {
-               ret = -EINVAL;
-               goto err;
-       }
-
-       if (!patch->enabled) {
-               ret = -EINVAL;
-               goto err;
-       }
-
-       ret = __klp_disable_patch(patch);
-
-err:
-       mutex_unlock(&klp_mutex);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(klp_disable_patch);
-
 static int __klp_enable_patch(struct klp_patch *patch)
 {
        struct klp_object *obj;
@@ -869,17 +926,8 @@ static int __klp_enable_patch(struct klp_patch *patch)
        if (WARN_ON(patch->enabled))
                return -EINVAL;
 
-       /* enforce stacking: only the first disabled patch can be enabled */
-       if (patch->list.prev != &klp_patches &&
-           !list_prev_entry(patch, list)->enabled)
-               return -EBUSY;
-
-       /*
-        * A reference is taken on the patch module to prevent it from being
-        * unloaded.
-        */
-       if (!try_module_get(patch->mod))
-               return -ENODEV;
+       if (!patch->kobj_added)
+               return -EINVAL;
 
        pr_notice("enabling patch '%s'\n", patch->mod->name);
 
@@ -914,8 +962,8 @@ static int __klp_enable_patch(struct klp_patch *patch)
        }
 
        klp_start_transition();
-       klp_try_complete_transition();
        patch->enabled = true;
+       klp_try_complete_transition();
 
        return 0;
 err:
@@ -926,11 +974,15 @@ err:
 }
 
 /**
- * klp_enable_patch() - enables a registered patch
- * @patch:     The registered, disabled patch to be enabled
+ * klp_enable_patch() - enable the livepatch
+ * @patch:     patch to be enabled
+ *
+ * Initializes the data structure associated with the patch, creates the sysfs
+ * interface, performs the needed symbol lookups and code relocations,
+ * registers the patched functions with ftrace.
  *
- * Performs the needed symbol lookups and code relocations,
- * then registers the patched functions with ftrace.
+ * This function is supposed to be called from the livepatch module_init()
+ * callback.
  *
  * Return: 0 on success, otherwise error
  */
@@ -938,21 +990,105 @@ int klp_enable_patch(struct klp_patch *patch)
 {
        int ret;
 
+       if (!patch || !patch->mod)
+               return -EINVAL;
+
+       if (!is_livepatch_module(patch->mod)) {
+               pr_err("module %s is not marked as a livepatch module\n",
+                      patch->mod->name);
+               return -EINVAL;
+       }
+
+       if (!klp_initialized())
+               return -ENODEV;
+
+       if (!klp_have_reliable_stack()) {
+               pr_warn("This architecture doesn't have support for the livepatch consistency model.\n");
+               pr_warn("The livepatch transition may never complete.\n");
+       }
+
        mutex_lock(&klp_mutex);
 
-       if (!klp_is_patch_registered(patch)) {
-               ret = -EINVAL;
-               goto err;
+       ret = klp_init_patch_early(patch);
+       if (ret) {
+               mutex_unlock(&klp_mutex);
+               return ret;
        }
 
+       ret = klp_init_patch(patch);
+       if (ret)
+               goto err;
+
        ret = __klp_enable_patch(patch);
+       if (ret)
+               goto err;
+
+       mutex_unlock(&klp_mutex);
+
+       return 0;
 
 err:
+       klp_free_patch_start(patch);
+
        mutex_unlock(&klp_mutex);
+
+       klp_free_patch_finish(patch);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(klp_enable_patch);
 
+/*
+ * This function removes replaced patches.
+ *
+ * We could be pretty aggressive here. It is called in the situation where
+ * these structures are no longer accessible. All functions are redirected
+ * by the klp_transition_patch. They use either a new code or they are in
+ * the original code because of the special nop function patches.
+ *
+ * The only exception is when the transition was forced. In this case,
+ * klp_ftrace_handler() might still see the replaced patch on the stack.
+ * Fortunately, it is carefully designed to work with removed functions
+ * thanks to RCU. We only have to keep the patches on the system. Also
+ * this is handled transparently by patch->module_put.
+ */
+void klp_discard_replaced_patches(struct klp_patch *new_patch)
+{
+       struct klp_patch *old_patch, *tmp_patch;
+
+       klp_for_each_patch_safe(old_patch, tmp_patch) {
+               if (old_patch == new_patch)
+                       return;
+
+               old_patch->enabled = false;
+               klp_unpatch_objects(old_patch);
+               klp_free_patch_start(old_patch);
+               schedule_work(&old_patch->free_work);
+       }
+}
+
+/*
+ * This function removes the dynamically allocated 'nop' functions.
+ *
+ * We could be pretty aggressive. NOPs do not change the existing
+ * behavior except for adding unnecessary delay by the ftrace handler.
+ *
+ * It is safe even when the transition was forced. The ftrace handler
+ * will see a valid ops->func_stack entry thanks to RCU.
+ *
+ * We could even free the NOPs structures. They must be the last entry
+ * in ops->func_stack. Therefore unregister_ftrace_function() is called.
+ * It does the same as klp_synchronize_transition() to make sure that
+ * nobody is inside the ftrace handler once the operation finishes.
+ *
+ * IMPORTANT: It must be called right after removing the replaced patches!
+ */
+void klp_discard_nops(struct klp_patch *new_patch)
+{
+       klp_unpatch_objects_dynamic(klp_transition_patch);
+       klp_free_objects_dynamic(klp_transition_patch);
+}
+
 /*
  * Remove parts of patches that touch a given kernel module. The list of
  * patches processed might be limited. When limit is NULL, all patches
@@ -964,7 +1100,7 @@ static void klp_cleanup_module_patches_limited(struct module *mod,
        struct klp_patch *patch;
        struct klp_object *obj;
 
-       list_for_each_entry(patch, &klp_patches, list) {
+       klp_for_each_patch(patch) {
                if (patch == limit)
                        break;
 
@@ -972,21 +1108,14 @@ static void klp_cleanup_module_patches_limited(struct module *mod,
                        if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
                                continue;
 
-                       /*
-                        * Only unpatch the module if the patch is enabled or
-                        * is in transition.
-                        */
-                       if (patch->enabled || patch == klp_transition_patch) {
-
-                               if (patch != klp_transition_patch)
-                                       klp_pre_unpatch_callback(obj);
+                       if (patch != klp_transition_patch)
+                               klp_pre_unpatch_callback(obj);
 
-                               pr_notice("reverting patch '%s' on unloading module '%s'\n",
-                                         patch->mod->name, obj->mod->name);
-                               klp_unpatch_object(obj);
+                       pr_notice("reverting patch '%s' on unloading module '%s'\n",
+                                 patch->mod->name, obj->mod->name);
+                       klp_unpatch_object(obj);
 
-                               klp_post_unpatch_callback(obj);
-                       }
+                       klp_post_unpatch_callback(obj);
 
                        klp_free_object_loaded(obj);
                        break;
@@ -1011,7 +1140,7 @@ int klp_module_coming(struct module *mod)
         */
        mod->klp_alive = true;
 
-       list_for_each_entry(patch, &klp_patches, list) {
+       klp_for_each_patch(patch) {
                klp_for_each_object(patch, obj) {
                        if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
                                continue;
@@ -1025,13 +1154,6 @@ int klp_module_coming(struct module *mod)
                                goto err;
                        }
 
-                       /*
-                        * Only patch the module if the patch is enabled or is
-                        * in transition.
-                        */
-                       if (!patch->enabled && patch != klp_transition_patch)
-                               break;
-
                        pr_notice("applying patch '%s' to loading module '%s'\n",
                                  patch->mod->name, obj->mod->name);