malloc() + gpg

Γιώργος Κεραμίδας keramida at ceid.upatras.gr
Tue Mar 11 18:28:01 EET 2003


On 2003-03-11 09:28, Alexandros Papadopoulos <apapadop at cmu.edu> wrote:
> On Tuesday 11 March 2003 06:48, Γιώργος Κεραμίδας wrote:
> > > To gpg είναι suid root.  Υποτίθεται ότι αν δεν μπορεί να
> > > lockάρει τη μνήμη, παραπονιέται με το γνωστό "WARNING: Using
> > > insecure memory".
> >
> > Υποτίθεται ότι η mlock() είναι μόνο για τον superuser.  Εδώ που το
> > gpg δεν είναι setuid root, όταν τρέχω το gpg από απλό χρήστη
> > παίρνω το "insecure memory" warning.  Όταν το τρέχω από root όμως
> > όχι.
>
> Μάλλον δεν ήμουν ξεκάθαρος. Το gpg είναι suid root, και δεν παίρνω
> warning για insecure memory, *αλλά* το strace μου έδειξε εκείνο το
> μήνυμα που μοιάζει με αποτυχία κλειδώματος της μνήμης.
>
> Αυτό που προσπαθώ να κάνω είναι να δω ότι όντως το gpg καλεί
> επιτυχώς την mlock().

Εδώ είναι λίγο περίεργα τα πράγματα.  Το ktrace στο BSD μου, έχει
συμπεριφορά που μοιάζει να είναι 'προστασία' των setuid προγραμμάτων
από tracing/debugging.  Τα παρακάτω είναι ότι ξέρω για το FreeBSD αλλά
αντίστοιχα πράγματα είμαι σίγουρος ότι μπορούν να βρεθούν και για το
Linux με λίγο ψάξιμο στο kernel source.

Όταν το gpg δεν είναι setuid, και τρέξω το ktrace για να κρατήσει log
από όλα τα system calls του προγράμματος, βλέπω:

: giorgos at gothmog[16:49]/home/giorgos$ kdump -f gpg.trace | grep mlock
:  34753 gpg      CALL  mlock(0x2829a000,0x4000)
:  34753 gpg      RET   mlock -1 errno 1 Operation not permitted

Αυτό είναι αναμενόμενο, αφού το gpg δεν είναι setuid root.  Όταν το
αλλάξω σε setuid, το ktrace μετά το exec του gpg σταματάει να μου
δείχνει τα events:

: giorgos at gothmog[16:55]/home/giorgos$ kdump -f gpg.trace | more
:  34850 ktrace   RET   ktrace 0
:  34850 ktrace   CALL  execve(0xbfbff360,0xbfbff880,0xbfbff88c)
:  34850 ktrace   NAMI  "/sbin/gpg"
:  34850 ktrace   RET   execve -1 errno 2 No such file or directory
:  34850 ktrace   CALL  execve(0xbfbff360,0xbfbff880,0xbfbff88c)
:  34850 ktrace   NAMI  "/bin/gpg"
:  34850 ktrace   RET   execve -1 errno 2 No such file or directory
:  34850 ktrace   CALL  execve(0xbfbff360,0xbfbff880,0xbfbff88c)
:  34850 ktrace   NAMI  "/usr/sbin/gpg"
:  34850 ktrace   RET   execve -1 errno 2 No such file or directory
:  34850 ktrace   CALL  execve(0xbfbff360,0xbfbff880,0xbfbff88c)
:  34850 ktrace   NAMI  "/usr/bin/gpg"
:  34850 ktrace   RET   execve -1 errno 2 No such file or directory
:  34850 ktrace   CALL  execve(0xbfbff360,0xbfbff880,0xbfbff88c)
:  34850 ktrace   NAMI  "/usr/games/gpg"
:  34850 ktrace   RET   execve -1 errno 2 No such file or directory
:  34850 ktrace   CALL  execve(0xbfbff360,0xbfbff880,0xbfbff88c)
:  34850 ktrace   NAMI  "/usr/local/bin/gpg"
:  34850 ktrace   NAMI  "/usr/libexec/ld-elf.so.1"
: giorgos at gothmog[16:55]/home/giorgos$

Πλέον το gpg τρέχει με δικαιώματα root και δεν επιτρέπεται σαν
'giorgos' να μπορώ να βλέπω τι κάνει ενα setuid πρόγραμμα.

Αντίθετα, σαν superuser, μπορώ να συνεχίσω το tracing κανονικά:

: sysop at gothmog[16:51]/home/giorgos# kdump -f gpg.trace | grep mlock
:  34781 gpg      CALL  mlock(0x2829a000,0x4000)
:  34781 gpg      RET   mlock 0

Ο περιορισμός αυτός επιβάλλεται από τον ίδιο τον πυρήνα του FreeBSD,
στο αρχείο kern_ktrace[1].  Η ktrace() ψάχνει πρώτα να βρει στο
process list το struct proc *p το οποίο προσπαθεί ο user να κάνει
trace.  'Υστερα καλείται το p_candebug() από το kern_prot.c[2].

Οι έλεγχοι που κάνει το p_candebug() είναι οι εξής:

  - Αν δεν είναι ενεργοποιημένο το superuser policy (ο χρήστης root
    όντως έχει περισσότερα δικαιώματα) ή  είναι το calling thread
    περιορισμένο σε κάποιο jail (jail == chroot on steroids), τότε η
    πρόσβαση απαγορεύεται.

  - Αν υπάρχει κάποιος άλλος περιορισμός λόγω jail (η function
    prison_check() αποτύχει), τότε η πρόσβαση απαγορεύεται.

  - Αν το sysctl security.bsd.see_other_uids είναι μηδέν ή το real uid
    του caller είναι διαφορετικό από το real uid του proc *p, τότε η
    πρόσβαση απαγορεύεται.

  - Οι τελευταίοι έλεγχοι είναι που μας ενδιαφέρουν όμως.  Τρεις
    διαφορετικοί έλεγχοι ενώνονται σε ένα if { ... } block.

   1591         /*
   1592          * Is p's group set a subset of td's effective group set?  This
   1593          * includes p's egid, group access list, rgid, and svgid.
   1594          */
...
   1606         /*
   1607          * Are the uids present in p's credential equal to td's
   1608          * effective uid?  This includes p's euid, svuid, and ruid.
   1609          */
...
   1619         /*
   1620          * If p's gids aren't a subset, or the uids aren't a subset,
   1621          * or the credential has changed, require appropriate privilege
   1622          * for td to debug p.  For POSIX.1e capabilities, this will
   1623          * require CAP_SYS_PTRACE.
   1624          */
   1625         if (!grpsubset || !uidsubset || credentialchanged) {
   1626                 error = suser_cred(td->td_ucred, PRISON_ROOT);
   1627                 if (error)
   1628                         return (error);
   1629         }

Αυτό είναι που με περιορίζει εμένα να κάνω ktrace σε setuid
προγράμματα από απλό user.  Και τώρα που διάβασα τι γίνεται και
κυρίως πως, μπορώ να πω ότι καταλαβαίνω γιατί το κάνουν αυτό :)


=== Αναφορές

[1] http://cvsweb.freebsd.org/src/sys/kern/kern_ktrace.c
[2] http://cvsweb.freebsd.org/src/sys/kern/kern_prot.c




More information about the Linux-greek-users mailing list