Προγραμματισμός

Ασφάλεια και επαληθευτής κλάσης

Το άρθρο αυτού του μήνα συνεχίζει τη συζήτηση για το μοντέλο ασφαλείας της Java που ξεκίνησε τον Αύγουστο "Under the Hood". Σε αυτό το άρθρο, έδωσα μια γενική επισκόπηση των μηχανισμών ασφαλείας που είναι ενσωματωμένοι στην εικονική μηχανή Java (JVM). Κοίταξα επίσης μια πτυχή αυτών των μηχανισμών ασφαλείας: τα ενσωματωμένα χαρακτηριστικά ασφαλείας της JVM. Τον Σεπτέμβριο "Under the Hood", εξέτασα την αρχιτεκτονική του φορτωτή κατηγορίας, μια άλλη πτυχή των ενσωματωμένων μηχανισμών ασφαλείας της JVM. Αυτό το μήνα θα επικεντρωθώ στο τρίτο σημείο της στρατηγικής ασφαλείας της JVM: τον επαληθευτή κλάσης.

Ο επαληθευτής αρχείου τάξης

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

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

Παρόλο που επιτρέπεται στους σχεδιαστές εικονικών μηχανών Java να αποφασίσουν πότε θα εκτελέσουν αυτούς τους ελέγχους οι εικονικές μηχανές τους, πολλές εφαρμογές θα κάνουν τους περισσότερους ελέγχους αμέσως μετά τη φόρτωση μιας κλάσης. Μια τέτοια εικονική μηχανή αναλύει bytecodes (και επαληθεύει την ακεραιότητά τους) μία φορά, πριν εκτελεστούν ποτέ. Ως μέρος της επαλήθευσης των κωδικών bytec, η εικονική μηχανή Java διασφαλίζει όλες τις οδηγίες άλματος - για παράδειγμα, παω σε (πηδά πάντα), ifeq (άλμα αν η κορυφή της στοίβας είναι μηδέν) κ.λπ. - προκαλέστε μετάβαση σε άλλη έγκυρη οδηγία στη ροή bytecode της μεθόδου. Κατά συνέπεια, η εικονική μηχανή δεν χρειάζεται να ελέγχει για έγκυρο στόχο κάθε φορά που συναντά μια εντολή άλματος καθώς εκτελεί bytecodes. Στις περισσότερες περιπτώσεις, ο έλεγχος όλων των bytecodes μία φορά πριν να εκτελεστεί είναι ένας πιο αποτελεσματικός τρόπος για να εγγυηθεί την ευρωστία από τον έλεγχο κάθε εντολής bytecode κάθε φορά που εκτελείται.

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

Πρώτη φάση: Εσωτερικοί έλεγχοι

Κατά τη διάρκεια της πρώτης φάσης, ο ελεγκτής αρχείων κατηγορίας ελέγχει ό, τι είναι δυνατό να ελέγξει σε ένα αρχείο τάξης κοιτάζοντας μόνο το ίδιο το αρχείο τάξης (χωρίς να εξετάσει άλλες κλάσεις ή διεπαφές). Η πρώτη φάση του επαληθευτή αρχείων κλάσης διασφαλίζει ότι το εισαγόμενο αρχείο κλάσης έχει σωστά διαμορφωθεί, εσωτερικά συνεπές, συμμορφώνεται με τους περιορισμούς της γλώσσας προγραμματισμού Java και περιέχει bytecodes που θα είναι ασφαλείς για την εικονική μηχανή Java για εκτέλεση. Εάν ο επαληθευτής αρχείου κλάσης διαπιστώσει ότι κανένα από αυτά δεν είναι αληθές, δημιουργεί σφάλμα και το αρχείο κλάσης δεν χρησιμοποιείται ποτέ από το πρόγραμμα.

Έλεγχος μορφής και εσωτερικής συνέπειας

Εκτός από την επαλήθευση της ακεραιότητας των κωδικών bytec, ο επαληθευτής εκτελεί πολλούς ελέγχους για σωστή μορφή αρχείου κλάσης και εσωτερική συνέπεια κατά τη διάρκεια της πρώτης φάσης. Για παράδειγμα, κάθε αρχείο τάξης πρέπει να ξεκινά με τα ίδια τέσσερα byte, τον μαγικό αριθμό: 0xCAFEBABE. Ο σκοπός των μαγικών αριθμών είναι να διευκολύνει τους αναλυτές αρχείων να αναγνωρίζουν έναν συγκεκριμένο τύπο αρχείου. Έτσι, το πρώτο πράγμα που ένας ελεγκτής αρχείων κατηγορίας ελέγχει πιθανώς είναι ότι το εισαγόμενο αρχείο πράγματι ξεκινά με 0xCAFEBABE.

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

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

Επιπλέον, ο επαληθευτής αρχείου κλάσης ελέγχει ότι η ίδια η κλάση συμμορφώνεται με ορισμένους περιορισμούς που θέτει σε αυτήν από την προδιαγραφή της γλώσσας προγραμματισμού Java. Για παράδειγμα, ο ελεγκτής επιβάλλει τον κανόνα ότι όλες οι κλάσεις, εκτός από την κλάση Αντικείμενο, πρέπει να έχει ένα superclass. Έτσι, ο ελεγκτής class-file ελέγχει κατά το χρόνο εκτέλεσης ορισμένους από τους κανόνες γλώσσας Java που θα έπρεπε να είχαν επιβληθεί κατά το χρόνο μεταγλώττισης. Επειδή ο επαληθευτής δεν έχει κανέναν τρόπο να γνωρίζει εάν το αρχείο κλάσης δημιουργήθηκε από έναν καλοπροαίρετο μεταγλωττιστή χωρίς σφάλματα, ελέγχει κάθε αρχείο τάξης για να βεβαιωθεί ότι τηρούνται οι κανόνες.

$config[zx-auto] not found$config[zx-overlay] not found