Steven
Steven6 λεπτά ανάγνωσης

Η εφαρμογή Mac σας δίνει πρόσβαση στο μικρόφωνο — και μετά την ξεχνά σε κάθε εκκίνηση

Το GeekBye ζήτησε άδεια μικροφώνου, την παραχωρήσατε και δούλεψε. Στην επόμενη εκκίνηση: χάθηκε. Και η εφαρμογή δεν εμφανίστηκε καθόλου στις Ρυθμίσεις συστήματος → Μικρόφωνο. Ο ένοχος ήταν μια λειτουργία ασφαλείας του macOS που έτρεχε σιωπηλά την εφαρμογή από μια διαδρομή που εξαφανίζεται — ιδού η διάγνωση και η διόρθωση με μία μόνο προτροπή.

macOS
Άδειες
Μηχανική
Εκδόσεις GeekBye
Η εφαρμογή Mac σας δίνει πρόσβαση στο μικρόφωνο — και μετά την ξεχνά σε κάθε εκκίνηση

Ιδού ένα σφάλμα που σε κάνει να αμφιβάλλεις για τα ίδια σου τα μάτια. Εγκαθιστάς το GeekBye, ζητά πρόσβαση στο μικρόφωνο, πατάς Allow, και η μεταγραφή δουλεύει. Τέλεια. Το κλείνεις, το ξανανοίγεις το επόμενο πρωί — και ζητά πρόσβαση στο μικρόφωνο ξανά. Πας να ελέγξεις τις Ρυθμίσεις συστήματος → Απόρρητο και ασφάλεια → Μικρόφωνο για να το διορθώσεις χειροκίνητα, και το GeekBye δεν είναι καν στη λίστα. Ούτε απορριφθέν. Ούτε επιτρεπόμενο. Απλώς απόν, σαν να μη ζήτησε ποτέ.

Κάθε επιμέρους κομμάτι φαινόταν σωστό. Η προτροπή ήταν πραγματική. Η άδεια δούλευε εκείνη τη στιγμή. Η εφαρμογή ήταν σωστά υπογεγραμμένη και notarized με τα σωστά usage strings. Κι όμως η παραχώρηση εξατμιζόταν σε κάθε εκκίνηση. Το GeekBye v2.0.6 το διόρθωσε — και η βασική αιτία είναι ένα από τα πιο ύπουλα πράγματα που κάνει το macOS για να σε προστατεύσει.

Η λειτουργία που έκρυβε την εφαρμογή από τον εαυτό της

Ο ένοχος είναι το macOS App Translocation, μια λειτουργία ασφαλείας του Gatekeeper. Όταν κατεβάζεις μια εφαρμογή και την τρέχεις απευθείας από το DMG ή από τον φάκελο ~/Downloads σου — οπουδήποτε είναι ακόμη «σε καραντίνα» — το macOS δεν την τρέχει στην πραγματικότητα από εκεί που τη βλέπεις. Την αντιγράφει διάφανα σε μια τυχαιοποιημένη διαδρομή μόνο για ανάγνωση, βαθιά κάτω από το /private/var/folders/.../AppTranslocation/… και τρέχει αυτό το αντίγραφο. Είναι καλή άμυνα: εμποδίζει μια κακόβουλη λήψη να πειράξει αρχεία δίπλα της.

Αλλά ιδού η σύγκρουση. Το σύστημα αδειών του macOS (TCC — αυτό που παρακολουθεί ποιος μπορεί να χρησιμοποιήσει το μικρόφωνο, την κάμερα, την οθόνη σου) αναγνωρίζει μια εφαρμογή από τη διαδρομή και την ταυτότητα κώδικά της. Όταν η εφαρμογή είναι translocated, αυτή η διαδρομή είναι τυχαία και προσωρινή. Έτσι, όταν παραχωρείς πρόσβαση στο μικρόφωνο, το macOS καταγράφει ευσυνείδητα την παραχώρηση — έναντι μιας διαδρομής που δεν θα υπάρχει στην επόμενη εκκίνηση. Ξανανοίγεις την εφαρμογή, το macOS την translocates σε μια διαφορετική τυχαία διαδρομή, βλέπει μια εφαρμογή για την οποία δεν έχει καμία εγγραφή, και ρωτά ξανά. Και επειδή αυτή η φανταστική διαδρομή δεν είναι ποτέ σταθερή τοποθεσία, η εφαρμογή δεν κερδίζει ποτέ μια μόνιμη σειρά στις Ρυθμίσεις συστήματος → Μικρόφωνο.

Η εφαρμογή παραχωρούσε άδεια σε ένα φάντασμα.

Γι' αυτό επίσης μόνο ορισμένοι άνθρωποι το συναντούσαν. Αν το αντίγραφό σου του GeekBye ζούσε ήδη στο /Applications — επειδή το έσυρες εκεί, ή επειδή έφτασε εκεί μέσω αυτόματης ενημέρωσης — δεν υπάρχει καραντίνα, δεν υπάρχει translocation, μια σταθερή διαδρομή, και όλα διατηρούνται τέλεια. Το σφάλμα ήταν αόρατο για εμάς και για όποιον είχε περάσει την πρώτη εγκατάσταση, ακριβώς το είδος σφάλματος που επιβιώνει περισσότερο.

Η διόρθωση: δώσε στην εφαρμογή ένα πραγματικό σπίτι

Αφού ολόκληρο το πρόβλημα είναι μια ασταθής διαδρομή, η διόρθωση είναι να βάλεις την εφαρμογή σε μια σταθερή. Η v2.0.6 ανιχνεύει πότε το GeekBye τρέχει translocated (ή απλώς τρέχει εκτός /Applications) και προσφέρει ένα «Move to Applications» με ένα κλικ — χρησιμοποιώντας την κλήση μετεγκατάστασης του macOS που αντιγράφει το bundle στο /Applications και το επανεκκινεί από εκεί. Από εκείνο το σημείο και μετά η εφαρμογή έχει σταθερή ταυτότητα: η παραχώρηση μικροφώνου παραμένει, η εγγραφή οθόνης παραμένει, και το GeekBye εμφανίζεται επιτέλους στις Ρυθμίσεις συστήματος, εκεί που θα το περίμενες.

Η προτροπή είναι ευγενική σχετικά με αυτό. Προσφέρει Move to Applications, Not Now και Don't Ask Again — και θυμάται την τελευταία επιλογή, ώστε η εφαρμογή να μην ενοχλεί ποτέ κάποιον που έχει σκόπιμο λόγο να την τρέχει από αλλού. Η απόφαση αν θα εμφανίσει καν την προτροπή είναι απομονωμένη σε μικρές, καθαρές συναρτήσεις (είναι αυτό το build translocated; είναι εκτός /Applications; το κατέστειλε ο χρήστης;) ώστε η λογική να ελέγχεται με unit tests χωρίς να χρειάζεται να εκκινήσεις ένα πραγματικό notarized build σε έναν πραγματικό τόμο σε καραντίνα.

Η ίδια έκδοση απλοποίησε επίσης και την ίδια την εμπειρία αδειών. Το GeekBye συνήθιζε να ανοίγει ένα προσαρμοσμένο, εξατομικευμένο παράθυρο αδειών εντός της εφαρμογής — μερικές εκατοντάδες γραμμές UI που προσπαθούσαν να αναπαραγάγουν κάτι που το λειτουργικό σύστημα κάνει ήδη καλά. Η v2.0.6 το διέγραψε και στηρίχθηκε στην εγγενή προτροπή αδειών του macOS, με την υποστήριξη ενός διακριτικού, μη μπλοκαρίσματος banner που εμφανίζεται μόνο όταν λείπει πραγματικά μια απαιτούμενη άδεια. Λιγότερος κώδικας, και συμπεριφορά που οι χρήστες ήδη αναγνωρίζουν επειδή κάθε άλλη εφαρμογή Mac δουλεύει το ίδιο.

Το κομμάτι για το οποίο είμαι πιο περήφανος: το αποδείξαμε πριν το πιστέψουμε

Θα ήταν εύκολο να μαντέψουμε το translocation και να κυκλοφορήσουμε μια διόρθωση. Αντ' αυτού, η έκδοση κυκλοφόρησε πρώτα ένα διαγνωστικό εκκίνησης: κατά την εκκίνηση, το GeekBye αναφέρει τώρα τη δική του διαδρομή εκτελέσιμου και το αν είναι translocated, το αν είναι μέσα στο /Applications, και την τρέχουσα κατάσταση των αδειών μικροφώνου και οθόνης. Αυτή η τηλεμετρία μετέτρεψε μια εύλογη θεωρία σε επιβεβαιωμένη — τα δεδομένα παραγωγής έδειξαν ότι οι επηρεαζόμενες συνεδρίες έτρεχαν, όντως, από translocated διαδρομές εκτός /Applications, ακριβώς όπως προβλέφθηκε.

Αυτή η σειρά έχει σημασία. Το «η προτροπή εμφανίζεται αλλά η άδεια δεν παραμένει» έχει αρκετές πιθανές εξηγήσεις — ένα πρόβλημα υπογραφής, ένα usage string που λείπει, ένα ζήτημα entitlement, μια ιδιοτροπία της βάσης δεδομένων TCC. Αποκλείσαμε τις αιτίες σε επίπεδο API (η διαδρομή του αιτήματος ήταν αποδεδειγμένα σωστή), και μετά αφήσαμε τα δεδομένα του πραγματικού κόσμου να δείξουν το επίπεδο ταυτότητας/διαδρομής, αντί να κυκλοφορήσουμε μια αισιόδοξη διόρθωση και να ελπίζουμε ότι τα tickets υποστήριξης σταμάτησαν.

Τρία πράγματα που διδάσκει αυτό το σφάλμα

  1. Μια άδεια που ζητά αλλά δεν διατηρείται είναι πρόβλημα ταυτότητας, όχι πρόβλημα API. Αν ο κώδικας του αιτήματος είναι σωστός και η παραχώρηση εξακολουθεί να εξαφανίζεται, σταμάτα να ξαναγράφεις το αίτημα. Ρώτα με ποια διαδρομή και ταυτότητα κώδικα δένει το λειτουργικό σύστημα την παραχώρηση — και αν αυτή η ταυτότητα είναι σταθερή ανάμεσα στις εκκινήσεις.
  2. Κυκλοφόρησε το διαγνωστικό μαζί με (ή πριν) τη διόρθωση. Μερικά πεδία — από πού τρέχω, ποια είναι η κατάσταση των αδειών μου — μετέτρεψαν μια μορφωμένη εικασία σε επαληθευμένη βασική αιτία και μας είπαν ακριβώς ποιοι χρήστες επηρεάστηκαν. Οργανολόγησε το όριο που υποψιάζεσαι πριν το μπαλώσεις.
  3. Τα σφάλματα που κρύβονται από τους προγραμματιστές είναι αυτά που τρέχουν στο «λάθος» περιβάλλον. Το δικό μας ζούσε στο /Applications σε κάθε μηχάνημα ανάπτυξης, οπότε το σφάλμα ήταν δομικά αόρατο για εμάς ενώ χτυπούσε τους χρήστες πρώτης εγκατάστασης. Όταν μια αναφορά δεν αναπαράγεται, η πρώτη ερώτηση είναι τι είναι διαφορετικό σχετικά με το πού τρέχει, όχι μήπως κάνει λάθος ο χρήστης.

Το GeekBye v2.0.6 κυκλοφόρησε την προτροπή μετεγκατάστασης και το διαγνωστικό μαζί. Για το ευρύτερο τόξο αξιοπιστίας στο οποίο εντάσσεται αυτό, δες τι πραγματικά χρειάζεται μια έκδοση 2 (v2.0.0) και γιατί η εγγραφή οθόνης πιάνει τη λάθος οθόνη (v2.0.10) — ένα άλλο σφάλμα που εμφανίστηκε μόνο σε συγκεκριμένο περιβάλλον. Για την έκδοση μικρών λεπτομερειών δίπλα, ήρεμο λογισμικό: η διόρθωση του flicker και το chip της λειτουργίας-απάντησης (v2.0.3 + v2.0.5).

Σχετικά Άρθρα

Η ανατομία της τέλειας κυκλοφορίας λογισμικού: Πώς ο έλεγχος κώδικα έπιασε αυτό που τα τεστ δεν μπορούσαν
Steven
Steven7 λεπτά ανάγνωσης

Η ανατομία της τέλειας κυκλοφορίας λογισμικού: Πώς ο έλεγχος κώδικα έπιασε αυτό που τα τεστ δεν μπορούσαν

Σε όλη τη σειρά του GeekBye v2, το ίδιο πράγμα συμβαίνει ξανά και ξανά: μια διόρθωση περνάει κάθε τεστ στο μηχάνημα του προγραμματιστή, και μετά ο έλεγχος κώδικα αποδεικνύει ότι θα είχε αποτύχει για σχεδόν όλους. Αυτή είναι η ροή εργασίας πίσω από εννέα κυκλοφορίες — η πύλη ελέγχου, οι διορθώσεις που πιάστηκαν από νωρίς και η πειθαρχία του «τεστ πριν την αποστολή» που μετατρέπει το «δουλεύει σ' εμένα» σε «δουλεύει».

Μηχανική
Διαδικασία
Έλεγχος Κώδικα
Μία μεταβλητή CSS, πέντε γύροι ελέγχου κι ένα Swift toolchain που είπε ψέματα
Steven
Steven7 λεπτά ανάγνωσης

Μία μεταβλητή CSS, πέντε γύροι ελέγχου κι ένα Swift toolchain που είπε ψέματα

Το GeekBye v2.0.7 έκανε ολόκληρο το overlay ρυθμιζόμενα ημιδιαφανές — που ακούγεται σαν μια αλλαγή CSS μιας γραμμής και σε καμία περίπτωση δεν ήταν. Η πραγματική ιστορία είναι τι έπιασε ο έλεγχος κώδικα: δύο επιφάνειες που αρνούνταν να ξεθωριάσουν, μια μπάρα εγγραφής που φαινόταν λάθος στην ίδια αδιαφάνεια, κι ένα μεταγλωττισμένο εκτελέσιμο που ταλαντεύτηκε κατά 672 bytes επειδή η δική μας τεκμηρίωση είπε σε έναν ελεγκτή τη λάθος έκδοση Swift.

Μηχανική
Σχεδιασμός
Build
Ήρεμο Λογισμικό: Σκοτώνοντας έναν Διακόπτη που Τρεμόπαιζε και Μαθαίνοντας το Chat να Λέει σε Ποια Λειτουργία Βρίσκεται
Steven
Steven6 λεπτά ανάγνωσης

Ήρεμο Λογισμικό: Σκοτώνοντας έναν Διακόπτη που Τρεμόπαιζε και Μαθαίνοντας το Chat να Λέει σε Ποια Λειτουργία Βρίσκεται

Δύο μικρές κυκλοφορίες του GeekBye, χωρίς εντυπωσιακές λειτουργίες — απλώς ένας διακόπτης ρυθμίσεων που σταμάτησε να τρεμοπαίζει και ένας βοηθός chat που επιτέλους σου λέει αν απάντησε σε λειτουργία σύσκεψης ή σε λειτουργία προγραμματισμού. Να τι πραγματικά κοστίζει το «ήρεμο λογισμικό», μια λεπτομέρεια τη φορά.

Προϊόν
Σχεδιασμός
Μηχανική