]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branches 'for-4.1/upstream-fixes', 'for-4.2/kaslr' and 'for-4.2/upstream' into...
authorJiri Kosina <jkosina@suse.cz>
Mon, 22 Jun 2015 14:26:56 +0000 (16:26 +0200)
committerJiri Kosina <jkosina@suse.cz>
Mon, 22 Jun 2015 14:26:56 +0000 (16:26 +0200)
1  2  3 
kernel/livepatch/core.c

diff --combined kernel/livepatch/core.c
index 9ec555732f1a9601ce3733bcd232bb15f4d9ce6f,0e7c23c6cf3fd555353f156a2504000f3be4ff90,a0acda468f1a9e9d38be8cc3d577a594b80ba2ae..c40ebcca0495fc5fb003e44c4c6549bc39fcd08d
@@@@ -128,7 -128,7 -128,7 +128,7 @@@@ static bool klp_is_patch_registered(str
   
   static bool klp_initialized(void)
   {
--      return klp_root_kobj;
++      return !!klp_root_kobj;
   }
   
   struct klp_find_arg {
@@@@ -179,9 -179,7 -179,7 +179,9 @@@@ static int klp_find_object_symbol(cons
                .count = 0
        };
   
 ++     mutex_lock(&module_mutex);
        kallsyms_on_each_symbol(klp_find_callback, &args);
 ++     mutex_unlock(&module_mutex);
   
        if (args.count == 0)
                pr_err("symbol '%s' not found in symbol table\n", name);
@@@@ -221,19 -219,13 -219,13 +221,19 @@@@ static int klp_verify_vmlinux_symbol(co
                .name = name,
                .addr = addr,
        };
 ++     int ret;
   
 --     if (kallsyms_on_each_symbol(klp_verify_callback, &args))
 --             return 0;
 ++     mutex_lock(&module_mutex);
 ++     ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
 ++     mutex_unlock(&module_mutex);
   
 --     pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
 --             name, addr);
 --     return -EINVAL;
 ++     if (!ret) {
 ++             pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
 ++                     name, addr);
 ++             return -EINVAL;
 ++     }
 ++
 ++     return 0;
   }
   
   static int klp_find_verify_func_addr(struct klp_object *obj,
        int ret;
   
   #if defined(CONFIG_RANDOMIZE_BASE)
- -     /* KASLR is enabled, disregard old_addr from user */
- -     func->old_addr = 0;
+ +     /* If KASLR has been enabled, adjust old_addr accordingly */
+ +     if (kaslr_enabled() && func->old_addr)
+ +             func->old_addr += kaslr_offset();
   #endif
   
        if (!func->old_addr || klp_is_module(obj))
@@@@ -430,7 -423,7 -422,7 +431,7 @@@@ static void klp_disable_object(struct k
   {
        struct klp_func *func;
   
--      for (func = obj->funcs; func->old_name; func++)
++      klp_for_each_func(obj, func)
                if (func->state == KLP_ENABLED)
                        klp_disable_func(func);
   
@@@@ -448,7 -441,7 -440,7 +449,7 @@@@ static int klp_enable_object(struct klp
        if (WARN_ON(!klp_is_object_loaded(obj)))
                return -EINVAL;
   
--      for (func = obj->funcs; func->old_name; func++) {
++      klp_for_each_func(obj, func) {
                ret = klp_enable_func(func);
                if (ret) {
                        klp_disable_object(obj);
@@@@ -471,7 -464,7 -463,7 +472,7 @@@@ static int __klp_disable_patch(struct k
   
        pr_notice("disabling patch '%s'\n", patch->mod->name);
   
--      for (obj = patch->objs; obj->funcs; obj++) {
++      klp_for_each_object(patch, obj) {
                if (obj->state == KLP_ENABLED)
                        klp_disable_object(obj);
        }
@@@@ -531,7 -524,7 -523,7 +532,7 @@@@ static int __klp_enable_patch(struct kl
   
        pr_notice("enabling patch '%s'\n", patch->mod->name);
   
--      for (obj = patch->objs; obj->funcs; obj++) {
++      klp_for_each_object(patch, obj) {
                if (!klp_is_object_loaded(obj))
                        continue;
   
@@@@ -659,6 -652,6 -651,15 +660,15 @@@@ static struct kobj_type klp_ktype_patc
        .default_attrs = klp_patch_attrs,
   };
   
++ static void klp_kobj_release_object(struct kobject *kobj)
++ {
++ }
++ 
++ static struct kobj_type klp_ktype_object = {
++      .release = klp_kobj_release_object,
++      .sysfs_ops = &kobj_sysfs_ops,
++ };
++ 
   static void klp_kobj_release_func(struct kobject *kobj)
   {
   }
@@@@ -688,7 -681,7 -689,7 +698,7 @@@@ static void klp_free_object_loaded(stru
   
        obj->mod = NULL;
   
--      for (func = obj->funcs; func->old_name; func++)
++      klp_for_each_func(obj, func)
                func->old_addr = 0;
   }
   
@@@@ -703,7 -696,7 -704,7 +713,7 @@@@ static void klp_free_objects_limited(st
   
        for (obj = patch->objs; obj->funcs && obj != limit; obj++) {
                klp_free_funcs_limited(obj, NULL);
--              kobject_put(obj->kobj);
++              kobject_put(&obj->kobj);
        }
   }
   
@@@@ -721,7 -714,7 -722,7 +731,7 @@@@ static int klp_init_func(struct klp_obj
        func->state = KLP_DISABLED;
   
        return kobject_init_and_add(&func->kobj, &klp_ktype_func,
--                                  obj->kobj, "%s", func->old_name);
++                                  &obj->kobj, "%s", func->old_name);
   }
   
   /* parts of the initialization that is done only when the object is loaded */
@@@@ -737,7 -730,7 -738,7 +747,7 @@@@ static int klp_init_object_loaded(struc
                        return ret;
        }
   
--      for (func = obj->funcs; func->old_name; func++) {
++      klp_for_each_func(obj, func) {
                ret = klp_find_verify_func_addr(obj, func);
                if (ret)
                        return ret;
@@@@ -761,11 -754,11 -762,12 +771,12 @@@@ static int klp_init_object(struct klp_p
        klp_find_object_module(obj);
   
        name = klp_is_module(obj) ? obj->name : "vmlinux";
--      obj->kobj = kobject_create_and_add(name, &patch->kobj);
--      if (!obj->kobj)
--              return -ENOMEM;
++      ret = kobject_init_and_add(&obj->kobj, &klp_ktype_object,
++                                 &patch->kobj, "%s", name);
++      if (ret)
++              return ret;
   
--      for (func = obj->funcs; func->old_name; func++) {
++      klp_for_each_func(obj, func) {
                ret = klp_init_func(obj, func);
                if (ret)
                        goto free;
   
   free:
        klp_free_funcs_limited(obj, func);
--      kobject_put(obj->kobj);
++      kobject_put(&obj->kobj);
        return ret;
   }
   
@@@@ -802,7 -795,7 -804,7 +813,7 @@@@ static int klp_init_patch(struct klp_pa
        if (ret)
                goto unlock;
   
--      for (obj = patch->objs; obj->funcs; obj++) {
++      klp_for_each_object(patch, obj) {
                ret = klp_init_object(patch, obj);
                if (ret)
                        goto free;
@@@@ -891,7 -884,7 -893,7 +902,7 @@@@ int klp_register_patch(struct klp_patc
   }
   EXPORT_SYMBOL_GPL(klp_register_patch);
   
-- static void klp_module_notify_coming(struct klp_patch *patch,
++ static int klp_module_notify_coming(struct klp_patch *patch,
                                     struct klp_object *obj)
   {
        struct module *pmod = patch->mod;
        int ret;
   
        ret = klp_init_object_loaded(patch, obj);
--      if (ret)
--              goto err;
++      if (ret) {
++              pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n",
++                      pmod->name, mod->name, ret);
++              return ret;
++      }
   
        if (patch->state == KLP_DISABLED)
--              return;
++              return 0;
   
        pr_notice("applying patch '%s' to loading module '%s'\n",
                  pmod->name, mod->name);
   
        ret = klp_enable_object(obj);
--      if (!ret)
--              return;
-- 
-- err:
--      pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
--              pmod->name, mod->name, ret);
++      if (ret)
++              pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
++                      pmod->name, mod->name, ret);
++      return ret;
   }
   
   static void klp_module_notify_going(struct klp_patch *patch,
@@@@ -938,6 -931,6 -941,7 +950,7 @@@@ disabled
   static int klp_module_notify(struct notifier_block *nb, unsigned long action,
                             void *data)
   {
++      int ret;
        struct module *mod = data;
        struct klp_patch *patch;
        struct klp_object *obj;
                mod->klp_alive = false;
   
        list_for_each_entry(patch, &klp_patches, list) {
--              for (obj = patch->objs; obj->funcs; obj++) {
++              klp_for_each_object(patch, obj) {
                        if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
                                continue;
   
                        if (action == MODULE_STATE_COMING) {
                                obj->mod = mod;
--                              klp_module_notify_coming(patch, obj);
++                              ret = klp_module_notify_coming(patch, obj);
++                              if (ret) {
++                                      obj->mod = NULL;
++                                      pr_warn("patch '%s' is in an inconsistent state!\n",
++                                              patch->mod->name);
++                              }
                        } else /* MODULE_STATE_GOING */
                                klp_module_notify_going(patch, obj);
   
@@@@ -981,7 -974,7 -990,7 +999,7 @@@@ static struct notifier_block klp_module
        .priority = INT_MIN+1, /* called late but before ftrace notifier */
   };
   
-- static int klp_init(void)
++ static int __init klp_init(void)
   {
        int ret;