mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-31 22:10:34 +03:00 
			
		
		
		
	elf: Fix LD_AUDIT for modules with invalid version (BZ#24122)
The error handling patch for invalid audit modules version access
invalid memory:
elf/rtld.c:
1454               unsigned int (*laversion) (unsigned int);
1455               unsigned int lav;
1456               if  (err_str == NULL
1457                    && (laversion = largs.result) != NULL
1458                    && (lav = laversion (LAV_CURRENT)) > 0
1459                    && lav <= LAV_CURRENT)
1460                 {
[...]
1526               else
1527                 {
1528                   /* We cannot use the DSO, it does not have the
1529                      appropriate interfaces or it expects something
1530                      more recent.  */
1531 #ifndef NDEBUG
1532                   Lmid_t ns = dlmargs.map->l_ns;
1533 #endif
1534                   _dl_close (dlmargs.map);
1535
1536                   /* Make sure the namespace has been cleared entirely.  */
1537                   assert (GL(dl_ns)[ns]._ns_loaded == NULL);
1538                   assert (GL(dl_ns)[ns]._ns_nloaded == 0);
1539
1540                   GL(dl_tls_max_dtv_idx) = tls_idx;
1541                   goto not_loaded;
1542                 }
1431           const char *err_str = NULL;
1432           bool malloced;
1433           (void) _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit,
1434                                   &dlmargs);
1435           if (__glibc_unlikely (err_str != NULL))
1436             {
1437             not_loaded:
1438               _dl_error_printf ("\
1439 ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
1440                                 name, err_str);
1441               if (malloced)
1442                 free ((char *) err_str);
1443             }
On failure the err_str will be NULL and _dl_debug_vdprintf does not handle
it properly:
elf/dl-misc.c:
200             case 's':
201               /* Get the string argument.  */
202               iov[niov].iov_base = va_arg (arg, char *);
203               iov[niov].iov_len = strlen (iov[niov].iov_base);
204               if (prec != -1)
205                 iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
206               ++niov;
207               break;
This patch fixes the issues and improves the error message.
Checked on x86_64-linux-gnu and i686-linux-gnu
	[BZ #24122]
	* elf/Makefile (tests): Add tst-audit13.
	(modules-names): Add tst-audit13mod1.
	(tst-audit13.out, LDFLAGS-tst-audit13mod1.so, tst-audit13-ENV): New
	rule.
	* elf/rtld.c (dl_main): Handle invalid audit module version.
	* elf/tst-audit13.c: New file.
	* elf/tst-audit13mod1.c: Likewise.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
			
			
This commit is contained in:
		
							
								
								
									
										11
									
								
								ChangeLog
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								ChangeLog
									
									
									
									
									
								
							| @@ -1,3 +1,14 @@ | ||||
| 2019-01-24  Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| 	[BZ #24122] | ||||
| 	* elf/Makefile (tests): Add tst-audit13. | ||||
| 	(modules-names): Add tst-audit13mod1. | ||||
| 	(tst-audit13.out, LDFLAGS-tst-audit13mod1.so, tst-audit13-ENV): New | ||||
| 	rule. | ||||
| 	* elf/rtld.c (dl_main): Handle invalid audit module version. | ||||
| 	* elf/tst-audit13.c: New file. | ||||
| 	* elf/tst-audit13mod1.c: Likewise. | ||||
| 
 | ||||
| 2019-01-22  Samuel Thibault  <samuel.thibault@ens-lyon.org> | ||||
| 
 | ||||
| 	* sysdeps/mach/hurd/faccessat.c (__faccessat_common): Check for errors | ||||
|   | ||||
| @@ -187,7 +187,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ | ||||
| 	 tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ | ||||
| 	 tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ | ||||
| 	 tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ | ||||
| 	 tst-unwind-ctor tst-unwind-main | ||||
| 	 tst-unwind-ctor tst-unwind-main tst-audit13 | ||||
| #	 reldep9 | ||||
| tests-internal += loadtest unload unload2 circleload1 \ | ||||
| 	 neededtest neededtest2 neededtest3 neededtest4 \ | ||||
| @@ -275,7 +275,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ | ||||
| 		tst-latepthreadmod $(tst-tls-many-dynamic-modules) \ | ||||
| 		tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \ | ||||
| 		tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \ | ||||
| 		tst-absolute-zero-lib tst-big-note-lib tst-unwind-ctor-lib | ||||
| 		tst-absolute-zero-lib tst-big-note-lib tst-unwind-ctor-lib \ | ||||
| 		tst-audit13mod1 | ||||
| # Most modules build with _ISOMAC defined, but those filtered out | ||||
| # depend on internal headers. | ||||
| modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\ | ||||
| @@ -1382,6 +1383,10 @@ tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so | ||||
| $(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so | ||||
| LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map | ||||
|  | ||||
| $(objpfx)tst-audit13.out: $(objpfx)tst-audit13mod1.so | ||||
| LDFLAGS-tst-audit13mod1.so = -Wl,-z,lazy | ||||
| tst-audit13-ENV = LD_AUDIT=$(objpfx)tst-audit13mod1.so | ||||
|  | ||||
| # Override -z defs, so that we can reference an undefined symbol. | ||||
| # Force lazy binding for the same reason. | ||||
| LDFLAGS-tst-latepthreadmod.so = \ | ||||
|   | ||||
							
								
								
									
										30
									
								
								elf/rtld.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								elf/rtld.c
									
									
									
									
									
								
							| @@ -1453,10 +1453,12 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", | ||||
|  | ||||
| 	      unsigned int (*laversion) (unsigned int); | ||||
| 	      unsigned int lav; | ||||
| 	      if  (err_str == NULL | ||||
| 		   && (laversion = largs.result) != NULL | ||||
| 		   && (lav = laversion (LAV_CURRENT)) > 0 | ||||
| 		   && lav <= LAV_CURRENT) | ||||
| 	      if (err_str != NULL) | ||||
| 		goto not_loaded; | ||||
|  | ||||
| 	      if ((laversion = largs.result) != NULL | ||||
| 		  && (lav = laversion (LAV_CURRENT)) > 0 | ||||
| 		  && lav <= LAV_CURRENT) | ||||
| 		{ | ||||
| 		  /* Allocate structure for the callback function pointers. | ||||
| 		     This call can never fail.  */ | ||||
| @@ -1538,7 +1540,25 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", | ||||
| 		  assert (GL(dl_ns)[ns]._ns_nloaded == 0); | ||||
|  | ||||
| 		  GL(dl_tls_max_dtv_idx) = tls_idx; | ||||
| 		  goto not_loaded; | ||||
| 		  if (GLRO(dl_debug_mask) & DL_DEBUG_FILES) | ||||
| 		    { | ||||
| 		      _dl_debug_printf ("\ | ||||
| \nfile=%s cannot be loaded as audit interface; ignored.\n", name); | ||||
| 		      if (laversion == NULL) | ||||
| 			_dl_debug_printf ( | ||||
| "  la_version function not found.\n"); | ||||
| 		      else | ||||
| 			{ | ||||
| 			  if (lav == 0) | ||||
| 			    _dl_debug_printf ( | ||||
| "  auditor requested to be ignored (returned version of 0).\n"); | ||||
| 			  else | ||||
| 			    _dl_debug_printf ( | ||||
| "  auditor disabled since expected version %d is greater than " | ||||
| "supported version %d.\n", | ||||
| 					      lav, LAV_CURRENT); | ||||
| 			} | ||||
| 		    } | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										28
									
								
								elf/tst-audit13.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								elf/tst-audit13.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| /* Check for invalid audit version (BZ#24122). | ||||
|    Copyright (C) 2019 Free Software Foundation, Inc. | ||||
|    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 | ||||
|    <http://www.gnu.org/licenses/>.  */ | ||||
|  | ||||
| #include <stdio.h> | ||||
|  | ||||
| static int | ||||
| do_test (void) | ||||
| { | ||||
|   puts ("plt call"); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| #include <support/test-driver.c> | ||||
							
								
								
									
										93
									
								
								elf/tst-audit13mod1.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								elf/tst-audit13mod1.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| /* Check for invalid audit version (BZ#24122). | ||||
|    Copyright (C) 2019 Free Software Foundation, Inc. | ||||
|    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 | ||||
|    <http://www.gnu.org/licenses/>.  */ | ||||
|  | ||||
| #include <link.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| unsigned int | ||||
| la_version (unsigned int version) | ||||
| { | ||||
|   /* The audit specification says that a version of 0 or a version | ||||
|      greater than any version supported by the dynamic loader shall | ||||
|      cause the module to be ignored.  */ | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| void | ||||
| la_activity (uintptr_t *cookie, unsigned int flag) | ||||
| { | ||||
|   exit (EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| char * | ||||
| la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) | ||||
| { | ||||
|   exit (EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| unsigned int | ||||
| la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t * cookie) | ||||
| { | ||||
|   exit (EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| void | ||||
| la_preinit (uintptr_t * cookie) | ||||
| { | ||||
|   exit (EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| uintptr_t | ||||
| #if __ELF_NATIVE_CLASS == 32 | ||||
| la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, | ||||
|               uintptr_t *defcook, unsigned int *flags, const char *symname) | ||||
| #else | ||||
| la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, | ||||
|               uintptr_t *defcook, unsigned int *flags, const char *symname) | ||||
| #endif | ||||
| { | ||||
|   exit (EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| unsigned int | ||||
| la_objclose (uintptr_t * cookie) | ||||
| { | ||||
|   exit (EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| #include <tst-audit.h> | ||||
| #if (!defined (pltenter) || !defined (pltexit) || !defined (La_regs) \ | ||||
|      || !defined (La_retval) || !defined (int_retval)) | ||||
| # error "architecture specific code needed in sysdeps/CPU/tst-audit.h" | ||||
| #endif | ||||
|  | ||||
| ElfW(Addr) | ||||
| pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, | ||||
|           uintptr_t *defcook, La_regs *regs, unsigned int *flags, | ||||
|           const char *symname, long int *framesizep) | ||||
| { | ||||
|   exit (EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| unsigned int | ||||
| pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, | ||||
|          uintptr_t *defcook, const La_regs *inregs, La_retval *outregs, | ||||
|          const char *symname) | ||||
| { | ||||
|   exit (EXIT_FAILURE); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user