mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	fs: Expand __receive_fd() to accept existing fd
Expand __receive_fd() with support for replace_fd() for the coming seccomp "addfd" ioctl(). Add new wrapper receive_fd_replace() for the new behavior and update existing wrappers to retain old behavior. Thanks to Colin Ian King <colin.king@canonical.com> for pointing out an uninitialized variable exposure in an earlier version of this patch. Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Dmitry Kadashev <dkadashev@gmail.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Arnd Bergmann <arnd@arndb.de> Cc: linux-fsdevel@vger.kernel.org Reviewed-by: Sargun Dhillon <sargun@sargun.me> Acked-by: Christian Brauner <christian.brauner@ubuntu.com> Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
		
							parent
							
								
									910d2f16ac
								
							
						
					
					
						commit
						173817151b
					
				
					 2 changed files with 26 additions and 9 deletions
				
			
		
							
								
								
									
										25
									
								
								fs/file.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								fs/file.c
									
									
									
									
									
								
							|  | @ -939,6 +939,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags) | |||
| /**
 | ||||
|  * __receive_fd() - Install received file into file descriptor table | ||||
|  * | ||||
|  * @fd: fd to install into (if negative, a new fd will be allocated) | ||||
|  * @file: struct file that was received from another process | ||||
|  * @ufd: __user pointer to write new fd number to | ||||
|  * @o_flags: the O_* flags to apply to the new fd entry | ||||
|  | @ -952,7 +953,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags) | |||
|  * | ||||
|  * Returns newly install fd or -ve on error. | ||||
|  */ | ||||
| int __receive_fd(struct file *file, int __user *ufd, unsigned int o_flags) | ||||
| int __receive_fd(int fd, struct file *file, int __user *ufd, unsigned int o_flags) | ||||
| { | ||||
| 	int new_fd; | ||||
| 	int error; | ||||
|  | @ -961,21 +962,33 @@ int __receive_fd(struct file *file, int __user *ufd, unsigned int o_flags) | |||
| 	if (error) | ||||
| 		return error; | ||||
| 
 | ||||
| 	new_fd = get_unused_fd_flags(o_flags); | ||||
| 	if (new_fd < 0) | ||||
| 		return new_fd; | ||||
| 	if (fd < 0) { | ||||
| 		new_fd = get_unused_fd_flags(o_flags); | ||||
| 		if (new_fd < 0) | ||||
| 			return new_fd; | ||||
| 	} else { | ||||
| 		new_fd = fd; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ufd) { | ||||
| 		error = put_user(new_fd, ufd); | ||||
| 		if (error) { | ||||
| 			put_unused_fd(new_fd); | ||||
| 			if (fd < 0) | ||||
| 				put_unused_fd(new_fd); | ||||
| 			return error; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (fd < 0) { | ||||
| 		fd_install(new_fd, get_file(file)); | ||||
| 	} else { | ||||
| 		error = replace_fd(new_fd, file, o_flags); | ||||
| 		if (error) | ||||
| 			return error; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Bump the sock usage counts, if any. */ | ||||
| 	__receive_sock(file); | ||||
| 	fd_install(new_fd, get_file(file)); | ||||
| 	return new_fd; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -92,18 +92,22 @@ extern void put_unused_fd(unsigned int fd); | |||
| 
 | ||||
| extern void fd_install(unsigned int fd, struct file *file); | ||||
| 
 | ||||
| extern int __receive_fd(struct file *file, int __user *ufd, | ||||
| extern int __receive_fd(int fd, struct file *file, int __user *ufd, | ||||
| 			unsigned int o_flags); | ||||
| static inline int receive_fd_user(struct file *file, int __user *ufd, | ||||
| 				  unsigned int o_flags) | ||||
| { | ||||
| 	if (ufd == NULL) | ||||
| 		return -EFAULT; | ||||
| 	return __receive_fd(file, ufd, o_flags); | ||||
| 	return __receive_fd(-1, file, ufd, o_flags); | ||||
| } | ||||
| static inline int receive_fd(struct file *file, unsigned int o_flags) | ||||
| { | ||||
| 	return __receive_fd(file, NULL, o_flags); | ||||
| 	return __receive_fd(-1, file, NULL, o_flags); | ||||
| } | ||||
| static inline int receive_fd_replace(int fd, struct file *file, unsigned int o_flags) | ||||
| { | ||||
| 	return __receive_fd(fd, file, NULL, o_flags); | ||||
| } | ||||
| 
 | ||||
| extern void flush_delayed_fput(void); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Kees Cook
						Kees Cook