mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	os-wrappers-test.c: Correctly forward arguments to fcntl
We can't just unconditionally read the optional arguments (and also read it as a void* despite actually being an int). While this happens to work on most architectures because the first few variadic arguments are passed in registers, this is non-portable and causes a crash on architectures that set bounds on variadic function arguments (for example CHERI-enabled architectures). It could also cause problems on big-endian architectures that pass variadic arguments on the stack rather than in registers. For CHERI-MIPS, reading sizeof(void*) causes a read of 16 bytes from the bounded varargs capability. This always crashes since even calls with the optional argument only have 4 bytes available. Signed-off-by: Alex Richardson <Alexander.Richardson@cl.cam.ac.uk> Reviewed-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
		
							parent
							
								
									e4659ffbf5
								
							
						
					
					
						commit
						e881934927
					
				
					 1 changed files with 22 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -85,7 +85,8 @@ __attribute__ ((visibility("default"))) int
 | 
			
		|||
fcntl(int fd, int cmd, ...)
 | 
			
		||||
{
 | 
			
		||||
	va_list ap;
 | 
			
		||||
	void *arg;
 | 
			
		||||
	int arg;
 | 
			
		||||
	int has_arg;
 | 
			
		||||
 | 
			
		||||
	wrapped_calls_fcntl++;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -93,12 +94,27 @@ fcntl(int fd, int cmd, ...)
 | 
			
		|||
		errno = EINVAL;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case F_DUPFD_CLOEXEC:
 | 
			
		||||
	case F_DUPFD:
 | 
			
		||||
	case F_SETFD:
 | 
			
		||||
		va_start(ap, cmd);
 | 
			
		||||
		arg = va_arg(ap, int);
 | 
			
		||||
		has_arg = 1;
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
		break;
 | 
			
		||||
	case F_GETFD:
 | 
			
		||||
		has_arg = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		fprintf(stderr, "Unexpected fctnl cmd %d\n", cmd);
 | 
			
		||||
		abort();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	va_start(ap, cmd);
 | 
			
		||||
	arg = va_arg(ap, void*);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
 | 
			
		||||
	return real_fcntl(fd, cmd, arg);
 | 
			
		||||
	if (has_arg) {
 | 
			
		||||
		return real_fcntl(fd, cmd, arg);
 | 
			
		||||
	}
 | 
			
		||||
	return real_fcntl(fd, cmd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__ ((visibility("default"))) ssize_t
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue