Download Exercise 2: Process-, Memory- and IO

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
Exercise 2: Process-, Memory- and
IO-Management
Introduction
In order to manage the system resources of a computer the control structure of an operating system (OS) is based on four entities: memory, processes, files and I/O. For
managing these entities the OS constructs and maintains tables of information about
each of them. In the following we provide an introduction, which should help to solve
the tasks given below.
The most requirements an OS has to fulfill are related to processes. Hence the management of processes is the fundamental task of OSs. The OS is responsible for scheduling
and dispatching processes for execution by the processor, allocating resources to processes and responding to requests of user processes. The aim of process management
is the efficient management of programs that are executed at the same time. Since a
processor can only execute one process at a time, this is achieved by switching the CPU
between multiple processes that are interrupted and resumed according to their priority.
A process is definded as a ’program in execution’ or in other words ’a unit of activity
characterized by the execution of a sequence of instruction, a current state, and an associated set of system resources’. There are three elements characterizing a process: program
code, associated data and a process control block (PCB). The process control block is a
data structure storing information that allows to uniquely characterize a process. This
includes a unique identifier, state, priority, a program counter, memory pointers, context
data, I/O status information and accounting information. The data structure of PCBs
is the key tool that enables the OS to provide multiprocessing, because it covers all necessary information to interrupt a running process and later resume execution as if the
interruption did not occurr. Since the information in a PCB is critical for the security of
an OS, they must be kept in an area of memory that is protected from normal user access.
However, usually each process has its own memory address space that is protected
from the access of other processes. Between processes exists a parent/child relationship.
A process can have multiple child processes but points to only one parent process. The
very first process, called init in UNIX, is started by the kernel at boot time and never
terminates.
As the creation of a process is usually caused by the user or an application, it can
also be useful to let one process (parent process) create another (child process) that runs
in parallel. This action is referred to as process spawning. Here, communication and
cooperation of processes become important. Enabling processes to share and exchange
information, protecting resources of each process from other processes and enabling syn-
1
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
chronization among processes represent difficult, security-related activities.
Many OS support threads as a further concept for managing task execution. By introducing threads, processes become more complex as presented so far. In general, a process
contains at least one but may also contain multiple threads, that can be executed independently but share the process’ resources. Operating systems which support multiple
threads within a single process are referred to as multithreaded environments. In these
systems the processor does not only switch between different processes, but also between
different threads. Processes are typically independent, have separate address spaces (at
least if no explicit methods are used, which require the intervention of the kernel) and
only interact through system-provided inter-process communication mechanisms (IPC).
Instead, threads within the same process share memory and files and can communicate
with each other without invoking the kernel. Thus, threads are able to access the same
datastructures without the need of further IPC. But the main advantage over processes
is the better performance of threads. Creation and termination of threads takes less time
and also switching between two threads within the same process. Thus, the concept of
threads is not only beneficial for multiprocessor systems. This comes with the cost of
more complex code1 which is much more difficult to debug and hence more vulnerable
to race-conditions and other security-related bugs.
0.1. Brief Introduction into the Python Programming Language
As the practical assignment requires coding work in python, this subsection aims to give a
very short introducing into the necessary parts of Python. (For a complete reference, see
the Python language reference [3].) Wikipedia [1] describes pythons design philosophy
as: it “emphasizes programmer productivity and code readability. Python’s core syntax
and semantics are minimalistic, while the standard library is large and comprehensive”
and as the syntax is minimalistic, it should be easy enough to learn even if you don’t have
any experiences before. For a more complete introduction into the python programming
language, see the Python tutorial [2].
0.1.1. Python-syntax
Preamble Every python file should let the system know which interpreter should be
used to execute this script. While on Windows (and DOS), this is traditionally done by
the file extension, on UNIX systems it is done by the first row of the file. If it contains a
“she-bang” (the combination #!) followed by a path to the interpreter and is executable,
the operating system will try to start the interpreter with the script as a parameter.
A typical python preamble would be:
1 #! / u s r / b i n / python
1
a programmer has to care about locking/unlocking of each part another thread may access
2
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
Statements: Python code usually has one statement per line. A statement may be
followed by a semicolon, but a simple newline is sufficient, so the semicolon may (and in
most cases is) omitted.
Comments: In Python, everything in a line following a # is treated as a comment.
Thus, the preamble in the last paragraph is interpreted as a comment by the interpreter,
too. As described before, it is not ignored by the system.
Example:
1 #! / u s r / b i n / python
2
3 #t h i s i s a comment
4
5 print ”huhu” # t h i s i s a comment too , b u t not t h e p r i n t !
print: The built in command print can be used, to print something to the standardoutput (stdout) followed by a newline. It is used in the previous section, thus the script
in the previous section would print out “huhu” onto the standard-console.
formatted print: Python’s print offers functionality similar to printf. The format
string is followed by a %-character and a tuple of parameters. An example should
illustrate this:
1 #! / u s r / b i n / python
2
3 t e m p e r a t u r e = 10
4 conditions = ” fine ”
5
6 print ” Weather today : i t i s %d d e g r e e s c e l s i u s , t h e c o n d i t i o n s
a r e %s ” % ( temperature , c o n d i t i o n s )
import: The import statement is used to include other “modules”, comparable to library. Functions of the module can be accessed after importing by the <modulename>.prefix. Library-functions important for the assignments are described in section 0.1.2.
An example for import is this:
1 #! / u s r / b i n / python
2
3 import s y s #t h i s i m p o r t s t h e ‘ ‘ s y s ’ ’ − module
4
5 s y s . s t d o u t . w r i t e ( ”huhu\n” )
6 #d o e s t h e same as t h e p r i n t s t a t e m e n t a bo ve
3
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
Variables and Data Types: Though python is a strong typed language, it uses dynamic
typing. Variables must not be declared, but can directly be assigned and take the type
of the assignment. Assignments are done by the = operator. Example:
1 #! / u s r / b i n / python
2
3 var = ” have you mooed today ? ” #t h i s i s a s t r i n g o b j e c t
4 var2 = 42 #i n t e g e r o b j e c t
5 var3 = E x c e p t i o n ( ) #new o b j e c t o f t y p e ” E x c e p t i o n ”
6 var2 = var #v ar2 i s now a s t r i n g o b j e c t , t o o
Operators on Variables: In python, every data type is a class, thus every variable (and
even static values) represents an object. The operators are defined by special functions
of that object, for example: var = 1 + 2 is the same as var = 1. add (2). As you
can see, the meaning of the operator can be different depending on the object type you
use it with. For standard number objects, this works as expected, for string-types (and
arrays, tuples, etc) the + operator does concatenation. You can redefine the meaning of
the operator (“operator overloading”) by creating a new class for example with another
add function. This could be useful if you want to implement matrix classes and +
should be the matrix addition, * should be the matrixmultiplication and / should be the
matrix inversion.
It is obvious that the types of the classes must be compatible. It does not make sense
to add a string to an integer. However, sometimes you want to concatenate the string
representation of an integer to a string. This isn’t possible directly (as the object types
aren’t compatible), the non-string object must be converted to its string representation
first. This can be done by the str function. Consider this example:
1 #! / u s r / b i n / python
2
3 var = ” have you mooed today ?\ nyes , ”
4 var2 = ” t i m e s ”
5 var3 = 5
6
7 print var + var3 . s t r ( ) + var2
8 print var + 7 . s t r ( ) + var2
Standard Classes:
Integer An integer number.
Float A floating-point number.
String The purpose of string is obvious. It can be accessed as string or as an array of
characters. Single characters can be accessed with st[5], substrings with st[5:8].
4
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
Tuple A tuple is a set of objects (components), bound to a single name. The set is
enclosed by parenthesis and its components are separated by comma. The components can be accessed by brackets.
Example:
1 #! / u s r / b i n / python
2
3 i = 5
4 s t = ” t h e l a z y dog jumps o v e r t h e . . . ”
5 pi = 3.1415947
6
7 tuple = ( i , st , pi )
8
9 print t u p l e [ 2 ] #p r i n t s o u t p i
Once assigned, it is not longer possible to change components. This is a major
restriction but gives a serious performance-boost.
Array An array is a set of objects (components) bound to a single name. The set is
enclosed by brackets and its components are separated by comma. Components
can be accessed like tuple-components.
Example:
1 #! / u s r / b i n / python
2
3 i = 5
4 s t = ” t h e l a z y dog jumps o v e r t h e . . . ”
5 pi = 3.1415947
6 roundpi = 3
7
8 array = [ i , st , pi ]
9
10 print a r r a y [ 2 ]
11 a r r a y [ 2 ] = r o u n d p i
12 print a r r a y [ 2 ]
Dictionary A dictionary is a set of key-value pairs. It manages relations between key
and value of a set of objects (components). The set is defined in the format:
key: value,... and is enclosed by brackets. Components are accessed by their
designated key.
Example:
#!/ u s r / b i n / python
d i c t i o n a r y = {” p i ” : 3 . 1 4 1 5 9 4 7 , ” s t ” : ” t h e l a z y dog jumps
over the . . . ” , ” i ”:5}
5
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
print dictionary [” pi ”]
Defining and Calling Functions: Functions are defined by two parts: a signature and
a function block. The signature consists of the def keyword, followed by a bracket, a list
of parameter names (possible with default values), a bracket and a colon. It is followed
by the function block which is a set of statements. A function is called by function name,
argument list separated by commas. If no arguments are given, the brackets are still
required!
Blocks: Unlike most other languages, python does not use parentheses to define block
starts and block ends. Blocks are entirely defined by indention2 , thus indention is very
important in python. Consider the following example:
1 #! / u s r / b i n / python
2
3 parameter = ” oink , o i n k ”
4
5 def f u n c ( parameter , parameter2 = ” t e s t ” ) :
6
print parameter2
7
print parameter
8
9 f u n c ( ” o p e r a t i n g system s e c u r i t y r o c k s ! ” )
It gives the output:
test
o p e r a t i n g system s e c u r i t y r o c k s !
While this:
1 #! / u s r / b i n / python
2
3 parameter = ” oink , o i n k ”
4
5 def f u n c ( parameter , parameter2 = ” t e s t ” ) :
6
print parameter2
7 print parameter #n o t e t h a t t h i s s t a t e m e n t i s not l o n g e r
indented .
8
9 f u n c ( ” o p e r a t i n g system s e c u r i t y r o c k s ! ” )
gives:
2
usual coding-convention defines 4 spaces for indention
6
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
test
oink , o i n k
Returning Values from Functions: A function can return an object. This is done by
the return-statement. After the return-statement, the program-flow leaves the function
and returns to the calling statement. Example:
1
2
3
4
5
6
7
8
#! / u s r / b i n / python
def f u n c ( ) :
print ” i am a f u n c t i o n ! ”
return ”Have you mooed today ? ”
x = func ( )
print x
gives
i am a f u n c t i o n !
Have you mooed today ?
Conditional Code Sometimes you need conditional codes. The most important example of conditional code in python is the if statement, possibly followed by an elif
(shorthand for else if) and/or an else-statement. The exact syntax is best shown in an
example:
1 #! / u s r / b i n / python
2
3 x = 1
4
5 i f x == 1 :
6
print ” f i r s t b l o c k : ”
7
print ”x = 1 ”
8 elif x > 1:
9
print ” s e c o n d b l o c k : ”
10
print ”x > 1 ”
11 e l s e :
12
print ” t h i r d b l o c k : ”
13
print ”x < 1 ”
Loops: Python has two different types of loops:
7
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
for-in-loop: The for in loop is a loop that iterates through objects. Important iterable
objects are strings, arrays, tuples and dictionaries. An example of a for in loop is:
1 #! / u s r / b i n / python
2
3 x = ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 ) # t u p l e w i t h 10 numbers
4
5 for i in x : # i t e r a t e s o v e r e v e r y component o f t h e t u p l e . . .
6
print ” l o o p i n g . . . ”
7
print i
while-loop: The Python while loop is a classical while-loop. It works as the following:
1 #! / u s r / b i n / python
2
3 x = 100
4
5 while x > 0 :
6
print x
7
print x −= 1 # e q u a l t o x = x − 1
range([start], stop, [step]), xrange([start], stop, [range]): The range/xrange-function
is a built in function, that generates iterable objects containing integer-ranges of numbers. Calling is quite obvious. Start is the start value (the first number in the range) (0 if
omitted), stop (the first number not in the range) is the stop value (cannot be omitted),
step defines the interval between the numbers (1 if omitted, must be an integer value).
The difference between range and xrange is that range returns a tuple, while xrange returns an iterable function. Thus, if you do range(10000000000), your tuple takes quite
some time to generate and uses large amounts of memory, while xrange(10000000000)
just returns an iterable object. While this is different, both works equivalent in for-loops.
Example:
1 #! / u s r / b i n / python
2
3 x = range ( 0 , 4 , 2 )
4 for i in x :
5
print i
gives
0
2
8
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
0.1.2. Python Modules
This part introduces some additional functions that should enable you to complete your
assignment. Additional informations of these functions are given in the appendix. A
complete documentation of the standard library of modules is the Python library reference [4].
os: The os-module provides the interface to the operating-system. It provides wrappers
to syscalls (like fork) and other advanced operating system functions (like directory
working).
os.fork: This is the python-implementation of the fork syscall. It creates a new process
clone and runs it independently. It returns 0 to the child process, and the pid of the
child to the parent process. It is called via the os. prefix of the module and the name
of the function + brackets (i.e. os.fork()). It takes no arguments!
os.wait: This is the python implementation of the wait syscall. It waits for a child
process to exit and retrieves it’s exit status. It takes no arguments!
os.getpid: This function retrieves the current process-id of the process calling from the
system. Example:
1 #! / u s r / b i n / python
2 import o s
3
4 pid = os . getpid ( )
5 print p i d
os.system: - system(param-string): The system call starts the default shell and lets
it execute the parameter-string. An example should make this clear:
1 #! / u s r / b i n / python
2
3 import o s
4
5 o s . system ( ” echo t h i s i s a t e s t > f i l e ” )
6 o s . system ( ” c a t f i l e ” )
7 o s . system ( ”rm f i l e ” )
It does the following: First creates a “file” named “file” and echos “this is a test” in it,
then prints out the contents of the “file” using the cat command and finally removes
the “file” with the rm command.
time: The time module provides an interface to all time-related functions of the system.
For instance it converts different time formats.
9
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
time.sleep: This function is the only function of the time module relevant for this
assignment. The signature is: sleep(secs). It stops the program flow for secs seconds.
0.1.3. How to Write and Execute Python Scripts
Python scripts can either be written in any texteditor or directly tested in the python
shell.
Write scripts with a text-editor: Open your favorite texteditor (for example kate [5])
and write the script. Make sure not to forget the preamble 0.1.1. After saving the script,
you must mark it executable by executing chmod +x <filename>. Now you can execute
it with ./<filename> in the directory you saved the script.
Test in the Python-shell:
Type python on the shell. It should give you something like:
Python 2 . 5 . 2 ( r 2 5 2 : 6 0 9 1 1 , Oct 7 2 0 0 8 , 1 2 : 4 5 : 4 9 )
[GCC 4 . 3 . 1 ] on l i n u x 2
Type ” h e l p ” , ” c o p y r i g h t ” , ” c r e d i t s ” o r ” l i c e n s e ” f o r more
information .
>>>
You can type your statements into the console. Single statements are evaluated after
typing enter, blocks are evaluated after finishing the statement. You can exit the shell
with the exit() statement. Example:
immo@wok ˜ $ python
Python 2 . 5 . 2 ( r 2 5 2 : 6 0 9 1 1 , Oct 7 2 0 0 8 , 1 2 : 4 5 : 4 9 )
[GCC 4 . 3 . 1 ] on l i n u x 2
Type ” h e l p ” , ” c o p y r i g h t ” , ” c r e d i t s ” o r ” l i c e n s e ” f o r more
information .
>>> f o r i i n r a n g e ( 1 , 5 ) : #range−f u n c t i o n r e t u r n s t u p l e
(1 ,2 ,3 ,4 ,5)
...
print i
...
1
2
3
4
>>> e x i t ( )
immo@wok ˜ $
10
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
1. Theoretical assignments:
1.1. Python-Questions ( π1 Points)
You should be able to answer all of these questions before starting the practical exercises. Use to disambiguate the indention!
1. How do you define a tuple?
2. Whats the difference between an array and a dictionary?
3. Implement (on paper) a small Python-script, that prints out your name!
4. Implement (on paper) a small Python-script, that counts from 0 to 10. Use a forloop, conditional code and the range-function! The output should be the following:
0 is
1
2
3 is
4
5
6 is
7
8
9 is
10
0 mod 3
0 mod 3
0 mod 3
0 mod 3
5. You have an integer-variable r, containing a random number. Give two possible
print-statements to print “our random number is -insert content of the random
number here-”
1.2. Process-Management (1/2 Point)
1. What is a process?
2. Why does someone want multiple processes? Give examples!
3. What information about processes are necessary for the OS to manage them?
4. What is the difference between processes and threads?
5. Consider the following python-code:
1 #! / u s r / b i n / python
2
3 import os , time
11
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
4 n=5
5
6 fo r i in xrange ( n ) :
7
os . f o r k ( )
8
9 time . s l e e p ( 1 0 0 )
a) How many processes will sleep in line 9?
b) How many processes will sleep in line 9 if n would be 10?
c) Develop a formula for calculating the number of processes for all n ∈ N.
Explain the formula!
1.3. Memory Management (1 Point)
1. What is swapping and what is its purpose?
2. Explain the paging-mechanism.
3. Explain why it is a security-problem if some user has read-access to the swapfile!
4. Why can it also be a problem if some user has write-access?
5. Why do OS use virtual addressing?
6. Describe the process-memory-layout on a general x86-system.
7. Where is the stack and what is the stack used for?
8. What is the heap, what does the heap?
9. Consider the following source-code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <s t r i n g . h>
#include <s t d i n t . h>
#include < s t d l i b . h>
int f u n c ( char∗ s , u i n t 1 6 t i ) {
return ∗ s + i ;
}
int main ( void ) {
char f o o [ 1 0 ] , ∗ bar = m a l l o c ( 1 5 ) ;
uint16 t foobar ;
u i n t 3 2 t blah ;
12
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
15
16
17
18
19
20
21
22 }
s t r c p y ( foo , ” 01234567 ” ) ;
foobar = 65532;
b l a h = f u n c ( foo , f o o b a r ) ;
/∗ THIS IS THE INTERESTING POSITION ∗/
return 0 ;
Let the start-address of the stack of the virtual memory for the process be 0x000f0000.
Assume that it is an IA-32 (x86)-architecture and sizeof(void*) is 4 (which
means that the size of a pointer is 4 bytes). Assume further the variables are pushed
on the stack in the same order as they are declared and assume no padding!3
a) In which direction does the stack grow?
b) Where points bar? What is the address of the first byte of bar (==&bar)?
c) How does the address of foo change in strcpy?
d) What is the address of the first byte of blah (== &blah)?
10. On Linux, if a process tries to access memory it does not belong to it, the kernel
sends signal 11 - SIGSEGV and the access fails. The standard behaviour on receiving SIGSEGV is to print out “segmentation fault” and exit the process. Explain
why this is done and what effects it would have if it have not been implemented.
Points)
1.4. I/O Management ( π−2
2π
1. Distinguish the tree techniques for performing I/O from each other: Programmed
I/O, Interrupt-driven I/O and DMA.
2. Why is I/O buffering important? Mention the different buffering-schemes that are
supported by OSs and point out their differences.
3. What is the difference between block-oriented devices and stream-oriented devices?
Give 1 examples of each.
2. Practical Assignments (
P
1 Point)
2.1. Linux
2.1.1. Process Management
1. Read the process table, find out the process id of a running python shell.
3
Note that usual compiler will do padding and possible reorganize, so calculate the solution, do not try
it out!
13
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
2. Write a basic python-script that creates a child-process. Both processes (the parent
and the child) shall print out its process-id. The parent-process shall wait for its
child to exit and then print something extra.
3. Check whether this program really starts a new process using the ps4 command.
4. Now let the child do some work! Copy the big buck bunny Video from the server
/insert/the/path/here to other/path/here. This can be done by using konqueror (doubleclick the link on the desktop). The Username is labor and the password labor1. Let the child execute mencoder to recode the video “big buck bunny.mkv”
to the h264 codec 5 . This task requires a lot of computations. Check that the parent process is still usable while the child does lots of work. Explain why it isn’t
blocked!
5. Change the script, so that one “global” variable is used in both processes, alter
this variable in one process! Has it changed in the other? explain Why/why-not!
2.1.2. Memory Management
1. Use python to place some string in the memory. (start the python shell and assign
a string to some variable)
2. Find out the memory-address using hex(id(str)).
3. Use the hexeditor hexedit to find it in /dev/mem. With the “return”-key, you
can jump to the address. Do you find the expected string? Explain!
2.2. Windows
2.2.1. Process Management
1. Run the Process Explorer utility on the desktop. (Process Explorer is a Windows
Sysinternals Tool free for download.)
2. Find out which processes are currently running on your system. (No notes needed.)
3. Now click on the System Information button to see details of CPU activity. How
many processes and how many threads are running?
4. Start multiple notepad sessions in the different ways listed below. Use the Process
Explorer to observe the differences. Are there differences with respect to the
priviledges?
• Start\All Programs\Accessories\Notepad
• start notepad using Command Prompt
4
5
prints out the current process-list, for further information see man ps
os.system("mencoder -ovc x264 -o -oac pcm -x264encopts bitrate=1000 big buck bunny.h264
big buck bunny.mkv")
14
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
• run Command Prompt as administrator (right click Command Promp on the
start menu and select ”run as administrator”) and execute
s c h t a s k s / C r e a t e /SC e i n m a l /ST 1 0 : 4 1 /TN Test
/TR notepad
(Replace the time 10:41 with the time of your system adding two or three
minutes.)
5. How does the number of threads and the assigned virtual space changes, during
entering some code, saving or opening a notepad document? (Just note the general
trends.)
6. Start notepad as administrator and try to open C:\Test\security-log.txt.
7. Create a new file ”malware.bat” in C:\Test using notepad and insert the following
code.
@ECHO OFF
C:
CD \TEST
ECHO 1 >> s e c u r i t y −l o g . t x t
PAUSE
8. Open Command Prompt as administrator and check if the size of the file securitylog.txt changes by entering:
a t 1 0 : 4 1 ”C: \ Test \ malware . bat ”
(Don’t forget to replace the time!)
9. Why does this work? What does this mean for the security of Windows Vista?
2.3. Bonus assignment (+1 Point)
We gathered the contents of a machines memory using DMA and firewire. There was
no time to check on the machine directly, so the only thing we have is the memorydump. Analyse the memory dump of this machine provided in Desktop/Exercise
Data/Exercise 2/memory.dump.
1. Which operating system was this machine running?
2. Search for the processes that have been running at the time when the image was
made.
3. Reconstruct the users and their passwords.
15
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
Appendix
The following information is not mandatory for the assignment. It is meant as background knowledge, if you are interested in one particular detail or have difficulties understand the things above. Many of the details included in the appendix are not comprehensible given only the information given in the lecture and in the introducion.
A. Syscalls
This is the (complete) documentation of selected syscalls for the linux operating system.
Since it is real world documentation, it is quite not easy to understand.
A.1. fork - create a child process
description: fork creates a new process by duplicating the calling process. The new
process, referred to as the child, is an exact duplicate of the calling process, referred to
as the parent, except for the following points:
• The child has its own unique process ID, and this PID does not match the ID of
any existing process group (see man setpgid).
• The child’s parent process ID is the same as the parent’s process ID.
• The child does not inherit its parent’s memory locks (mlock, mlockall).
• Process resource utilizations (getrusage) and CPU time counters (times) are reset
to zero in the child.
• The child’s set of pending signals is initially empty
• The child does not inherit semaphore adjustments from its parent
• The child does not inherit record locks from its parent
• The child does not inherit timers from its parent
• The child does not inherit outstanding asynchronous I/O operations from its parent
The process attributes in the preceding list are all specified in POSIX.1-2001. The
parent and child also differ with respect to the following Linux-specific process attributes:
• The child does not inherit directory change notifications (dnotify) from its parent
(see the description of F NOTIFY in the man-page of fcntl).
• The prctl PR SET PDEATHSIG setting is reset so that the child does not receive a
signal when its parent terminates.
• Memory mappings that have been marked with the madvise MADV DONTFORK flag
are not inherited across a fork.
16
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
• The termination signal of the child is always SIGCHLD (see the manpage of clone).
Note the following further points:
• The child process is created with a single thread – the one that called fork.
The entire virtual address space of the parent is replicated in the child, including the states of mutexes, condition variables, and other pthreads objects; the use
of pthread atfork may be helpful for dealing with problems that this can cause.
• The child inherits copies of the parent’s set of open file descriptors. Each file
descriptor in the child refers to the same open file description (see man open) as
the corresponding file descriptor in the parent. This means that the two descriptors
share open file status flags, current file offset, and signal-driven I/O attributes (see
the description of F SETOWN and F SETSIG in man fcntl).
• The child inherits copies of the parent’s set of open message queue descriptors (see
man mq overview). Each descriptor in the child refers to the same open message
queue description as the corresponding descriptor in the parent. This means that
the two descriptors share the same flags (mq flags).
• The child inherits copies of the parent’s set of open directory streams (see man
opendir). POSIX.1-2001 says that the corresponding directory streams in the
parent and child may share the directory stream positioning; on Linux/glibc they
do not.
return value: On success, the PID of the child process is returned in the parent, and
0 is returned in the child. On failure, -1 is returned in the parent, no child process is
created, and errno is set appropriately.
errors:
EAGAIN fork cannot allocate sufficient memory to copy the parent’s page tables and
allocate a task structure for the child.
EAGAIN It was not possible to create a new process because the caller’s RLIMIT NPROC
resource limit was encountered. To exceed this limit, the process must have either
the CAP SYS ADMIN or the CAP SYS RESOURCE capability.
ENOMEM fork failed to allocate the necessary kernel structures because memory is
tight.
conforming to:
SVr4, 4.3BSD, POSIX.1-2001.
17
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
notes: Under Linux, fork is implemented using copy-on-write pages, so the only penalty
that it incurs is the time and memory required to duplicate the parent’s page tables,
and to create a unique task structure for the child.
Since version 2.3.3, rather than invoking the kernel’s fork system call, the glibc fork
wrapper that is provided as part of the NPTL threading implementation invokes clone
with flags that provide the same effect as the traditional system call. The glibc wrapper
invokes any fork handlers that have been established using pthread atfork.
A.2. exit - terminate the calling process
description: The function exit terminates the calling process ”immediately”. Any
open file descriptors belonging to the process are closed; any children of the process are
inherited by process 1, init, and the process’s parent is sent a SIGCHLD signal.
The value status is returned to the parent process as the process’s exit status, and
can be collected using one of the wait family of calls.
return value: This function does not return.
conforming to:
SVr4, POSIX.1-2001, 4.3BSD.
notes: For a discussion on the effects of an exit, the transmission of exit status, zombie
processes, signals sent, etc., see the manpage of exit.
The function exit is like exit, but does not call any functions registered with atexit
or on exit. Whether it flushes standard I/O buffers and removes temporary files created
with tmpfile is implementation-dependent. On the other hand, exit does close open
file descriptors, and this may cause an unknown delay, waiting for pending output to
finish. If the delay is undesired, it may be useful to call functions like tcflush before
calling exit. Whether any pending I/O is canceled, and which pending I/O may be
canceled upon exit() is implementation-dependent.
A.3. wait, waitpid, waitid - wait for process to change state
description:
All of these system calls are used to wait for state changes in a child of
the calling process, and obtain information about the child whose state has changed. A
state change is considered to be: the child terminated; the child was stopped by a signal;
or the child was resumed by a signal. In the case of a terminated child, performing a
wait allows the system to release the resources associated with the child; if a wait is not
performed, then the terminated child remains in a “zombie” state (see NOTES below).
18
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
If a child has already changed state, then these calls return immediately. Otherwise
they block until either a child changes state or a signal handler interrupts the call (assuming that system calls are not automatically restarted using the SA RESTART flag of
sigaction). In the remainder of this page, a child whose state has changed and which
has not yet been waited upon by one of these system calls is termed waitable.
wait and waitpid The wait system call suspends execution of the calling process until
one of its children terminates. The call wait(&status); is equivalent to:
w a i t p i d ( −1 , &s t a t u s , 0 ) ;
The waitpid system call suspends execution of the calling process until a child specified by pid argument has changed state. By default, waitpid waits only for terminated
children, but this behavior is modifiable via the options argument, as described below.
The value of pid can be:
< -1 meaning wait for any child process whose process group ID is equal to the absolute
value of pid.
-1 meaning wait for any child process.
0 meaning wait for any child process whose process group ID is equal to that of the
calling process.
> 0 meaning wait for the child whose process ID is equal to the value of pid.
The value of options is an OR of zero or more of the following constants:
WNOHANG return immediately if no child has exited.
WUNTRACED also return if a child has stopped (but not traced via ptrace). Status for
traced children which have stopped is provided even if this option is not specified.
WCONTINUED (since Linux 2.6.10) also return if a stopped child has been resumed
by delivery of SIGCONT.
(For Linux-only options, see below.)
The WUNTRACED and WCONTINUED options are only effective if the SA NOCLDSTOP flag
has not been set for the SIGCHLD signal (see sigaction).
19
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
If status is not NULL, wait and waitpid store status information in the int to which it
points. This integer can be inspected with the following macros (which take the integer
itself as an argument, not a pointer to it, as is done in wait and waitpid!):
WIFEXITED(status) returns true if the child terminated normally, that is, by calling
exit or exit, or by returning from main().
WEXITSTATUS(status) returns the exit status of the child. This consists of the least
significant 8 bits of the status argument that the child specified in a call to exit
or exit or as the argument for a return statement in main(). This macro should
only be employed if WIFEXITED returned true.
WIFSIGNALED(status) returns true if the child process was terminated by a signal.
WTERMSIG(status) returns the number of the signal that caused the child process to
terminate. This macro should only be employed if WIFSIGNALED returned true.
WCOREDUMP(status) returns true if the child produced a core dump. This macro
should only be employed if WIFSIGNALED returned true. This macro is not specified
in POSIX.1-2001 and is not available on some Unix implementations (e.g., AIX,
SunOS). Only use this enclosed in #ifdef WCOREDUMP ... #endif.
WIFSTOPPED(status) returns true if the child process was stopped by delivery of a
signal; this is only possible if the call was done using WUNTRACED or when the child
is being traced (see manpage of ptrace).
WSTOPSIG(status) returns the number of the signal which caused the child to stop.
This macro should only be employed if WIFSTOPPED returned true.
WIFCONTINUED(status) (since Linux 2.6.10) returns true if the child process was
resumed by delivery of SIGCONT.
The waitid() system call (available since Linux 2.6.9) provides more precise control over
which child state changes to wait for.
The idtype and id arguments select the child(ren) to wait for, as follows:
idtype == P PID Wait for the child whose process ID matches id.
idtype == P PGID Wait for any child whose process group ID matches id.
idtype == P ALL Wait for any child; id is ignored.
The child state changes to wait for are specified by ORing one or more of the following
flags in options:
20
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
WEXITED Wait for children that have terminated.
WSTOPPED Wait for children that have been stopped by delivery of a signal.
WCONTINUED Wait for (previously stopped) children that have been resumed by
delivery of SIGCONT.
The following flags may additionally be ORed in options:
WNOHANG As for waitpid.
WNOWAIT Leave the child in a waitable state; a later wait call can be used to again
retrieve the child status information.
Upon successful return, waitid fills in the following fields of the siginfo t structure
pointed to by infop:
si pid The process ID of the child.
si uid The real user ID of the child. (This field is not set on most other implementations.)
si signo Always set to SIGCHLD.
si status Either the exit status of the child, as given to exit (or exit), or the signal
that caused the child to terminate, stop, or continue. The si code field can be
used to determine how to interpret this field.
si code Set to one of: CLD EXITED (child called exit); CLD KILLED (child killed by
signal); CLD STOPPED (child stopped by signal); or CLD CONTINUED (child continued
by SIGCONT).
If WNOHANG was specified in options and there were no children in a waitable state, then
waitid returns 0 immediately and the state of the siginfo t structure pointed to by
infop is unspecified. To distinguish this case from that where a child was in a waitable
state, zero out the si pid field before the call and check for a non-zero value in this field
after the call returns.
return value:
wait on success, returns the process ID of the terminated child; on error, -1 is returned.
waitpid on success, returns the process ID of the child whose state has changed; if
WNOHANG was specified and one or more child(ren) specified by pid exist, but have
not yet changed state, then 0 is returned. On error, -1 is returned.
waitid returns 0 on success or if WNOHANG was specified and no child(ren) specified by id
has yet changed state; on error, -1 is returned.
Each of these calls sets errno to an appropriate value in the case of an error.
21
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
errors:
ECHILD (for wait) The calling process does not have any unwaited-for children.
ECHILD (for waitpid or waitid) The process specified by pid (waitpid) or idtype and
id (waitid) does not exist or is not a child of the calling process. (This can happen
for one’s own child if the action for SIGCHLD is set to SIG IGN. See also the Linux
Notes section about threads.)
EINTR WNOHANG was not set and an unblocked signal or a SIGCHLD was caught.
EINVAL The options argument was invalid.
conforming to:
SVr4, 4.3BSD, POSIX.1-2001.
notes: A child that terminates, but has not been waited for becomes a “zombie”. The
kernel maintains a minimal set of information about the zombie process (PID, termination status, resource usage information) in order to allow the parent to later perform a
wait to obtain information about the child. As long as a zombie is not removed from
the system via a wait, it will consume a slot in the kernel process table, and if this table
fills, it will not be possible to create further pro- cesses. If a parent process terminates,
then its “zombie” children (if any) are adopted by init, which automatically performs
a wait to remove the zombies.
POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG IGN or the
SA NOCLDWAIT flag is set for SIGCHLD (see manpage of sigaction), then children that
terminate do not become zombies and a call to wait or waitpid will block until all
children have terminated, and then fail with errno set to ECHILD. (The original POSIX
standard left the behavior of setting SIGCHLD to SIG IGN unspecified. Note that even
though the default disposition of SIGCHLD is ”ignore”, explicitly setting the disposition
to SIG IGN results in different treatment of zombie process children.) Linux 2.6 conforms
to this specification. However, Linux 2.4 (and earlier) does not: if a wait or waitpid
call is made while SIGCHLD is being ignored, the call behaves just as though SIGCHLD
were not being ignored, that is, the call blocks until the next child terminates and then
returns the process ID and status of that child.
linux notes: In the Linux kernel, a kernel-scheduled thread is not a distinct construct
from a process. Instead, a thread is simply a process that is created using the Linuxunique clone system call; other routines such as the portable pthread create call are
implemented using clone. Before Linux 2.4, a thread was just a special case of a process,
and as a consequence one thread could not wait on the children of another thread, even
when the latter belongs to the same thread group. However, POSIX prescribes such
functionality, and since Linux 2.4 a thread can, and by default will, wait on children of
other threads in the same thread group.
22
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
The following Linux-specific options are for use with children created using clone;
they can- not be used with waitid:
WCLONE Wait for “clone” children only. If omitted then wait for “non-clone” children only. (A ”clone” child is one which delivers no signal, or a signal other than
SIGCHLD to its parent upon termination.) This option is ignored if WALL is
also specified.
WALL (since Linux 2.4) Wait for all children, regardless of type (“clone” or “nonclone”).
WNOTHREAD (since Linux 2.4) Do not wait for children of other threads in the
same thread group. This was the default before Linux 2.4.
example: The following program demonstrates the use of fork and waitpid. The program creates a child process. If no command-line argument is supplied to the program,
then the child suspends its execution using pause, to allow the user to send signals
to the child. Otherwise, if a command-line argument is supplied, then the child exits
immediately, using the integer supplied on the command line as the exit status. The
parent process executes a loop that monitors the child using waitpid, and uses the W*()
macros described above to analyze the wait status value.
The following shell session demonstrates the use of the program:
$ . / a . out &
C h i l d PID i s 32360
[ 1 ] 32359
$ k i l l −STOP 32360
s to p pe d by s i g n a l 19
$ k i l l −CONT 32360
continued
$ k i l l −TERM 32360
k i l l e d by s i g n a l 15
[ 1 ] + Done
$
1
2
3
4
5
6
#include
#include
#include
#include
. / a . out
<s y s / w a i t . h>
< s t d l i b . h>
<u n i s t d . h>
<s t d i o . h>
int main ( int argc , char ∗ argv [ ] )
23
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
7 {
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 }
p i d t cpid , w ;
int s t a t u s ;
cpid = fork () ;
i f ( c p i d == −1) {
perror (” fork ”) ;
e x i t (EXIT FAILURE) ;
}
i f ( c p i d == 0 ) {
/∗ Code e x e c u t e d by c h i l d ∗/
p r i n t f ( ” C h i l d PID i s %l d \n” , ( long ) g e t p i d ( ) ) ;
i f ( a r g c == 1 )
pause ( ) ;
/∗ Wait f o r s i g n a l s ∗/
e x i t ( a t o i ( argv [ 1 ] ) ) ;
} else {
/∗ Code e x e c u t e d by p a r e n t ∗/
do {
w = w a i t p i d ( cpid , &s t a t u s , WUNTRACED | WCONTINUED) ;
i f (w == −1) {
perror ( ” waitpid ” ) ;
e x i t (EXIT FAILURE) ;
}
i f (WIFEXITED( s t a t u s ) ) {
p r i n t f ( ” e x i t e d , s t a t u s=%d\n” , WEXITSTATUS( s t a t u s ) ) ;
} e l s e i f (WIFSIGNALED( s t a t u s ) ) {
p r i n t f ( ” k i l l e d by s i g n a l %d\n” , WTERMSIG( s t a t u s ) ) ;
} e l s e i f (WIFSTOPPED( s t a t u s ) ) {
p r i n t f ( ” s t o p p e d by s i g n a l %d\n” , WSTOPSIG( s t a t u s ) ) ;
} e l s e i f (WIFCONTINUED( s t a t u s ) ) {
p r i n t f ( ” c o n t i n u e d \n” ) ;
}
} while ( ! WIFEXITED( s t a t u s ) && ! WIFSIGNALED( s t a t u s ) ) ;
e x i t (EXIT SUCCESS) ;
}
A.4. getpid, getppid - get process identification
description: getpid returns the process ID of the calling process. (This is often used
by routines that generate unique temporary filenames.)
24
RUHR-UNIVERSITY BOCHUM
Exercises Operating System Security
WS2008/09
Chair for
System Security
getppid returns the process ID of the parent of the calling process.
errors: These functions are always successful.
confirming to: POSIX.1-2001, 4.3BSD, SVr4
References
[1] Python (programming language)
(programming_language)
http://en.wikipedia.org/wiki/Python_
[2] Python Tutorial http://docs.python.org/tutorial/
[3] Python Language Reference http://docs.python.org/reference/
[4] Python Standard Library http://docs.python.org/library/
[5] The Kate Text Editor http://kate-editor.org/
[6] The wikipedia malloc-page http://en.wikipedia.org/wiki/Malloc
25