| 
									
										
										
										
											2020-04-22 16:48:10 +00:00
										 |  |  | /* Test for syscall interfaces.
 | 
					
						
							| 
									
										
										
										
											2025-01-01 18:14:45 +00:00
										 |  |  |    Copyright (C) 2020-2025 Free Software Foundation, Inc. | 
					
						
							| 
									
										
										
										
											2020-04-22 16:48:10 +00:00
										 |  |  |    This file is part of the GNU C Library. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The GNU C Library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |    modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |    License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |    version 2.1 of the License, or (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The GNU C Library 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 | 
					
						
							|  |  |  |    Lesser General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |    License along with the GNU C Library; if not, see | 
					
						
							|  |  |  |    <https://www.gnu.org/licenses/>.  */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This test verifies that the x32 system call handling zero-extends
 | 
					
						
							|  |  |  |    unsigned 32-bit arguments to the 64-bit argument registers for | 
					
						
							|  |  |  |    system calls (bug 25810).  The bug is specific to x32, but the test | 
					
						
							|  |  |  |    should pass on all architectures.  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <sys/mman.h>
 | 
					
						
							|  |  |  | #include <support/check.h>
 | 
					
						
							|  |  |  | #include <support/xunistd.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* On x32, this can be passed in a single 64-bit integer register.  */ | 
					
						
							|  |  |  | struct Array | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   size_t length; | 
					
						
							|  |  |  |   void *ptr; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int error_count; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-22 21:11:58 +00:00
										 |  |  | __attribute_optimization_barrier__ | 
					
						
							| 
									
										
										
										
											2020-04-22 16:48:10 +00:00
										 |  |  | struct Array | 
					
						
							|  |  |  | allocate (size_t bytes) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!bytes) | 
					
						
							|  |  |  |     return __extension__ (struct Array) {0, 0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void *p = mmap (0x0, bytes, PROT_READ | PROT_WRITE, | 
					
						
							|  |  |  | 		  MAP_PRIVATE | MAP_ANON, -1, 0); | 
					
						
							|  |  |  |   if (p == MAP_FAILED) | 
					
						
							|  |  |  |     return __extension__ (struct Array) {0, 0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return __extension__ (struct Array) {bytes, p}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-22 21:11:58 +00:00
										 |  |  | __attribute_optimization_barrier__ | 
					
						
							| 
									
										
										
										
											2020-04-22 16:48:10 +00:00
										 |  |  | void | 
					
						
							|  |  |  | deallocate (struct Array b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* On x32, the 64-bit integer register containing `b' may be copied
 | 
					
						
							|  |  |  |      to another 64-bit integer register to pass the second argument to | 
					
						
							|  |  |  |      munmap.  */ | 
					
						
							|  |  |  |   if (b.length && munmap (b.ptr, b.length)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       printf ("munmap error: %m\n"); | 
					
						
							|  |  |  |       error_count++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-22 21:11:58 +00:00
										 |  |  | __attribute_optimization_barrier__ | 
					
						
							| 
									
										
										
										
											2020-04-22 16:48:10 +00:00
										 |  |  | void * | 
					
						
							|  |  |  | do_mmap (void *addr, size_t length) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return mmap (addr, length, PROT_READ | PROT_WRITE, | 
					
						
							|  |  |  | 	       MAP_PRIVATE | MAP_ANON, -1, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-22 21:11:58 +00:00
										 |  |  | __attribute_optimization_barrier__ | 
					
						
							| 
									
										
										
										
											2020-04-22 16:48:10 +00:00
										 |  |  | void * | 
					
						
							|  |  |  | reallocate (struct Array b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* On x32, the 64-bit integer register containing `b' may be copied
 | 
					
						
							|  |  |  |      to another 64-bit integer register to pass the second argument to | 
					
						
							|  |  |  |      do_mmap.  */ | 
					
						
							|  |  |  |   if (b.length) | 
					
						
							|  |  |  |     return do_mmap (b.ptr, b.length); | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-22 21:11:58 +00:00
										 |  |  | __attribute_optimization_barrier__ | 
					
						
							| 
									
										
										
										
											2020-04-22 16:48:10 +00:00
										 |  |  | void | 
					
						
							|  |  |  | protect (struct Array b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (b.length) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* On x32, the 64-bit integer register containing `b' may be copied
 | 
					
						
							|  |  |  | 	 to another 64-bit integer register to pass the second argument | 
					
						
							|  |  |  | 	 to mprotect.  */ | 
					
						
							|  |  |  |       if (mprotect (b.ptr, b.length, | 
					
						
							|  |  |  | 		    PROT_READ | PROT_WRITE | PROT_EXEC)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  printf ("mprotect error: %m\n"); | 
					
						
							|  |  |  | 	  error_count++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-22 21:11:58 +00:00
										 |  |  | __attribute_optimization_barrier__ | 
					
						
							| 
									
										
										
										
											2020-04-22 16:48:10 +00:00
										 |  |  | ssize_t | 
					
						
							|  |  |  | do_read (int fd, void *ptr, struct Array b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* On x32, the 64-bit integer register containing `b' may be copied
 | 
					
						
							|  |  |  |      to another 64-bit integer register to pass the second argument to | 
					
						
							|  |  |  |      read.  */ | 
					
						
							|  |  |  |   if (b.length) | 
					
						
							|  |  |  |     return read (fd, ptr, b.length); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-22 21:11:58 +00:00
										 |  |  | __attribute_optimization_barrier__ | 
					
						
							| 
									
										
										
										
											2020-04-22 16:48:10 +00:00
										 |  |  | ssize_t | 
					
						
							|  |  |  | do_write (int fd, void *ptr, struct Array b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* On x32, the 64-bit integer register containing `b' may be copied
 | 
					
						
							|  |  |  |      to another 64-bit integer register to pass the second argument to | 
					
						
							|  |  |  |      write.  */ | 
					
						
							|  |  |  |   if (b.length) | 
					
						
							|  |  |  |     return write (fd, ptr, b.length); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | do_test (void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct Array array; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   array = allocate (1); | 
					
						
							|  |  |  |   protect (array); | 
					
						
							|  |  |  |   deallocate (array); | 
					
						
							|  |  |  |   void *p = reallocate (array); | 
					
						
							|  |  |  |   if (p == MAP_FAILED) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       printf ("mmap error: %m\n"); | 
					
						
							|  |  |  |       error_count++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   array.ptr = p; | 
					
						
							|  |  |  |   protect (array); | 
					
						
							|  |  |  |   deallocate (array); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int fd = xopen ("/dev/null", O_RDWR, 0); | 
					
						
							|  |  |  |   char buf[2]; | 
					
						
							|  |  |  |   array.ptr = buf; | 
					
						
							|  |  |  |   if (do_read (fd, array.ptr, array) == -1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       printf ("read error: %m\n"); | 
					
						
							|  |  |  |       error_count++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (do_write (fd, array.ptr, array) == -1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       printf ("write error: %m\n"); | 
					
						
							|  |  |  |       error_count++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   xclose (fd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return error_count ? EXIT_FAILURE : EXIT_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <support/test-driver.c>
 |