forked from mirrors/linux
		
	EDAC, mc: Fix locking around mc_devices list
When accessing the mc_devices list of memory controller descriptors, we need to hold mem_ctls_mutex. This was not always the case, fix that. Make all external callers call a version which grabs the mutex since the last is local to edac_mc.c. Reported-by: Yazen Ghannam <yazen.ghannam@amd.com> Signed-off-by: Borislav Petkov <bp@suse.de>
This commit is contained in:
		
							parent
							
								
									90e493d7d5
								
							
						
					
					
						commit
						c73e8833be
					
				
					 1 changed files with 31 additions and 18 deletions
				
			
		|  | @ -482,15 +482,8 @@ void edac_mc_free(struct mem_ctl_info *mci) | |||
| } | ||||
| EXPORT_SYMBOL_GPL(edac_mc_free); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * find_mci_by_dev | ||||
|  * | ||||
|  *	scan list of controllers looking for the one that manages | ||||
|  *	the 'dev' device | ||||
|  * @dev: pointer to a struct device related with the MCI | ||||
|  */ | ||||
| struct mem_ctl_info *find_mci_by_dev(struct device *dev) | ||||
| /* Caller must hold mem_ctls_mutex */ | ||||
| static struct mem_ctl_info *__find_mci_by_dev(struct device *dev) | ||||
| { | ||||
| 	struct mem_ctl_info *mci; | ||||
| 	struct list_head *item; | ||||
|  | @ -506,6 +499,24 @@ struct mem_ctl_info *find_mci_by_dev(struct device *dev) | |||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * find_mci_by_dev | ||||
|  * | ||||
|  *	scan list of controllers looking for the one that manages | ||||
|  *	the 'dev' device | ||||
|  * @dev: pointer to a struct device related with the MCI | ||||
|  */ | ||||
| struct mem_ctl_info *find_mci_by_dev(struct device *dev) | ||||
| { | ||||
| 	struct mem_ctl_info *ret; | ||||
| 
 | ||||
| 	mutex_lock(&mem_ctls_mutex); | ||||
| 	ret = __find_mci_by_dev(dev); | ||||
| 	mutex_unlock(&mem_ctls_mutex); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(find_mci_by_dev); | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -588,7 +599,7 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci) | |||
| 
 | ||||
| 	insert_before = &mc_devices; | ||||
| 
 | ||||
| 	p = find_mci_by_dev(mci->pdev); | ||||
| 	p = __find_mci_by_dev(mci->pdev); | ||||
| 	if (unlikely(p != NULL)) | ||||
| 		goto fail0; | ||||
| 
 | ||||
|  | @ -640,26 +651,28 @@ static int del_mc_from_global_list(struct mem_ctl_info *mci) | |||
|  * | ||||
|  * If found, return a pointer to the structure. | ||||
|  * Else return NULL. | ||||
|  * | ||||
|  * Caller must hold mem_ctls_mutex. | ||||
|  */ | ||||
| struct mem_ctl_info *edac_mc_find(int idx) | ||||
| { | ||||
| 	struct mem_ctl_info *mci = NULL; | ||||
| 	struct list_head *item; | ||||
| 	struct mem_ctl_info *mci; | ||||
| 
 | ||||
| 	mutex_lock(&mem_ctls_mutex); | ||||
| 
 | ||||
| 	list_for_each(item, &mc_devices) { | ||||
| 		mci = list_entry(item, struct mem_ctl_info, link); | ||||
| 
 | ||||
| 		if (mci->mc_idx >= idx) { | ||||
| 			if (mci->mc_idx == idx) | ||||
| 				return mci; | ||||
| 
 | ||||
| 			if (mci->mc_idx == idx) { | ||||
| 				goto unlock; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| unlock: | ||||
| 	mutex_unlock(&mem_ctls_mutex); | ||||
| 	return mci; | ||||
| } | ||||
| EXPORT_SYMBOL(edac_mc_find); | ||||
| 
 | ||||
|  | @ -779,7 +792,7 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) | |||
| 	mutex_lock(&mem_ctls_mutex); | ||||
| 
 | ||||
| 	/* find the requested mci struct in the global list */ | ||||
| 	mci = find_mci_by_dev(dev); | ||||
| 	mci = __find_mci_by_dev(dev); | ||||
| 	if (mci == NULL) { | ||||
| 		mutex_unlock(&mem_ctls_mutex); | ||||
| 		return NULL; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Borislav Petkov
						Borislav Petkov