mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	mm: new primitive kvmemdup()
Similar to kmemdup(), but support large amount of bytes with kvmalloc() and does *not* guarantee that the result will be physically contiguous. Use only in cases where kvmalloc() is needed and free it with kvfree(). Also adapt policy_unpack.c in case someone bisect into this. Link: https://lkml.kernel.org/r/20221221144245.27164-1-sunhao.th@gmail.com Signed-off-by: Hao Sun <sunhao.th@gmail.com> Suggested-by: Daniel Borkmann <daniel@iogearbox.net> Cc: Nick Terrell <terrelln@fb.com> Cc: John Johansen <john.johansen@canonical.com> Cc: Paul Moore <paul@paul-moore.com> Cc: James Morris <jmorris@namei.org> Cc: "Serge E. Hallyn" <serge@hallyn.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									5a9e34747c
								
							
						
					
					
						commit
						0b7b8704dd
					
				
					 3 changed files with 25 additions and 11 deletions
				
			
		|  | @ -177,6 +177,7 @@ extern char *kstrdup(const char *s, gfp_t gfp) __malloc; | |||
| extern const char *kstrdup_const(const char *s, gfp_t gfp); | ||||
| extern char *kstrndup(const char *s, size_t len, gfp_t gfp); | ||||
| extern void *kmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2); | ||||
| extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2); | ||||
| extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp); | ||||
| 
 | ||||
| extern char **argv_split(gfp_t gfp, const char *str, int *argcp); | ||||
|  |  | |||
							
								
								
									
										24
									
								
								mm/util.c
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								mm/util.c
									
										
									
									
									
								
							|  | @ -120,7 +120,8 @@ EXPORT_SYMBOL(kstrndup); | |||
|  * @len: memory region length | ||||
|  * @gfp: GFP mask to use | ||||
|  * | ||||
|  * Return: newly allocated copy of @src or %NULL in case of error | ||||
|  * Return: newly allocated copy of @src or %NULL in case of error, | ||||
|  * result is physically contiguous. Use kfree() to free. | ||||
|  */ | ||||
| void *kmemdup(const void *src, size_t len, gfp_t gfp) | ||||
| { | ||||
|  | @ -133,6 +134,27 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp) | |||
| } | ||||
| EXPORT_SYMBOL(kmemdup); | ||||
| 
 | ||||
| /**
 | ||||
|  * kvmemdup - duplicate region of memory | ||||
|  * | ||||
|  * @src: memory region to duplicate | ||||
|  * @len: memory region length | ||||
|  * @gfp: GFP mask to use | ||||
|  * | ||||
|  * Return: newly allocated copy of @src or %NULL in case of error, | ||||
|  * result may be not physically contiguous. Use kvfree() to free. | ||||
|  */ | ||||
| void *kvmemdup(const void *src, size_t len, gfp_t gfp) | ||||
| { | ||||
| 	void *p; | ||||
| 
 | ||||
| 	p = kvmalloc(len, gfp); | ||||
| 	if (p) | ||||
| 		memcpy(p, src, len); | ||||
| 	return p; | ||||
| } | ||||
| EXPORT_SYMBOL(kvmemdup); | ||||
| 
 | ||||
| /**
 | ||||
|  * kmemdup_nul - Create a NUL-terminated string from unterminated data | ||||
|  * @s: The data to stringify | ||||
|  |  | |||
|  | @ -161,15 +161,6 @@ VISIBLE_IF_KUNIT bool aa_inbounds(struct aa_ext *e, size_t size) | |||
| } | ||||
| EXPORT_SYMBOL_IF_KUNIT(aa_inbounds); | ||||
| 
 | ||||
| static void *kvmemdup(const void *src, size_t len) | ||||
| { | ||||
| 	void *p = kvmalloc(len, GFP_KERNEL); | ||||
| 
 | ||||
| 	if (p) | ||||
| 		memcpy(p, src, len); | ||||
| 	return p; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * aa_unpack_u16_chunk - test and do bounds checking for a u16 size based chunk | ||||
|  * @e: serialized data read head (NOT NULL) | ||||
|  | @ -1027,7 +1018,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) | |||
| 
 | ||||
| 			data->key = key; | ||||
| 			data->size = aa_unpack_blob(e, &data->data, NULL); | ||||
| 			data->data = kvmemdup(data->data, data->size); | ||||
| 			data->data = kvmemdup(data->data, data->size, GFP_KERNEL); | ||||
| 			if (data->size && !data->data) { | ||||
| 				kfree_sensitive(data->key); | ||||
| 				kfree_sensitive(data); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Hao Sun
						Hao Sun