* csu/Makefile (routines): Add check_fds.
	* elf/rtld.c (dl_main): Call __libc_check_standard_fds for SUID
	binaries.  Add various __builtin_expect.
	* sysdeps/generic/libc-start.c: Move check_fds and helper functions...
	* sysdeps/generic/check_fds.c: ...here.  New file.

	* malloc/malloc.c (ptmalloc_init): Only enable debugging for SUID
	binaries if file /etc/suid-debug is available.
This commit is contained in:
Ulrich Drepper 2000-05-25 05:02:35 +00:00
parent acb5ee2e56
commit db33f7d4ae
6 changed files with 95 additions and 43 deletions

View File

@ -1,5 +1,14 @@
2000-05-24 Ulrich Drepper <drepper@redhat.com>
* csu/Makefile (routines): Add check_fds.
* elf/rtld.c (dl_main): Call __libc_check_standard_fds for SUID
binaries. Add various __builtin_expect.
* sysdeps/generic/libc-start.c: Move check_fds and helper functions...
* sysdeps/generic/check_fds.c: ...here. New file.
* malloc/malloc.c (ptmalloc_init): Only enable debugging for SUID
binaries if file /etc/suid-debug is available.
* locale/programs/ld-collate.c (struct element_t): Add mbseqorder
and wcseqorder members.
(struct locale_collate_t): Likewise.

View File

@ -27,7 +27,7 @@
subdir := csu
routines = init-first libc-start $(libc-init) sysdep version
routines = init-first libc-start $(libc-init) sysdep version check_fds
csu-dummies = $(filter-out $(start-installed-name),crt1.o Mcrt1.o)
extra-objs = start.o gmon-start.o \
$(start-installed-name) g$(start-installed-name) \

View File

@ -52,6 +52,9 @@ extern void *_dl_sysdep_read_whole_file (const char *filename,
size_t *filesize_ptr,
int mmap_prot);
/* Protec SUID program against misuse of file descriptors. */
extern void __libc_check_standard_fds (void);
/* Helper function to handle errors while resolving symbols. */
static void print_unresolved (int errcode, const char *objname,
const char *errsting);
@ -396,6 +399,12 @@ dl_main (const ElfW(Phdr) *phdr,
hp_timing_t diff;
#endif
/* First thing, if this is a SUID program we make sure that FDs 0,
1, and 2 are allocated. If necessary we are doing it ourself.
If it is not possible we stop the program. */
if (__builtin_expect (__libc_enable_secure, 0))
__libc_check_standard_fds ();
/* Process the environment variable which control the behaviour. */
process_envvars (&mode, &_dl_lazy);
@ -673,7 +682,7 @@ of this helper program; chances are you did not intend to run this program.\n\
preloads = NULL;
npreloads = 0;
if (preloadlist)
if (__builtin_expect (preloadlist != NULL, 0))
{
/* The LD_PRELOAD environment variable gives list of libraries
separated by white space or colons that are loaded before the
@ -687,7 +696,8 @@ of this helper program; chances are you did not intend to run this program.\n\
while ((p = strsep (&list, " :")) != NULL)
if (p[0] != '\0'
&& (! __libc_enable_secure || strchr (p, '/') == NULL))
&& (__builtin_expect (! __libc_enable_secure, 1)
|| strchr (p, '/') == NULL))
{
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0);
@ -704,7 +714,7 @@ of this helper program; chances are you did not intend to run this program.\n\
/* Read the contents of the file. */
file = _dl_sysdep_read_whole_file ("/etc/ld.so.preload", &file_size,
PROT_READ | PROT_WRITE);
if (file)
if (__builtin_expect (file != NULL, 0))
{
/* Parse the file. It contains names of libraries to be loaded,
separated by white spaces or `:'. It may also contain
@ -783,7 +793,7 @@ of this helper program; chances are you did not intend to run this program.\n\
__munmap (file, file_size);
}
if (npreloads != 0)
if (__builtin_expect (npreloads, 0) != 0)
{
/* Set up PRELOADS with a vector of the preloaded libraries. */
struct link_map *l;
@ -1072,7 +1082,7 @@ of this helper program; chances are you did not intend to run this program.\n\
this has to go here because the calls it makes should use the
rtld versions of the functions (particularly calloc()), but it
needs to have _dl_profile_map set up by the relocator. */
if (_dl_profile_map != NULL)
if (__builtin_expect (_dl_profile_map != NULL, 0))
/* We must prepare the profiling. */
_dl_start_profile (_dl_profile_map, _dl_profile_output);

View File

@ -1722,7 +1722,7 @@ ptmalloc_init __MALLOC_P((void))
__malloc_hook = save_malloc_hook;
__free_hook = save_free_hook;
#endif
if(s) {
if(s && (! __libc_enable_secure || access ("/etc/suid-debug", F_OK) == 0)) {
if(s[0]) mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0'));
__malloc_check_init();
}

View File

@ -0,0 +1,62 @@
/* Copyright (C) 2000 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 Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <unistd.h>
/* Try to get a machine dependent instruction which will make the
program crash. This is used in case everything else fails. */
#include <abort-instr.h>
#ifndef ABORT_INSTRUCTION
/* No such instruction is available. */
# define ABORT_INSTRUCTION
#endif
/* Should other OSes (e.g., Hurd) have different versions which can
be written in a better way? */
static void
check_one_fd (int fd, int mode)
{
if (__builtin_expect (__libc_fcntl (fd, F_GETFD), 0) == -1
&& errno == EBADF)
{
/* Something is wrong with this descriptor, it's probably not
opened. Open /dev/null so that the SUID program we are
about to start does not accidently use this descriptor. */
int nullfd = __libc_open (_PATH_DEVNULL, mode);
if (__builtin_expect (nullfd, 0) == -1)
/* We cannot even give an error message here since it would
run into the same problems. */
while (1)
/* Try for ever and ever. */
ABORT_INSTRUCTION;
}
}
void
__libc_check_standard_fds (void)
{
/* Check all three standard file descriptors. */
check_one_fd (STDIN_FILENO, O_RDONLY);
check_one_fd (STDOUT_FILENO, O_RDWR);
check_one_fd (STDERR_FILENO, O_RDWR);
}

View File

@ -16,12 +16,8 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <ldsodefs.h>
extern void __libc_init_first (int argc, char **argv, char **envp);
@ -32,7 +28,7 @@ extern int __libc_multiple_libcs;
extern void *__libc_stack_end;
/* Prototype for local function. */
static void check_standard_fds (void);
extern void __libc_check_standard_fds (void);
int
__libc_start_main (int (*main) (int, char **, char **), int argc,
@ -54,10 +50,14 @@ __libc_start_main (int (*main) (int, char **, char **), int argc,
/* Set the global _environ variable correctly. */
__environ = &argv[argc + 1];
#ifndef SHARED
/* Some security at this point. Prevent starting a SUID binary where
the standard file descriptors are not opened. */
the standard file descriptors are not opened. We have to do this
only for statically linked applications since otherwise the dynamic
loader did the work already. */
if (__builtin_expect (__libc_enable_secure, 0))
check_standard_fds ();
__libc_check_standard_fds ();
#endif
/* Register the destructor of the dynamic linker if there is any. */
if (__builtin_expect (rtld_fini != NULL, 1))
@ -89,32 +89,3 @@ __libc_start_main (int (*main) (int, char **, char **), int argc,
exit ((*main) (argc, argv, __environ));
}
/* Should other OSes (e.g., Hurd) have different versions which can
be written in a better way? */
static void
check_one_fd (int fd, int mode)
{
if (__libc_fcntl (fd, F_GETFD) == -1 && errno == EBADF)
{
/* Something is wrong with this descriptor, it's probably not
opened. Open /dev/null so that the SUID program we are
about to start does not accidently use this descriptor. */
int nullfd = __libc_open (_PATH_DEVNULL, mode);
if (nullfd == -1)
/* We cannot even give an error message here since it would
run into the same problems. */
abort ();
}
}
static void
check_standard_fds (void)
{
/* Check all three standard file descriptors. */
check_one_fd (STDIN_FILENO, O_RDONLY);
check_one_fd (STDOUT_FILENO, O_RDWR);
check_one_fd (STDERR_FILENO, O_RDWR);
}