diff options
Diffstat (limited to 'kernel/kprobes.c')
| -rw-r--r-- | kernel/kprobes.c | 39 | 
1 files changed, 27 insertions, 12 deletions
| diff --git a/kernel/kprobes.c b/kernel/kprobes.c index ab257be4d924..90e98e233647 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -546,8 +546,14 @@ static void do_free_cleaned_kprobes(void)  	struct optimized_kprobe *op, *tmp;  	list_for_each_entry_safe(op, tmp, &freeing_list, list) { -		BUG_ON(!kprobe_unused(&op->kp));  		list_del_init(&op->list); +		if (WARN_ON_ONCE(!kprobe_unused(&op->kp))) { +			/* +			 * This must not happen, but if there is a kprobe +			 * still in use, keep it on kprobes hash list. +			 */ +			continue; +		}  		free_aggr_kprobe(&op->kp);  	}  } @@ -700,11 +706,11 @@ static void unoptimize_kprobe(struct kprobe *p, bool force)  }  /* Cancel unoptimizing for reusing */ -static void reuse_unused_kprobe(struct kprobe *ap) +static int reuse_unused_kprobe(struct kprobe *ap)  {  	struct optimized_kprobe *op; +	int ret; -	BUG_ON(!kprobe_unused(ap));  	/*  	 * Unused kprobe MUST be on the way of delayed unoptimizing (means  	 * there is still a relative jump) and disabled. @@ -714,8 +720,12 @@ static void reuse_unused_kprobe(struct kprobe *ap)  	/* Enable the probe again */  	ap->flags &= ~KPROBE_FLAG_DISABLED;  	/* Optimize it again (remove from op->list) */ -	BUG_ON(!kprobe_optready(ap)); +	ret = kprobe_optready(ap); +	if (ret) +		return ret; +  	optimize_kprobe(ap); +	return 0;  }  /* Remove optimized instructions */ @@ -940,11 +950,16 @@ static void __disarm_kprobe(struct kprobe *p, bool reopt)  #define kprobe_disarmed(p)			kprobe_disabled(p)  #define wait_for_kprobe_optimizer()		do {} while (0) -/* There should be no unused kprobes can be reused without optimization */ -static void reuse_unused_kprobe(struct kprobe *ap) +static int reuse_unused_kprobe(struct kprobe *ap)  { +	/* +	 * If the optimized kprobe is NOT supported, the aggr kprobe is +	 * released at the same time that the last aggregated kprobe is +	 * unregistered. +	 * Thus there should be no chance to reuse unused kprobe. +	 */  	printk(KERN_ERR "Error: There should be no unused kprobe here.\n"); -	BUG_ON(kprobe_unused(ap)); +	return -EINVAL;  }  static void free_aggr_kprobe(struct kprobe *p) @@ -1259,8 +1274,6 @@ NOKPROBE_SYMBOL(cleanup_rp_inst);  /* Add the new probe to ap->list */  static int add_new_kprobe(struct kprobe *ap, struct kprobe *p)  { -	BUG_ON(kprobe_gone(ap) || kprobe_gone(p)); -  	if (p->post_handler)  		unoptimize_kprobe(ap, true);	/* Fall back to normal kprobe */ @@ -1318,9 +1331,12 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)  			goto out;  		}  		init_aggr_kprobe(ap, orig_p); -	} else if (kprobe_unused(ap)) +	} else if (kprobe_unused(ap)) {  		/* This probe is going to die. Rescue it */ -		reuse_unused_kprobe(ap); +		ret = reuse_unused_kprobe(ap); +		if (ret) +			goto out; +	}  	if (kprobe_gone(ap)) {  		/* @@ -1704,7 +1720,6 @@ noclean:  	return 0;  disarmed: -	BUG_ON(!kprobe_disarmed(ap));  	hlist_del_rcu(&ap->hlist);  	return 0;  } |