 606686eeac
			
		
	
	
	606686eeac
	
	
	
		
			
			Al pointed out that we can just toss out the old name on a device and add a new one arbitrarily, so anybody who uses device->name in printk could possibly use free'd memory. Instead of adding locking around all of this he suggested doing it with RCU, so I've introduced a struct rcu_string that does just that and have gone through and protected all accesses to device->name that aren't under the uuid_mutex with rcu_read_lock(). This protects us and I will use it for dealing with removing the device that we used to mount the file system in a later patch. Thanks, Reviewed-by: David Sterba <dsterba@suse.cz> Signed-off-by: Josef Bacik <josef@redhat.com>
		
			
				
	
	
		
			56 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			56 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2012 Red Hat.  All rights reserved.
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public
 | |
|  * License v2 as published by the Free Software Foundation.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public
 | |
|  * License along with this program; if not, write to the
 | |
|  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | |
|  * Boston, MA 021110-1307, USA.
 | |
|  */
 | |
| 
 | |
| struct rcu_string {
 | |
| 	struct rcu_head rcu;
 | |
| 	char str[0];
 | |
| };
 | |
| 
 | |
| static inline struct rcu_string *rcu_string_strdup(const char *src, gfp_t mask)
 | |
| {
 | |
| 	size_t len = strlen(src) + 1;
 | |
| 	struct rcu_string *ret = kzalloc(sizeof(struct rcu_string) +
 | |
| 					 (len * sizeof(char)), mask);
 | |
| 	if (!ret)
 | |
| 		return ret;
 | |
| 	strncpy(ret->str, src, len);
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static inline void rcu_string_free(struct rcu_string *str)
 | |
| {
 | |
| 	if (str)
 | |
| 		kfree_rcu(str, rcu);
 | |
| }
 | |
| 
 | |
| #define printk_in_rcu(fmt, ...) do {	\
 | |
| 	rcu_read_lock();		\
 | |
| 	printk(fmt, __VA_ARGS__);	\
 | |
| 	rcu_read_unlock();		\
 | |
| } while (0)
 | |
| 
 | |
| #define printk_ratelimited_in_rcu(fmt, ...) do {	\
 | |
| 	rcu_read_lock();				\
 | |
| 	printk_ratelimited(fmt, __VA_ARGS__);		\
 | |
| 	rcu_read_unlock();				\
 | |
| } while (0)
 | |
| 
 | |
| #define rcu_str_deref(rcu_str) ({				\
 | |
| 	struct rcu_string *__str = rcu_dereference(rcu_str);	\
 | |
| 	__str->str;						\
 | |
| })
 |