Lass mich das mal enträzeln:
1 | daniel@mouse:~$ ps -ft pts/9
|
2 | UID PID PPID C STIME TTY TIME CMD
|
3 | daniel 25839 25836 0 16:27 pts/9 00:00:00 -bash
|
4 | daniel 26043 25839 0 16:29 pts/9 00:00:00 ps -ft pts/9
|
5 | daniel@mouse:~$ who -all -H
|
6 | NAME LINE TIME IDLE PID COMMENT EXIT
|
7 | 2017-07-28 00:28 372 id=si term=0 exit=0
|
8 | system boot 2017-07-28 00:28
|
9 | run-level 2 2017-07-28 00:28 last=S
|
10 | 2017-07-28 00:28 2334 id=l2 term=0 exit=0
|
11 | LOGIN tty1 2017-07-31 17:41 19500 id=1
|
12 | LOGIN tty2 2017-07-28 00:28 3197 id=2
|
13 | LOGIN tty3 2017-07-28 00:28 3198 id=3
|
14 | LOGIN tty4 2017-07-28 00:28 3199 id=4
|
15 | LOGIN tty5 2017-07-28 00:28 3200 id=5
|
16 | LOGIN tty6 2017-07-28 00:28 3201 id=6
|
17 | daniel - pts/9 2017-08-01 16:27 . 25815 (10.60.10.140)
|
18 | daniel@mouse:~$ pstree -sp 25839
|
19 | ?(1)───?(25836)───bash(25839)───pstree(26066)
|
20 | daniel@mouse:~$ su -c "pstree -sp 25839"
|
21 | Password:
|
22 | init(1)───sshd(3128)───sshd(25815)───sshd(25836)───bash(25839)───su(26166)───pstree(26191)
|
Zunächst zur Ausgabe von 'pstree -sp 25839', normalerweise wäre diese
identisch zu 'su -c "pstree -sp 25839"' oder 'sudo pstree -sp 25839',
aber auf meinem System habe ich /proc in der fstab mittels 'hidepid=2'
gemounted, womit jeder benutzer ausser root nur seine eigenen Prozesse
sieht.
Der ssh Prozess 3128 wartet auf Verbindungen. Nach dem Verbindungsaufbau
wird mit fork eine Kopie des ssh prozesses erstellt (hier mit pid
25815), der sich um die Verbindung kümmert. Dieser Prozess prüft dann
mit pam ob die Logindaten stimmen, und erstellt mit pam_open_session
eine neue pam session. Diese siehst du beim Befehl 'who -all -H'.
Nachdem sshd(25815) pam_open_session aufgerufen hat, erstellt es mit
fork eine weitere Kopie von sich, die dann mit setuid und setgid zum
eigentlichen Benutzer wechselt.
Es gibt bei jedem Prozess 3 uids und 3 gids: real, effective und saved.
Die effective uid/gid werden bei den Berechtigungschecks verwendet, um
zu prüfen ob der Zugriff auf eine Ressource erlaubt ist. Die saved
uid/gid ist vorallem bei setuid/setgid programmen relevant, und kann
genutzt werden um nur temporär mittels seteuid die effective uid zu
ändern und danach wieder auf die saved uid zu setzen, aber versuche dies
nicht, denn es ist sinnlos falls der Prozess kompromittiert würde. Die
real uid ist der Benutzer, als welcher ein Prozess gestartet wurde. Wenn
man ein setuid Programm hat, werden die saved uid und die effective uid
auf den Benutzer der Programmdatei gesetzt, und die Real uid bleibt der
Benutzer der die Datei aufgerufen hat. Wenn man dann setuid mit der real
uid aufruft, werden die effective und saved uid auf die real uid
gesetzt*, und es ist unmöglich mit setuid wieder mehr Berechtigungen zu
erlangen. Dies nennt man "to drop privileges", also "Berechtigungen
wegwerfen". Im falle von pam und ssh wäre demnach die real uid der
PAM_USER, also der Benutzer zu dem gewechselt wird, und die effective
uid wäre der Benutzer des ssh daemon, before mit setuid auch diese zum
PAM_USER, der real uid, geändert wird. Für die gid vehält sich alles
analog.
Nachdem der Prozess sshd(25836) seine Berechtigungen abgegeben hat, wird
ein pseudo terminal allociiert, und das eigentliche Programm wird
gestarted. Dies geschieht mittels open, fork und exec. Wenn man
/dev/ptmx öffnet, wird ein pseudoterminal erstellt. Man erhält einen
filedescriptor auf ein Pseudo-terminal master device (ptm), und ein
Pseudo terminal slave device (pts) wird in /dev/pts/ erstellt.
Mit fork wird eine weitere Kopie des Prozesses erstellt. Dieser hatte
hier pid 25839. In diesem Prozess wird das Pseudo-terminal slave device
(pts) als stdin (file descriptor 0) und stdout (file descriptor 1)
geöffnet. Deshalb siehst du hier in diesem Beispiel bei 'ps -ft pts/9'
den Prozess bash(25839). bash, weil nach dem oben beschriebenen bash mit
exec() aufgerufen wird. exec überschreibt den momentanen Prozess mit dem
angegebenen Programm, aber einige Dinge, wie die pid, die environment
variablen**, und die file-descriptoren*** bleiben erhalten.
pts und ptm devices verhalten sich ähnlich wie fifos oder pipes. Was
beim einen geschrieben wird kommt beim anderen wieder raus. Jedoch haben
beide noch device-spezifische ioctls.
* Ausser wenn die saved uid root und die effective uid nicht auf die
real uid gesetzt werden soll, oder eine inheritable capability gesetzt
wird, dann wird die saved uid durch setuid nicht zurückgesetzt. Ich bin
mir nicht sicher, ob letzteres ein bug in linux ist, auch wenn es
trivial ist root zu erlangen wenn man eine capabillity hat. Ich empfehle
deshalb setresuid und setresgid statt setuid, setgid, setresuid und
setregid zu verwenden.
** Ausser einige wie z.B. LD_PRELOAD bei setuid Programmen, je nach
libc.
*** Ausser solche bei denen das FD_CLOEXEC flab gesetzt wurde.