Filehandles, αρχεία, κατάλογοι
chroot#
Αλλάζει τον ριζικό κατάλογο της τρέχουσας διεργασίας και κάθε παιδιού που αυτή δημιουργεί στη συνέχεια.
Μετά από επιτυχή chroot, κάθε όνομα διαδρομής που ξεκινά με / αναλύεται σχετικά ως προς τον κατάλογο που υποδεικνύεται από το FILENAME αντί για την πραγματική ρίζα του συστήματος αρχείων. Η διεργασία χάνει τη δυνατότητα να ονομάζει αρχεία εκτός αυτού του υποδέντρου μέσω απόλυτων διαδρομών. Ο πυρήνας το επιβάλλει αυτό για την τρέχουσα διεργασία και για κάθε απόγονο - δεν υπάρχει εμβέλεια ανά νήμα ούτε τρόπος αναίρεσης από το εσωτερικό του κελιού.
Το chroot δεν αλλάζει τον τρέχοντα κατάλογο εργασίας. Αν ο κατάλογος εργασίας ήταν εκτός της νέας ρίζας τη στιγμή που η κλήση πέτυχε, παραμένει εκτός, και οι σχετικές διαδρομές μπορούν ακόμη να ξεφύγουν. Ακολουθήστε πάντοτε μια επιτυχημένη chroot με chdir στο / (που πλέον σημαίνει εντός του κελιού) πριν κάνετε οτιδήποτε άλλο.
Η κλήση περιορίζεται στον υπερχρήστη. Μια ανεξουσιοδότητη διεργασία λαμβάνει EPERM και το $! τίθεται ανάλογα.
Σύνοψη#
chroot FILENAME
chroot
Τι επιστρέφεται#
1 σε επιτυχία, 0 σε αποτυχία. Σε αποτυχία το $! κρατά το errno από την υποκείμενη κλήση συστήματος chroot(2) - συνήθως EPERM (όχι root), ENOENT (η διαδρομή δεν υπάρχει), ή ENOTDIR (η διαδρομή δεν είναι κατάλογος).
Ελέγχετε πάντα την τιμή επιστροφής. Μια σιωπηλή αποτυχία αφήνει τη διεργασία να εκτελείται εκτός του προβλεπόμενου κελιού, κάτι που είναι συνήθως χειρότερο από τη διαδρομή κώδικα που πραγματοποίησε την κλήση εξαρχής.
chroot "/var/empty"
or die "chroot: $!";
chdir "/"
or die "chdir after chroot: $!";
Καθολική κατάσταση που επηρεάζει#
Παραδείγματα#
Η κανονική ασφαλής ακολουθία - αλλαγή ρίζας, μετά αλλαγή καταλόγου εργασίας στη νέα ρίζα, και μετά αποβολή δικαιωμάτων:
chroot "/srv/jail" or die "chroot: $!";
chdir "/" or die "chdir: $!";
$) = $(= 65534; # drop to 'nobody' gids
$> = $< = 65534; # drop to 'nobody' uids
Ανοίξτε αρχεία και φορτώστε κοινόχρηστες βιβλιοθήκες πριν από το chroot, όχι μετά. Η νέα ρίζα τυπικά δεν έχει ούτε /etc/resolv.conf ούτε τις διαδρομές αναζήτησης του δυναμικού συνδέτη:
open my $log, ">>", "/var/log/app.log" or die $!;
my $cfg = read_config("/etc/app.conf");
chroot "/srv/jail" or die "chroot: $!";
chdir "/" or die "chdir: $!";
# $log and $cfg are still usable inside the jail.
Έλεγχος των τρόπων αποτυχίας ξεχωριστά - η διάκριση μεταξύ «όχι root» και «λανθασμένη διαδρομή» έχει σημασία για τα διαγνωστικά:
use Errno qw(EPERM ENOENT ENOTDIR);
unless (chroot $path) {
die "chroot: need root privileges\n" if $! == EPERM;
die "chroot: $path does not exist\n" if $! == ENOENT;
die "chroot: $path is not a directory\n" if $! == ENOTDIR;
die "chroot: $!";
}
Η μορφή με προεπιλεγμένο όρισμα διαβάζει τη διαδρομή από το $_:
$_ = "/srv/jail";
chroot or die "chroot: $!";
Οριακές περιπτώσεις#
Όχι root: αποτυγχάνει με
EPERM. Δεν υπάρχει χαλάρωση βασισμένη σε δυνατότητες (capabilities) στο τυπικό Linux εκτός αν η διεργασία κατέχει τοCAP_SYS_CHROOT.Σχετική διαδρομή: το
chroot "jail"αναλύεται ως προς τον τρέχοντα κατάλογο εργασίας τη στιγμή της κλήσης. Προτιμήστε απόλυτες διαδρομές ώστε η συμπεριφορά να μην εξαρτάται από τοcwdτου καλούντος.Symlinks στο
FILENAME: αναλύονται πριν τεθεί σε ισχύ η chroot. Symlinks εντός της νέας ρίζας που δείχνουν σε απόλυτες διαδρομές θα αναλυθούν σχετικά ως προς τη νέα ρίζα, όχι την πραγματική ρίζα - αυτή είναι η προβλεπόμενη συμπεριφορά εγκλεισμού, όχι σφάλμα.Οι ανοιχτοί περιγραφείς αρχείων επιζούν: κάθε handle που ανοίχθηκε πριν την κλήση παραμένει χρήσιμο μετά. Έτσι οι καλοδιατεθειμένοι δαίμονες διατηρούν αρχεία καταγραφής, διαμόρφωση και υποδοχές που ακούν κατά τη μετάβαση.
Καμία διαφυγή από μέσα: μια διεργασία δεν μπορεί να «βγει» κάνοντας
chroot. Ο μόνος τρόπος εξόδου από ένα chroot είναι να την συλλέξει και να την αντικαταστήσει μια προνομιακή διεργασία εκτός αυτού.Κατάλογος εργασίας εκτός της νέας ρίζας: ο πυρήνας επιτρέπει την κλήση, αλλά οι σχετικές διαδρομές και η διάσχιση
..από εκεί μπορούν ακόμη να φτάσουν σε αρχεία εκτός του κελιού. Το υποχρεωτικόchdir "/"μετά τοchrootκλείνει αυτό το κενό.Threads: το
chrootστο Linux είναι ανά διεργασία (αυστηρά, ανά fs struct). Υπόuse threadsόλα τα νήματα διερμηνέα μοιράζονται την ίδια ρίζα μετά την κλήση - δεν υπάρχει κελί ανά νήμα.Δεν επηρεάζει τις
$0,%ENV, ούτε τις ανοιχτές υποδοχές. Αλλάζει μόνο η ανάλυση διαδρομών.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
chdir- η υποχρεωτική συνέχεια μετά από επιτυχήchroot· χωρίς αυτό ο κατάλογος εργασίας μπορεί να δείχνει ακόμη εκτός της νέας ρίζαςfork- τα παιδιά κληρονομούν το chroot· συνδυάστε μεchrootγια να εκτελέσετε κώδικα χωρίς εμπιστοσύνη σε περιορισμένο υποδέντροexec- εκτελεί το πρόγραμμα αντικατάστασης εντός της τρέχουσας ρίζας, οπότε το εκτελέσιμο-στόχος και οι δυναμικές του βιβλιοθήκες πρέπει να υπάρχουν εντός του κελιούopen- το άνοιγμα αρχείων με απόλυτη διαδρομή μετά απόchrootαναζητά ονόματα εντός του κελιού· ανοίξτε εκ των προτέρων ό,τι χρειάζεστε από έξω πριν την κλήση$_- η προεπιλεγμένη διαδρομή όταν τοchrootκαλείται χωρίς όρισμα$!- κρατά τοerrnoαπό τοchroot(2)σε αποτυχία