LINUX_book
456 pág.

LINUX_book


DisciplinaLinux714 materiais1.847 seguidores
Pré-visualização50 páginas
from the traced tool\u2019s output (if tracing something off of
the command line). For csh or tcsh, you can use something like ( strace /bin/
ls > /dev/null ) | & less to see the actual strace output without the output
from the traced program (/bin/ls in this case). Other shells support separating
stdout and stderr as well, although it is usually just easier to send the output
to a file using the -o switch to strace. This also ensures that the strace output
is completely clean and without any stderr output from the traced process.
When a setuid program is run off of the command line, the program is
run as the user of the strace program, and the setuid does not take place.
There are also security protections against tracing a running program that
was setuid. Even if a running setuid-root program changes its effective user
ID back to the real user ID, strace will not be able to attach to the process and
trace it. This is for security reasons since the process may still have sensitive
information in its memory from when it was running as root.
If a program is setuid to root, strace requires root privileges to properly
trace it. There are two easy ways to trace a setuid-root program, both of which
require root privileges. The first method is to strace the setuid program as
root. This will ensure the setuid-root program is also straced as root, but the
real user ID will be root and not a mortal user as would normally be the case.
The other method is to trace the shell as root using the -f switch to follow the
setuid-root program and its invocation. The latter method is better, although
it is a bit less convenient.
61
2.4.1 strace and EINTR
If you are using strace on a program that does not handle interrupted system
calls properly, the target program will very likely experience a problem.
Consider the following source code snippet:
result = accept(s, addr, &addrlen);
if (result < 0)
{
 perror( \u201caccept\u201d ) ;
 return (SOCKET) INVALID_SOCKET;
}
else
 return result;
This function does not handle interruptions to the accept() call properly and is
not safe to strace. If you were to strace this process while it was waiting on
accept(), the process would pop out of the accept call and return an error via
perror(). The error code (errno) received when a system call is interrupted is
EINTR. Because the process does not handle EINTR error codes, the process
will not recover, and the process may even exit altogether.
 A better (and more robust) way to write this code would be
do
{
 result = accept(s, addr, &addrlen);
} while ( result < 0 && errno == EINTR )
if (result < 0)
{
 perror( \u201caccept\u201d ) ;
 return (SOCKET) INVALID_SOCKET;
}
else
 return result;
The new code will still pop out of accept() if strace attaches to it, although the
while loop will call accept() again when it receives the EINTR error code. In
other words, when strace attaches, the code loop will see the EINTR error code
and restart the accept() system call. This code is robust with respect to
interrupts (that are caused by signals).
2.4 Effects and Issues of Using strace
62 strace and System Call Tracing Explained Chap. 2
2.5 REAL DEBUGGING EXAMPLES
The best way to learn about any tool is to roll up your sleeves and try to solve
some real problems on your own. This section includes some examples to get
you started.
2.5.1 Reducing Start Up Time by Fixing LD_LIBRARY_PATH
The LD_LIBRARY_PATH environment variable is used by the run time linker
to find the depended libraries for an executable or library. The ldd command
can be used to find the dependent libraries:
ion 201% ldd /bin/ls
 librt.so.1 => /lib/librt.so.1 (0x40024000)
 libacl.so.1 => /lib/libacl.so.1 (0x40035000)
 libc.so.6 => /lib/libc.so.6 (0x4003b000)
 libpthread.so.0 => /lib/libpthread.so.0 (0x40159000)
 libattr.so.1 => /lib/libattr.so.1 (0x4016e000)
 /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
When a program is first run, the run time linker must locate and load all of
these libraries before the program can execute. The run time linker runs inside
the process itself, and any interactions with the operating system can be traced
with strace. Before getting into details, first let me apologize in advance for
the long strace output. This is a good example of a poor LD_LIBRARY_PATH,
but unfortunately the output is very long.
ion 685% echo $LD_LIBRARY_PATH
/usr/lib:/home/wilding/sqllib/lib:/usr/java/lib:/usr/ucblib:/opt/
\u27a5IBMcset/lib
With this LD_LIBRARY_PATH, the run time linker will have to search /usr/
lib first, then /home/wilding/sqllib/lib, then /usr/java/lib, and so on. The strace
tool will show just how much work is involved:
ion 206% strace telnet
execve(\u201c/usr/bin/telnet\u201d, [\u201ctelnet\u201d, \u201cfoo\u201d, \u201c136\u201d], [/* 64 vars */
\u27a5]) = 0
uname({sys=\u201dLinux\u201d, node=\u201dion\u201d, ...}) = 0
\u27a5brk(0) = 0x8066308
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -
1, 0) = 0x40013000
open(\u201c/etc/ld.so.preload\u201d, O_RDONLY) = -1 ENOENT (No such file or
\u27a5directory)
open(\u201c/usr/lib/i686/mmx/libncurses.so.5\u201d, O_RDONLY) = -1 ENOENT (No
63
\u27a5such file or directory)
stat64(\u201c/usr/lib/i686/mmx\u201d, 0xbfffe59c) = -1 ENOENT (No such
\u27a5file or directory)
open(\u201c/usr/lib/i686/libncurses.so.5\u201d, O_RDONLY) = -1 ENOENT
\u27a5(No such file or directory)
stat64(\u201c/usr/lib/i686\u201d, 0xbfffe59c) = -1 ENOENT (No such
\u27a5file or directory)
open(\u201c/usr/lib/mmx/libncurses.so.5\u201d, O_RDONLY) = -1 ENOENT (No
\u27a5such file or directory)
stat64(\u201c/usr/lib/mmx\u201d, 0xbfffe59c) = -1 ENOENT (No such
\u27a5file or directory)
open(\u201c/usr/lib/libncurses.so.5\u201d, O_RDONLY) = -1 ENOENT (No
\u27a5such file or directory)
stat64(\u201c/usr/lib\u201d, {st_mode=S_IFDIR|0755, st_size=32768, ...})
= 0
open(\u201c/home/wilding/sqllib/lib/i686/mmx/libncurses.so.5\u201d,
\u27a5O_RDONLY) = -1 ENOENT (No such file or directory)
stat64(\u201c/home/wilding/sqllib/lib/i686/mmx\u201d, 0xbfffe59c) = -1
\u27a5ENOENT (No such file or directory)
open(\u201c/home/wilding/sqllib/lib/i686/libncurses.so.5\u201d,
\u27a5O_RDONLY) = -1 ENOENT (No such file or directory)
stat64(\u201c/home/wilding/sqllib/lib/i686\u201d, 0xbfffe59c) = -1
\u27a5ENOENT (No such file or directory)
open(\u201c/home/wilding/sqllib/lib/mmx/libncurses.so.5\u201d, O_RDONLY)
\u27a5= -1 ENOENT (No such file or directory)
stat64(\u201c/home/wilding/sqllib/lib/mmx\u201d, 0xbfffe59c) = -1 ENOENT
\u27a5(No such file or directory)
open(\u201c/home/wilding/sqllib/lib/libncurses.so.5\u201d, O_RDONLY) = -1
\u27a5ENOENT (No such file or directory)
stat64(\u201c/home/wilding/sqllib/lib\u201d,
{st_mode=S_IFDIR|S_ISGID|0755, st_size=12288, ...}) = 0
open(\u201c/usr/java/lib/i686/mmx/libncurses.so.5\u201d, O_RDONLY) = -1
\u27a5ENOENT (No such file or directory)
stat64(\u201c/usr/java/lib/i686/mmx\u201d, 0xbfffe59c) = -1 ENOENT (No
\u27a5such file or directory)
open(\u201c/usr/java/lib/i686/libncurses.so.5\u201d, O_RDONLY) = -1
\u27a5ENOENT (No such file or directory)
stat64(\u201c/usr/java/lib/i686\u201d, 0xbfffe59c) = -1 ENOENT (No such
\u27a5file or directory)
open(\u201c/usr/java/lib/mmx/libncurses.so.5\u201d, O_RDONLY) = -1
\u27a5ENOENT (No such file or directory)
stat64(\u201c/usr/java/lib/mmx\u201d, 0xbfffe59c) = -1 ENOENT (No such
\u27a5file or directory)
open(\u201c/usr/java/lib/libncurses.so.5\u201d, O_RDONLY) = -1 ENOENT (No
\u27a5such file or directory)
stat64(\u201c/usr/java/lib\u201d, 0xbfffe59c) = -1 ENOENT (No such
\u27a5file or directory)
open(\u201c/usr/ucblib/i686/mmx/libncurses.so.5\u201d, O_RDONLY) = -1
\u27a5ENOENT No such file or directory)
stat64(\u201c/usr/ucblib/i686/mmx\u201d, 0xbfffe59c) = -1 ENOENT (No such
2.5 Real Debugging Examples
64 strace and System Call Tracing Explained Chap. 2
\u27a5file or directory)
open(\u201c/usr/ucblib/i686/libncurses.so.5\u201d, O_RDONLY) = -1 ENOENT (No
\u27a5such file or directory)
stat64(\u201c/usr/ucblib/i686\u201d, 0xbfffe59c) = -1 ENOENT (No such file or
\u27a5directory)
open(\u201c/usr/ucblib/mmx/libncurses.so.5\u201d, O_RDONLY) = -1 ENOENT(No
\u27a5such file or directory)
stat64(\u201c/usr/ucblib/mmx\u201d, 0xbfffe59c) = -1 ENOENT (No such file or
\u27a5directory)
open(\u201c/usr/ucblib/libncurses.so.5\u201d,