* NEWS (New commands): Mention "set disable-randomization".
	* configure.ac: Add check for HAVE_PERSONALITY and
	HAVE_DECL_ADDR_NO_RANDOMIZE.
	* configure, config.in: Regenerate.
	* linux-nat.c [HAVE_PERSONALITY]: New include <sys/personality.h>.
	[HAVE_PERSONALITY] [!HAVE_DECL_ADDR_NO_RANDOMIZE]: Set
	ADDR_NO_RANDOMIZE.
	(disable_randomization, show_disable_randomization)
	(set_disable_randomization): New.
	(linux_nat_create_inferior) [HAVE_PERSONALITY]: New variables
	PERSONALITY_ORIG and PERSONALITY_SET.  Disable randomization upon the
	variable DISABLE_RANDOMIZATION.
	(_initialize_linux_nat): Call ADD_SETSHOW_BOOLEAN_CMD for the variable
	DISABLE_RANDOMIZATION.

gdb/doc/
	* gdb.texinfo (Starting): Document "set disable-randomization".

gdb/testsuite/
	* gdb.base/randomize.exp, gdb.base/randomize.c: New files.
This commit is contained in:
Jan Kratochvil 2008-07-10 09:31:00 +00:00
parent 1b31505692
commit 10568435e1
11 changed files with 488 additions and 0 deletions

View file

@ -1,3 +1,20 @@
2008-07-10 Jan Kratochvil <jan.kratochvil@redhat.com>
* NEWS (New commands): Mention "set disable-randomization".
* configure.ac: Add check for HAVE_PERSONALITY and
HAVE_DECL_ADDR_NO_RANDOMIZE.
* configure, config.in: Regenerate.
* linux-nat.c [HAVE_PERSONALITY]: New include <sys/personality.h>.
[HAVE_PERSONALITY] [!HAVE_DECL_ADDR_NO_RANDOMIZE]: Set
ADDR_NO_RANDOMIZE.
(disable_randomization, show_disable_randomization)
(set_disable_randomization): New.
(linux_nat_create_inferior) [HAVE_PERSONALITY]: New variables
PERSONALITY_ORIG and PERSONALITY_SET. Disable randomization upon the
variable DISABLE_RANDOMIZATION.
(_initialize_linux_nat): Call ADD_SETSHOW_BOOLEAN_CMD for the variable
DISABLE_RANDOMIZATION.
2008-07-09 Pedro Alves <pedro@codesourcery.com>
Adjust all targets to new target_stop interface.

View file

@ -98,6 +98,12 @@ show arm force-mode
the current CPSR value for instructions without symbols; previous
versions of GDB behaved as if "set arm fallback-mode arm".
set disable-randomization
show disable-randomization
Standalone programs run with the virtual address space randomization enabled
by default on some platforms. This option keeps the addresses stable across
multiple debugging sessions.
* New targets
x86 DICOS i[34567]86-*-dicos*

View file

@ -82,6 +82,10 @@
/* Define to 1 if you have the <curses.h> header file. */
#undef HAVE_CURSES_H
/* Define to 1 if you have the declaration of `ADDR_NO_RANDOMIZE', and to 0 if
you don't. */
#undef HAVE_DECL_ADDR_NO_RANDOMIZE
/* Define to 1 if you have the declaration of `free', and to 0 if you don't.
*/
#undef HAVE_DECL_FREE
@ -237,6 +241,9 @@
/* Define to 1 if you have the <nlist.h> header file. */
#undef HAVE_NLIST_H
/* Define if you support the personality syscall. */
#undef HAVE_PERSONALITY
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL

182
gdb/configure vendored
View file

@ -23669,6 +23669,188 @@ _ACEOF
fi
echo "$as_me:$LINENO: checking whether ADDR_NO_RANDOMIZE is declared" >&5
echo $ECHO_N "checking whether ADDR_NO_RANDOMIZE is declared... $ECHO_C" >&6
if test "${ac_cv_have_decl_ADDR_NO_RANDOMIZE+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <sys/personality.h>
int
main ()
{
#ifndef ADDR_NO_RANDOMIZE
char *p = (char *) ADDR_NO_RANDOMIZE;
#endif
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_have_decl_ADDR_NO_RANDOMIZE=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_have_decl_ADDR_NO_RANDOMIZE=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_have_decl_ADDR_NO_RANDOMIZE" >&5
echo "${ECHO_T}$ac_cv_have_decl_ADDR_NO_RANDOMIZE" >&6
if test $ac_cv_have_decl_ADDR_NO_RANDOMIZE = yes; then
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_ADDR_NO_RANDOMIZE 1
_ACEOF
else
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_ADDR_NO_RANDOMIZE 0
_ACEOF
fi
if test "$cross_compiling" = yes; then
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <sys/personality.h>
int
main ()
{
# if !HAVE_DECL_ADDR_NO_RANDOMIZE
# define ADDR_NO_RANDOMIZE 0x0040000
# endif
/* Test the flag could be set and stays set. */
personality (personality (0xffffffff) | ADDR_NO_RANDOMIZE);
if (!(personality (personality (0xffffffff)) & ADDR_NO_RANDOMIZE))
return 1
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
have_personality=true
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
have_personality=false
fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <sys/personality.h>
int
main ()
{
# if !HAVE_DECL_ADDR_NO_RANDOMIZE
# define ADDR_NO_RANDOMIZE 0x0040000
# endif
/* Test the flag could be set and stays set. */
personality (personality (0xffffffff) | ADDR_NO_RANDOMIZE);
if (!(personality (personality (0xffffffff)) & ADDR_NO_RANDOMIZE))
return 1
;
return 0;
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && { ac_try='./conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
have_personality=true
else
echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
( exit $ac_status )
have_personality=false
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
if $have_personality
then
cat >>confdefs.h <<\_ACEOF
#define HAVE_PERSONALITY 1
_ACEOF
fi
# Check whether --with-sysroot or --without-sysroot was given.

View file

@ -1268,6 +1268,29 @@ if test "x$gdb_cv_sys_syscall_h_has_tkill" = "xyes" && test "x$ac_cv_func_syscal
AC_DEFINE(HAVE_TKILL_SYSCALL, 1, [Define if you support the tkill syscall.])
fi
dnl Check if we can disable the virtual address space randomization.
dnl The functionality of setarch -R.
AC_CHECK_DECLS([ADDR_NO_RANDOMIZE],,, [#include <sys/personality.h>])
define([PERSONALITY_TEST], [AC_LANG_PROGRAM([#include <sys/personality.h>], [
# if !HAVE_DECL_ADDR_NO_RANDOMIZE
# define ADDR_NO_RANDOMIZE 0x0040000
# endif
/* Test the flag could be set and stays set. */
personality (personality (0xffffffff) | ADDR_NO_RANDOMIZE);
if (!(personality (personality (0xffffffff)) & ADDR_NO_RANDOMIZE))
return 1])])
AC_RUN_IFELSE([PERSONALITY_TEST],
[have_personality=true],
[have_personality=false],
[AC_LINK_IFELSE([PERSONALITY_TEST],
[have_personality=true],
[have_personality=false])])
if $have_personality
then
AC_DEFINE([HAVE_PERSONALITY], 1,
[Define if you support the personality syscall.])
fi
dnl Handle optional features that can be enabled.
AC_ARG_WITH(sysroot,

View file

@ -1,3 +1,7 @@
2008-07-10 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.texinfo (Starting): Document "set disable-randomization".
2008-07-07 Andreas Schwab <schwab@suse.de>
* gdb.texinfo (GDB/MI Target Manipulation): Fix last change.

View file

@ -1999,6 +1999,57 @@ environment:
This command is available when debugging locally on most targets, excluding
@sc{djgpp}, Cygwin, MS Windows, and QNX Neutrino.
@kindex set disable-randomization
@item set disable-randomization
@itemx set disable-randomization on
This option (enabled by default in @value{GDBN}) will turn off the native
randomization of the virtual address space of the started program. This option
is useful for multiple debugging sessions to make the execution better
reproducible and memory addresses reusable across debugging sessions.
This feature is implemented only on @sc{gnu}/Linux. You can get the same
behavior using
@smallexample
(@value{GDBP}) set exec-wrapper setarch `uname -m` -R
@end smallexample
@item set disable-randomization off
Leave the behavior of the started executable unchanged. Some bugs rear their
ugly heads only when the program is loaded at certain addresses. If your bug
disappears when you run the program under @value{GDBN}, that might be because
@value{GDBN} by default disables the address randomization on platforms, such
as @sc{gnu}/Linux, which do that for stand-alone programs. Use @kbd{set
disable-randomization off} to try to reproduce such elusive bugs.
The virtual address space randomization is implemented only on @sc{gnu}/Linux.
It protects the programs against some kinds of security attacks. In these
cases the attacker needs to know the exact location of a concrete executable
code. Randomizing its location makes it impossible to inject jumps misusing
a code at its expected addresses.
Prelinking shared libraries provides a startup performance advantage but it
makes addresses in these libraries predictable for privileged processes by
having just unprivileged access at the target system. Reading the shared
library binary gives enough information for assembling the malicious code
misusing it. Still even a prelinked shared library can get loaded at a new
random address just requiring the regular relocation process during the
startup. Shared libraries not already prelinked are always loaded at
a randomly chosen address.
Position independent executables (PIE) contain position independent code
similar to the shared libraries and therefore such executables get loaded at
a randomly chosen address upon startup. PIE executables always load even
already prelinked shared libraries at a random address. You can build such
executable using @command{gcc -fPIE -pie}.
Heap (malloc storage), stack and custom mmap areas are always placed randomly
(as long as the randomization is enabled).
@item show disable-randomization
Show the current setting of the explicit disable of the native randomization of
the virtual address space of the started program.
@end table
@node Arguments

View file

@ -50,6 +50,13 @@
#include "event-loop.h"
#include "event-top.h"
#ifdef HAVE_PERSONALITY
# include <sys/personality.h>
# if !HAVE_DECL_ADDR_NO_RANDOMIZE
# define ADDR_NO_RANDOMIZE 0x0040000
# endif
#endif /* HAVE_PERSONALITY */
/* This comment documents high-level logic of this file.
Waiting for events in sync mode
@ -220,6 +227,33 @@ show_debug_linux_nat_async (struct ui_file *file, int from_tty,
value);
}
static int disable_randomization = 1;
static void
show_disable_randomization (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
#ifdef HAVE_PERSONALITY
fprintf_filtered (file, _("\
Disabling randomization of debuggee's virtual address space is %s.\n"),
value);
#else /* !HAVE_PERSONALITY */
fputs_filtered (_("\
Disabling randomization of debuggee's virtual address space is unsupported on\n\
this platform.\n"), file);
#endif /* !HAVE_PERSONALITY */
}
static void
set_disable_randomization (char *args, int from_tty, struct cmd_list_element *c)
{
#ifndef HAVE_PERSONALITY
error (_("\
Disabling randomization of debuggee's virtual address space is unsupported on\n\
this platform."));
#endif /* !HAVE_PERSONALITY */
}
static int linux_parent_pid;
struct simple_pid_list
@ -1279,6 +1313,9 @@ linux_nat_create_inferior (char *exec_file, char *allargs, char **env,
int from_tty)
{
int saved_async = 0;
#ifdef HAVE_PERSONALITY
int personality_orig = 0, personality_set = 0;
#endif /* HAVE_PERSONALITY */
/* The fork_child mechanism is synchronous and calls target_wait, so
we have to mask the async mode. */
@ -1302,8 +1339,36 @@ linux_nat_create_inferior (char *exec_file, char *allargs, char **env,
the inferior execing. */
linux_nat_async_events (sigchld_default);
#ifdef HAVE_PERSONALITY
if (disable_randomization)
{
errno = 0;
personality_orig = personality (0xffffffff);
if (errno == 0 && !(personality_orig & ADDR_NO_RANDOMIZE))
{
personality_set = 1;
personality (personality_orig | ADDR_NO_RANDOMIZE);
}
if (errno != 0 || (personality_set
&& !(personality (0xffffffff) & ADDR_NO_RANDOMIZE)))
warning (_("Error disabling address space randomization: %s"),
safe_strerror (errno));
}
#endif /* HAVE_PERSONALITY */
linux_ops->to_create_inferior (exec_file, allargs, env, from_tty);
#ifdef HAVE_PERSONALITY
if (personality_set)
{
errno = 0;
personality (personality_orig);
if (errno != 0)
warning (_("Error restoring address space randomization: %s"),
safe_strerror (errno));
}
#endif /* HAVE_PERSONALITY */
if (saved_async)
linux_nat_async_mask (saved_async);
}
@ -4378,6 +4443,17 @@ Tells gdb whether to control the GNU/Linux inferior in asynchronous mode."),
/* Install the default mode. */
linux_nat_set_async_mode (linux_async_permitted);
add_setshow_boolean_cmd ("disable-randomization", class_support,
&disable_randomization, _("\
Set disabling of debuggee's virtual address space randomization."), _("\
Show disabling of debuggee's virtual address space randomization."), _("\
When this mode is on (which is the default), randomization of the virtual\n\
address space is disabled. Standalone programs run with the randomization\n\
enabled by default on some platforms."),
&set_disable_randomization,
&show_disable_randomization,
&setlist, &showlist);
}

View file

@ -1,3 +1,7 @@
2008-07-10 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.base/randomize.exp, gdb.base/randomize.c: New files.
2008-07-09 Pedro Alves <pedro@codesourcery.com>
* gdb.base/chng-syms.exp: Don't expect "No symbol ...".

View file

@ -0,0 +1,31 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2008 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Please email any bugs, comments, and/or additions to this file to:
bug-gdb@prep.ai.mit.edu */
#include <stdlib.h>
#include <stdio.h>
int main()
{
void *p;
p = malloc (1);
return 0; /* print p */
}

View file

@ -0,0 +1,87 @@
# Copyright 2008 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
set testfile randomize
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
untested "Couldn't compile test program"
return -1
}
# Get things started.
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
proc address_get { testname } {
global gdb_prompt
if {![runto_main]} {
return -1
}
# Do not rely on printf; some test configurations don't work with stdio.
gdb_breakpoint [gdb_get_line_number "print p"]
gdb_continue_to_breakpoint "$testname - address set"
gdb_test_multiple "print/x p" $testname {
-re "\\$\[0-9\]+ = (0x\[0-9a-f\]*)\r?\n$gdb_prompt $" {
pass $testname
return $expect_out(1,string)
}
}
}
set test "set disable-randomization off"
gdb_test_multiple "${test}" "${test}" {
-re "Disabling randomization .* unsupported .*$gdb_prompt $" {
untested "No randomization supported by this GDB"
return -1
}
-re "$gdb_prompt $" {
pass $test
}
}
gdb_test "show disable-randomization" \
"Disabling randomization .* is off." \
"show disable-randomization off"
set addr1 [address_get "randomized first address"]
set addr2 [address_get "randomized second address"]
set test "randomized addresses should not match"
if {$addr1 eq $addr2} {
untested "No randomization detected on this system"
return -1
} else {
pass $test
}
gdb_test "set disable-randomization on"
gdb_test "show disable-randomization" \
"Disabling randomization .* is on." \
"show disable-randomization on"
set addr1 [address_get "fixed first address"]
set addr2 [address_get "fixed second address"]
set test "fixed addresses should match"
if {$addr1 eq $addr2} {
pass $test
} else {
fail $test
}