Έργο για τη μεταφορά του μηχανισμού απομόνωσης δέσμευσης στο Linux

Ο συγγραφέας της βιβλιοθήκης Cosmopolitan standard C και της πλατφόρμας Redbean ανακοίνωσε την εφαρμογή του μηχανισμού απομόνωσης pledge() για Linux. Το Pledge αναπτύχθηκε αρχικά από το έργο OpenBSD και σας επιτρέπει να απαγορεύετε επιλεκτικά στις εφαρμογές την πρόσβαση σε αχρησιμοποίητες κλήσεις συστήματος (ένα είδος λευκής λίστας κλήσεων συστήματος σχηματίζεται για την εφαρμογή και άλλες κλήσεις απαγορεύονται). Σε αντίθεση με τους μηχανισμούς περιορισμού κλήσεων συστήματος που είναι διαθέσιμοι στο Linux, όπως το seccomp, ο μηχανισμός δέσμευσης σχεδιάστηκε αρχικά για να είναι όσο το δυνατόν απλούστερος.

Η αποτυχημένη πρωτοβουλία για την απομόνωση εφαρμογών στο βασικό περιβάλλον του OpenBSD με χρήση του μηχανισμού systrace έδειξε ότι η απομόνωση σε επίπεδο μεμονωμένων κλήσεων συστήματος ήταν πολύ περίπλοκη και χρονοβόρα. Ως εναλλακτική λύση, προτάθηκε μια δέσμευση, η οποία κατέστησε δυνατή τη δημιουργία κανόνων απομόνωσης χωρίς να μπούμε σε λεπτομέρειες και να χειριστούμε έτοιμες τάξεις πρόσβασης. Για παράδειγμα, οι κατηγορίες που προσφέρονται είναι stdio (είσοδος/έξοδος), rpath (αρχεία μόνο για ανάγνωση), wpath (εγγραφή αρχείων), cpath (δημιουργία αρχείων), tmppath (εργασία με προσωρινά αρχεία), inet (υποδοχές δικτύου), unix ( υποδοχές unix), dns (ανάλυση DNS), getpw (πρόσβαση ανάγνωσης στη βάση δεδομένων χρήστη), ioctl (κλήση ioctl), proc (διαχείριση διαδικασίας), exec (εκκίνηση διεργασίας) και id (διαχείριση δικαιωμάτων πρόσβασης).

Οι κανόνες για την εργασία με κλήσεις συστήματος καθορίζονται με τη μορφή σχολιασμών, συμπεριλαμβανομένης μιας λίστας επιτρεπόμενων κλάσεων κλήσεων συστήματος και μιας σειράς διαδρομών αρχείων όπου επιτρέπεται η πρόσβαση. Μετά τη δημιουργία και την εκκίνηση της τροποποιημένης εφαρμογής, ο πυρήνας αναλαμβάνει το έργο της παρακολούθησης της συμμόρφωσης με τους καθορισμένους κανόνες.

Για το FreeBSD αναπτύσσεται μια ξεχωριστή εφαρμογή δέσμευσης, η οποία διακρίνεται από την ικανότητα απομόνωσης εφαρμογών χωρίς αλλαγές στον κώδικά τους, ενώ στο OpenBSD η κλήση δέσμευσης στοχεύει στη στενή ενοποίηση με το βασικό περιβάλλον και την προσθήκη σχολιασμών στον κώδικα κάθε εφαρμογή.

Οι προγραμματιστές της θύρας δέσμευσης για Linux πήραν το παράδειγμα του FreeBSD και, αντί να κάνουν αλλαγές στον κώδικα, ετοίμασαν ένα πρόσθετο βοηθητικό πρόγραμμα pledge.com που σας επιτρέπει να εφαρμόζετε περιορισμούς χωρίς να αλλάξετε τον κώδικα της εφαρμογής. Για παράδειγμα, για να εκτελέσετε το βοηθητικό πρόγραμμα curl με πρόσβαση μόνο στις κλάσεις κλήσεων συστήματος stdio, rpath, inet και threadstdio, απλώς εκτελέστε το "./pledge.com -p 'stdio rpath inet thread' curl http://example.com".

Το βοηθητικό πρόγραμμα pledge λειτουργεί σε όλες τις διανομές Linux ξεκινώντας από το RHEL6 και δεν απαιτεί πρόσβαση root. Επιπλέον, με βάση την κοσμοπολίτικη βιβλιοθήκη, παρέχεται ένα API για τη διαχείριση περιορισμών στον κώδικα προγράμματος στη γλώσσα C, το οποίο επιτρέπει, μεταξύ άλλων, τη δημιουργία θυλάκων για τον επιλεκτικό περιορισμό της πρόσβασης σε σχέση με ορισμένες λειτουργίες εφαρμογής.

Η υλοποίηση δεν απαιτεί αλλαγές στον πυρήνα - οι περιορισμοί δέσμευσης μεταφράζονται σε κανόνες SECCOMP BPF και υποβάλλονται σε επεξεργασία χρησιμοποιώντας τον εγγενή μηχανισμό απομόνωσης κλήσεων συστήματος Linux. Για παράδειγμα, η δέσμευση κλήσης("stdio rpath", 0) θα μετατραπεί σε ένα φίλτρο BPF static const struct sock_filter kFilter[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, syscall, 0, 14 - 1 ), / * L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), /* L2*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 4 - 3, 0), /* L3* / BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 10, 0, 13 - 4), /* L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), /* L5*/ BPF_STMT (BPF_STMT) | BPF_K, ~0x80800), /* L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 8 - 7, 0), /* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | 2, -0,) , /* L13*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[8])), /* L8*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 9 - 0, 12), /*L10 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 10 - 6, 12), /*L11*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 11, 17 - 0), /*BPF_13 SECCOMP_RET_ALLOW), /*L11*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L12*/ /* επόμενο φίλτρο */ };

Πηγή: opennet.ru

Προσθέστε ένα σχόλιο