mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-29 00:01:12 +00:00
Update.
* 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:
parent
acb5ee2e56
commit
db33f7d4ae
@ -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.
|
||||
|
@ -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) \
|
||||
|
20
elf/rtld.c
20
elf/rtld.c
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
62
sysdeps/generic/check_fds.c
Normal file
62
sysdeps/generic/check_fds.c
Normal 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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user