diff options
Diffstat (limited to 'kernel/kprobes.c')
| -rw-r--r-- | kernel/kprobes.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 7c44133f51ec..9737a76e106f 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -1145,14 +1145,13 @@ int __kprobes register_kprobe(struct kprobe *p) | |||
| 1145 | if (ret) | 1145 | if (ret) |
| 1146 | return ret; | 1146 | return ret; |
| 1147 | 1147 | ||
| 1148 | jump_label_lock(); | ||
| 1148 | preempt_disable(); | 1149 | preempt_disable(); |
| 1149 | if (!kernel_text_address((unsigned long) p->addr) || | 1150 | if (!kernel_text_address((unsigned long) p->addr) || |
| 1150 | in_kprobes_functions((unsigned long) p->addr) || | 1151 | in_kprobes_functions((unsigned long) p->addr) || |
| 1151 | ftrace_text_reserved(p->addr, p->addr) || | 1152 | ftrace_text_reserved(p->addr, p->addr) || |
| 1152 | jump_label_text_reserved(p->addr, p->addr)) { | 1153 | jump_label_text_reserved(p->addr, p->addr)) |
| 1153 | preempt_enable(); | 1154 | goto fail_with_jump_label; |
| 1154 | return -EINVAL; | ||
| 1155 | } | ||
| 1156 | 1155 | ||
| 1157 | /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ | 1156 | /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ |
| 1158 | p->flags &= KPROBE_FLAG_DISABLED; | 1157 | p->flags &= KPROBE_FLAG_DISABLED; |
| @@ -1166,10 +1165,9 @@ int __kprobes register_kprobe(struct kprobe *p) | |||
| 1166 | * We must hold a refcount of the probed module while updating | 1165 | * We must hold a refcount of the probed module while updating |
| 1167 | * its code to prohibit unexpected unloading. | 1166 | * its code to prohibit unexpected unloading. |
| 1168 | */ | 1167 | */ |
| 1169 | if (unlikely(!try_module_get(probed_mod))) { | 1168 | if (unlikely(!try_module_get(probed_mod))) |
| 1170 | preempt_enable(); | 1169 | goto fail_with_jump_label; |
| 1171 | return -EINVAL; | 1170 | |
| 1172 | } | ||
| 1173 | /* | 1171 | /* |
| 1174 | * If the module freed .init.text, we couldn't insert | 1172 | * If the module freed .init.text, we couldn't insert |
| 1175 | * kprobes in there. | 1173 | * kprobes in there. |
| @@ -1177,16 +1175,18 @@ int __kprobes register_kprobe(struct kprobe *p) | |||
| 1177 | if (within_module_init((unsigned long)p->addr, probed_mod) && | 1175 | if (within_module_init((unsigned long)p->addr, probed_mod) && |
| 1178 | probed_mod->state != MODULE_STATE_COMING) { | 1176 | probed_mod->state != MODULE_STATE_COMING) { |
| 1179 | module_put(probed_mod); | 1177 | module_put(probed_mod); |
| 1180 | preempt_enable(); | 1178 | goto fail_with_jump_label; |
| 1181 | return -EINVAL; | ||
| 1182 | } | 1179 | } |
| 1183 | } | 1180 | } |
| 1184 | preempt_enable(); | 1181 | preempt_enable(); |
| 1182 | jump_label_unlock(); | ||
| 1185 | 1183 | ||
| 1186 | p->nmissed = 0; | 1184 | p->nmissed = 0; |
| 1187 | INIT_LIST_HEAD(&p->list); | 1185 | INIT_LIST_HEAD(&p->list); |
| 1188 | mutex_lock(&kprobe_mutex); | 1186 | mutex_lock(&kprobe_mutex); |
| 1189 | 1187 | ||
| 1188 | jump_label_lock(); /* needed to call jump_label_text_reserved() */ | ||
| 1189 | |||
| 1190 | get_online_cpus(); /* For avoiding text_mutex deadlock. */ | 1190 | get_online_cpus(); /* For avoiding text_mutex deadlock. */ |
| 1191 | mutex_lock(&text_mutex); | 1191 | mutex_lock(&text_mutex); |
| 1192 | 1192 | ||
| @@ -1214,12 +1214,18 @@ int __kprobes register_kprobe(struct kprobe *p) | |||
| 1214 | out: | 1214 | out: |
| 1215 | mutex_unlock(&text_mutex); | 1215 | mutex_unlock(&text_mutex); |
| 1216 | put_online_cpus(); | 1216 | put_online_cpus(); |
| 1217 | jump_label_unlock(); | ||
| 1217 | mutex_unlock(&kprobe_mutex); | 1218 | mutex_unlock(&kprobe_mutex); |
| 1218 | 1219 | ||
| 1219 | if (probed_mod) | 1220 | if (probed_mod) |
| 1220 | module_put(probed_mod); | 1221 | module_put(probed_mod); |
| 1221 | 1222 | ||
| 1222 | return ret; | 1223 | return ret; |
| 1224 | |||
| 1225 | fail_with_jump_label: | ||
| 1226 | preempt_enable(); | ||
| 1227 | jump_label_unlock(); | ||
| 1228 | return -EINVAL; | ||
| 1223 | } | 1229 | } |
| 1224 | EXPORT_SYMBOL_GPL(register_kprobe); | 1230 | EXPORT_SYMBOL_GPL(register_kprobe); |
| 1225 | 1231 | ||
| @@ -2001,6 +2007,7 @@ static ssize_t write_enabled_file_bool(struct file *file, | |||
| 2001 | static const struct file_operations fops_kp = { | 2007 | static const struct file_operations fops_kp = { |
| 2002 | .read = read_enabled_file_bool, | 2008 | .read = read_enabled_file_bool, |
| 2003 | .write = write_enabled_file_bool, | 2009 | .write = write_enabled_file_bool, |
| 2010 | .llseek = default_llseek, | ||
| 2004 | }; | 2011 | }; |
| 2005 | 2012 | ||
| 2006 | static int __kprobes debugfs_kprobe_init(void) | 2013 | static int __kprobes debugfs_kprobe_init(void) |
