When
ever we run a command or a program in linux , there are 2 types of
calls that are being made.
1.library
calls – These are the calls that are done to a external library
module.Most of the library functions are in the standard C library,
libc.
2.System
Calls – These are the very important calls that are implemented
inside the linux Kernel.
When
a program makes a system call, the arguments are packaged and sent
to the kernel, which takes over execution of the program until the
call completes. A system call is not just an ordinary function call,
and a special procedure is required to transfer control to the
kernel.
The
system calls are the layer between the programs and kernel. Some
system calls can be very dangerious like shutdown the system ,
passing resources to process . These have restrictions on who
invokes these. Only a root user can has the access to invoke them but
as a part of working some non-user started process also can invoke
these calls.
Strace
is a command available in linux which helps in debugging and
troubleshooting the execution of a executable ( command or a
process).Strace also tells you what is going with a program at this
point. It can tell you what system calls the program is using and
whether they pass or fail.
Lets
use the Strace command and analyze the output. In the below example
we will use the hostname command along with strace and see how it
calls the kernel layer
Just
invoke the strace with hostname like
[root@vx111a
~]# strace hostname
execve("/bin/hostname",
["hostname"], [/* 47 vars */]) = 0
brk(0)
= 0x2190000
mmap(NULL,
4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7f4e18479000
access("/etc/ld.so.preload",
R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache",
O_RDONLY) = 3
fstat(3,
{st_mode=S_IFREG|0644, st_size=61740, ...}) = 0
mmap(NULL,
61740, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f4e18469000
close(3)
= 0
open("/lib64/libselinux.so.1",
O_RDONLY) = 3
read(3,
"\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0
X\240@?\0\0\0"..., 832) = 832
fstat(3,
{st_mode=S_IFREG|0755, st_size=124624, ...}) = 0
mmap(0x3f40a00000,
2221912, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) =
0x3f40a00000
mprotect(0x3f40a1d000,
2093056, PROT_NONE) = 0
mmap(0x3f40c1c000,
8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3,
0x1c000) = 0x3f40c1c000
mmap(0x3f40c1e000,
1880, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1,
0) = 0x3f40c1e000
close(3)
= 0
open("/lib64/libc.so.6",
O_RDONLY) = 3
read(3,
"\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\355a??\0\0\0"...,
832) = 832
fstat(3,
{st_mode=S_IFREG|0755, st_size=1912928, ...}) = 0
mmap(0x3f3f600000,
3737768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) =
0x3f3f600000
mprotect(0x3f3f787000,
2097152, PROT_NONE) = 0
mmap(0x3f3f987000,
20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3,
0x187000) = 0x3f3f987000
mmap(0x3f3f98c000,
18600, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1,
0) = 0x3f3f98c000
close(3)
= 0
open("/lib64/libdl.so.2",
O_RDONLY) = 3
read(3,
"\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340\r
??\0\0\0"..., 832) = 832
fstat(3,
{st_mode=S_IFREG|0755, st_size=22536, ...}) = 0
mmap(NULL,
4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7f4e18468000
mmap(0x3f3f200000,
2109696, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) =
0x3f3f200000
mprotect(0x3f3f202000,
2097152, PROT_NONE) = 0
mmap(0x3f3f402000,
8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3,
0x2000) = 0x3f3f402000
close(3)
= 0
mmap(NULL,
8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7f4e18466000
arch_prctl(ARCH_SET_FS,
0x7f4e184667a0) = 0
mprotect(0x3f40c1c000,
4096, PROT_READ) = 0
mprotect(0x3f3f987000,
16384, PROT_READ) = 0
mprotect(0x3f3f402000,
4096, PROT_READ) = 0
mprotect(0x3f3f01f000,
4096, PROT_READ) = 0
munmap(0x7f4e18469000,
61740) = 0
statfs("/selinux",
{f_type=0xf97cff8c, f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0,
f_files=0, f_ffree=0, f_fsid={0, 0}, f_namelen=255, f_frsize=4096}) =
0
brk(0)
= 0x2190000
brk(0x21b1000)
= 0x21b1000
open("/usr/lib/locale/locale-archive",
O_RDONLY) = 3
fstat(3,
{st_mode=S_IFREG|0644, st_size=99158752, ...}) = 0
mmap(NULL,
99158752, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f4e125d5000
close(3)
= 0
uname({sys="Linux",
node="vx111a.jas.com", ...}) = 0
fstat(1,
{st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL,
4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7f4e18478000
write(1,
"vx111a.jas.com\n", 15vx111a.jas.com) = 15
exit_group(0)
= ?
We
will see a couple of Screens as an Output.each line in the output is
a System call. For each call, the system call’s name is listed,
followed by its arguments (or abbreviated arguments, if they are very
long) and its return value
execve("/bin/hostname",
["hostname"], [/* 47 vars */]) = 0
The
first call is the execve call in which the first argument is the name
of the program to run; the second is its argument list, consisting of
only a single element; and the third is its environment list.
The
next lines are part of loading the standard C library for obtaining
the hostname.
The
uname system call is used to obtain the system’s hostname from the
kernel,
uname({sys="Linux",
node="vx111a.jas.com", ...}) = 0
In
the above uname call the strace helpfully labels the fields (sys and
node) of the structure argument. This structure is filled in by the
system call—Linux sets the sys field to the operating system name
and the node field to the system’s hostname like
write(1,
"vx111a.jas.com\n", 15) = 15
Finally,
the write system call produces output. Recall that file descriptor 1
corresponds to standard output. The third argument is the number of
characters to write, and the return value is the number of characters
that were actually written.
We
can analyze various system calls using the strace command available
in linux.