1404 lines · 35.3 KB · C
RawDownload
		limit++;		WARN(1, KERN_ERR "ODEBUG: %s %s (active state %u) "				 "object type: %s hint: %pS\n",			msg, obj_states[obj->state], obj->astate,			descr->name, hint);	}	debug_objects_warnings++;} /* * Try to repair the damage, so we have a better chance to get useful * debug output. */static booldebug_object_fixup(bool (*fixup)(void *addr, enum debug_obj_state state),		   void * addr, enum debug_obj_state state){	if (fixup && fixup(addr, state)) {		debug_objects_fixups++;		return true;	}	return false;} static void debug_object_is_on_stack(void *addr, int onstack){	int is_on_stack;	static int limit; 	if (limit > 4)		return; 	is_on_stack = object_is_on_stack(addr);	if (is_on_stack == onstack)		return; 	limit++;	if (is_on_stack)		pr_warn("object %p is on stack %p, but NOT annotated.\n", addr,			 task_stack_page(current));	else		pr_warn("object %p is NOT on stack %p, but annotated.\n", addr,			 task_stack_page(current)); 	WARN_ON(1);} static void__debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack){	enum debug_obj_state state;	bool check_stack = false;	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags; 	/*	 * On RT enabled kernels the pool refill must happen in preemptible	 * context:	 */	if (!IS_ENABLED(CONFIG_PREEMPT_RT) || preemptible())		fill_pool(); 	db = get_bucket((unsigned long) addr); 	raw_spin_lock_irqsave(&db->lock, flags); 	obj = lookup_object(addr, db);	if (!obj) {		obj = alloc_object(addr, db, descr);		if (!obj) {			debug_objects_enabled = 0;			raw_spin_unlock_irqrestore(&db->lock, flags);			debug_objects_oom();			return;		}		check_stack = true;	} 	switch (obj->state) {	case ODEBUG_STATE_NONE:	case ODEBUG_STATE_INIT:	case ODEBUG_STATE_INACTIVE:		obj->state = ODEBUG_STATE_INIT;		break; 	case ODEBUG_STATE_ACTIVE:		state = obj->state;		raw_spin_unlock_irqrestore(&db->lock, flags);		debug_print_object(obj, "init");		debug_object_fixup(descr->fixup_init, addr, state);		return; 	case ODEBUG_STATE_DESTROYED:		raw_spin_unlock_irqrestore(&db->lock, flags);		debug_print_object(obj, "init");		return;	default:		break;	} 	raw_spin_unlock_irqrestore(&db->lock, flags);	if (check_stack)		debug_object_is_on_stack(addr, onstack);} /** * debug_object_init - debug checks when an object is initialized * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_init(void *addr, const struct debug_obj_descr *descr){	if (!debug_objects_enabled)		return; 	__debug_object_init(addr, descr, 0);}EXPORT_SYMBOL_GPL(debug_object_init); /** * debug_object_init_on_stack - debug checks when an object on stack is *				initialized * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_init_on_stack(void *addr, const struct debug_obj_descr *descr){	if (!debug_objects_enabled)		return; 	__debug_object_init(addr, descr, 1);}EXPORT_SYMBOL_GPL(debug_object_init_on_stack); /** * debug_object_activate - debug checks when an object is activated * @addr:	address of the object * @descr:	pointer to an object specific debug description structure * Returns 0 for success, -EINVAL for check failed. */int debug_object_activate(void *addr, const struct debug_obj_descr *descr){	enum debug_obj_state state;	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags;	int ret;	struct debug_obj o = { .object = addr,			       .state = ODEBUG_STATE_NOTAVAILABLE,			       .descr = descr }; 	if (!debug_objects_enabled)		return 0; 	db = get_bucket((unsigned long) addr); 	raw_spin_lock_irqsave(&db->lock, flags); 	obj = lookup_object(addr, db);	if (obj) {		bool print_object = false; 		switch (obj->state) {		case ODEBUG_STATE_INIT:		case ODEBUG_STATE_INACTIVE:			obj->state = ODEBUG_STATE_ACTIVE;			ret = 0;			break; 		case ODEBUG_STATE_ACTIVE:			state = obj->state;			raw_spin_unlock_irqrestore(&db->lock, flags);			debug_print_object(obj, "activate");			ret = debug_object_fixup(descr->fixup_activate, addr, state);			return ret ? 0 : -EINVAL; 		case ODEBUG_STATE_DESTROYED:			print_object = true;			ret = -EINVAL;			break;		default:			ret = 0;			break;		}		raw_spin_unlock_irqrestore(&db->lock, flags);		if (print_object)			debug_print_object(obj, "activate");		return ret;	} 	raw_spin_unlock_irqrestore(&db->lock, flags); 	/*	 * We are here when a static object is activated. We	 * let the type specific code confirm whether this is	 * true or not. if true, we just make sure that the	 * static object is tracked in the object tracker. If	 * not, this must be a bug, so we try to fix it up.	 */	if (descr->is_static_object && descr->is_static_object(addr)) {		/* track this static object */		debug_object_init(addr, descr);		debug_object_activate(addr, descr);	} else {		debug_print_object(&o, "activate");		ret = debug_object_fixup(descr->fixup_activate, addr,					ODEBUG_STATE_NOTAVAILABLE);		return ret ? 0 : -EINVAL;	}	return 0;}EXPORT_SYMBOL_GPL(debug_object_activate); /** * debug_object_deactivate - debug checks when an object is deactivated * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_deactivate(void *addr, const struct debug_obj_descr *descr){	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags;	bool print_object = false; 	if (!debug_objects_enabled)		return; 	db = get_bucket((unsigned long) addr); 	raw_spin_lock_irqsave(&db->lock, flags); 	obj = lookup_object(addr, db);	if (obj) {		switch (obj->state) {		case ODEBUG_STATE_INIT:		case ODEBUG_STATE_INACTIVE:		case ODEBUG_STATE_ACTIVE:			if (!obj->astate)				obj->state = ODEBUG_STATE_INACTIVE;			else				print_object = true;			break; 		case ODEBUG_STATE_DESTROYED:			print_object = true;			break;		default:			break;		}	} 	raw_spin_unlock_irqrestore(&db->lock, flags);	if (!obj) {		struct debug_obj o = { .object = addr,				       .state = ODEBUG_STATE_NOTAVAILABLE,				       .descr = descr }; 		debug_print_object(&o, "deactivate");	} else if (print_object) {		debug_print_object(obj, "deactivate");	}}EXPORT_SYMBOL_GPL(debug_object_deactivate); /** * debug_object_destroy - debug checks when an object is destroyed * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_destroy(void *addr, const struct debug_obj_descr *descr){	enum debug_obj_state state;	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags;	bool print_object = false; 	if (!debug_objects_enabled)		return; 	db = get_bucket((unsigned long) addr); 	raw_spin_lock_irqsave(&db->lock, flags); 	obj = lookup_object(addr, db);	if (!obj)		goto out_unlock; 	switch (obj->state) {	case ODEBUG_STATE_NONE:	case ODEBUG_STATE_INIT:	case ODEBUG_STATE_INACTIVE:		obj->state = ODEBUG_STATE_DESTROYED;		break;	case ODEBUG_STATE_ACTIVE:		state = obj->state;		raw_spin_unlock_irqrestore(&db->lock, flags);		debug_print_object(obj, "destroy");		debug_object_fixup(descr->fixup_destroy, addr, state);		return; 	case ODEBUG_STATE_DESTROYED:		print_object = true;		break;	default:		break;	}out_unlock:	raw_spin_unlock_irqrestore(&db->lock, flags);	if (print_object)		debug_print_object(obj, "destroy");}EXPORT_SYMBOL_GPL(debug_object_destroy); /** * debug_object_free - debug checks when an object is freed * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_free(void *addr, const struct debug_obj_descr *descr){	enum debug_obj_state state;	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags; 	if (!debug_objects_enabled)		return; 	db = get_bucket((unsigned long) addr); 	raw_spin_lock_irqsave(&db->lock, flags); 	obj = lookup_object(addr, db);	if (!obj)		goto out_unlock; 	switch (obj->state) {	case ODEBUG_STATE_ACTIVE:		state = obj->state;		raw_spin_unlock_irqrestore(&db->lock, flags);		debug_print_object(obj, "free");		debug_object_fixup(descr->fixup_free, addr, state);		return;	default:		hlist_del(&obj->node);		raw_spin_unlock_irqrestore(&db->lock, flags);		free_object(obj);		return;	}out_unlock:	raw_spin_unlock_irqrestore(&db->lock, flags);}EXPORT_SYMBOL_GPL(debug_object_free); /** * debug_object_assert_init - debug checks when object should be init-ed * @addr:	address of the object * @descr:	pointer to an object specific debug description structure */void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr){	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags; 	if (!debug_objects_enabled)		return; 	db = get_bucket((unsigned long) addr); 	raw_spin_lock_irqsave(&db->lock, flags); 	obj = lookup_object(addr, db);	if (!obj) {		struct debug_obj o = { .object = addr,				       .state = ODEBUG_STATE_NOTAVAILABLE,				       .descr = descr }; 		raw_spin_unlock_irqrestore(&db->lock, flags);		/*		 * Maybe the object is static, and we let the type specific		 * code confirm. Track this static object if true, else invoke		 * fixup.		 */		if (descr->is_static_object && descr->is_static_object(addr)) {			/* Track this static object */			debug_object_init(addr, descr);		} else {			debug_print_object(&o, "assert_init");			debug_object_fixup(descr->fixup_assert_init, addr,					   ODEBUG_STATE_NOTAVAILABLE);		}		return;	} 	raw_spin_unlock_irqrestore(&db->lock, flags);}EXPORT_SYMBOL_GPL(debug_object_assert_init); /** * debug_object_active_state - debug checks object usage state machine * @addr:	address of the object * @descr:	pointer to an object specific debug description structure * @expect:	expected state * @next:	state to move to if expected state is found */voiddebug_object_active_state(void *addr, const struct debug_obj_descr *descr,			  unsigned int expect, unsigned int next){	struct debug_bucket *db;	struct debug_obj *obj;	unsigned long flags;	bool print_object = false; 	if (!debug_objects_enabled)		return; 	db = get_bucket((unsigned long) addr); 	raw_spin_lock_irqsave(&db->lock, flags); 	obj = lookup_object(addr, db);	if (obj) {		switch (obj->state) {		case ODEBUG_STATE_ACTIVE:			if (obj->astate == expect)				obj->astate = next;			else				print_object = true;			break; 		default:			print_object = true;			break;		}	} 	raw_spin_unlock_irqrestore(&db->lock, flags);	if (!obj) {		struct debug_obj o = { .object = addr,				       .state = ODEBUG_STATE_NOTAVAILABLE,				       .descr = descr }; 		debug_print_object(&o, "active_state");	} else if (print_object) {		debug_print_object(obj, "active_state");	}}EXPORT_SYMBOL_GPL(debug_object_active_state); #ifdef CONFIG_DEBUG_OBJECTS_FREEstatic void __debug_check_no_obj_freed(const void *address, unsigned long size){	unsigned long flags, oaddr, saddr, eaddr, paddr, chunks;	const struct debug_obj_descr *descr;	enum debug_obj_state state;	struct debug_bucket *db;	struct hlist_node *tmp;	struct debug_obj *obj;	int cnt, objs_checked = 0; 	saddr = (unsigned long) address;	eaddr = saddr + size;	paddr = saddr & ODEBUG_CHUNK_MASK;	chunks = ((eaddr - paddr) + (ODEBUG_CHUNK_SIZE - 1));	chunks >>= ODEBUG_CHUNK_SHIFT; 	for (;chunks > 0; chunks--, paddr += ODEBUG_CHUNK_SIZE) {		db = get_bucket(paddr); repeat:		cnt = 0;		raw_spin_lock_irqsave(&db->lock, flags);		hlist_for_each_entry_safe(obj, tmp, &db->list, node) {			cnt++;			oaddr = (unsigned long) obj->object;			if (oaddr < saddr || oaddr >= eaddr)				continue; 			switch (obj->state) {			case ODEBUG_STATE_ACTIVE:				descr = obj->descr;				state = obj->state;				raw_spin_unlock_irqrestore(&db->lock, flags);				debug_print_object(obj, "free");				debug_object_fixup(descr->fixup_free,						   (void *) oaddr, state);				goto repeat;			default:				hlist_del(&obj->node);				__free_object(obj);				break;			}		}		raw_spin_unlock_irqrestore(&db->lock, flags); 

Lines 501–1000 of 1404. Previous lines