mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	dm: convert dm_dev_internal.count from atomic_t to refcount_t
atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable dm_dev_internal.count is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees Cook <keescook@chromium.org> Reviewed-by: David Windsor <dwindsor@gmail.com> Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com> Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
		
							parent
							
								
									bb176f6709
								
							
						
					
					
						commit
						2a0b4682e0
					
				
					 2 changed files with 5 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -451,15 +451,15 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
 | 
			
		|||
			return r;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		atomic_set(&dd->count, 0);
 | 
			
		||||
		refcount_set(&dd->count, 1);
 | 
			
		||||
		list_add(&dd->list, &t->devices);
 | 
			
		||||
 | 
			
		||||
	} else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) {
 | 
			
		||||
		r = upgrade_mode(dd, mode, t->md);
 | 
			
		||||
		if (r)
 | 
			
		||||
			return r;
 | 
			
		||||
		refcount_inc(&dd->count);
 | 
			
		||||
	}
 | 
			
		||||
	atomic_inc(&dd->count);
 | 
			
		||||
 | 
			
		||||
	*result = dd->dm_dev;
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -515,7 +515,7 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d)
 | 
			
		|||
		       dm_device_name(ti->table->md), d->name);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (atomic_dec_and_test(&dd->count)) {
 | 
			
		||||
	if (refcount_dec_and_test(&dd->count)) {
 | 
			
		||||
		dm_put_table_device(ti->table->md, d);
 | 
			
		||||
		list_del(&dd->list);
 | 
			
		||||
		kfree(dd);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
#include <linux/hdreg.h>
 | 
			
		||||
#include <linux/completion.h>
 | 
			
		||||
#include <linux/kobject.h>
 | 
			
		||||
#include <linux/refcount.h>
 | 
			
		||||
 | 
			
		||||
#include "dm-stats.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +39,7 @@
 | 
			
		|||
 */
 | 
			
		||||
struct dm_dev_internal {
 | 
			
		||||
	struct list_head list;
 | 
			
		||||
	atomic_t count;
 | 
			
		||||
	refcount_t count;
 | 
			
		||||
	struct dm_dev *dm_dev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue