Steven
Steven5 min čtení

Vaše Mac aplikace získá přístup k mikrofonu — a pak ho při každém spuštění zapomene

GeekBye požádal o oprávnění k mikrofonu, udělili jste ho a fungovalo to. Při dalším spuštění: pryč. A aplikace se v Nastavení systému → Mikrofon vůbec neobjevila. Viníkem byla bezpečnostní funkce macOS, která aplikaci tiše spouštěla z cesty, jež mizí — tady je diagnóza a oprava pomocí jediné výzvy.

macOS
Oprávnění
Inženýrství
Vydání GeekBye
Vaše Mac aplikace získá přístup k mikrofonu — a pak ho při každém spuštění zapomene

Tady je chyba, kvůli které začnete pochybovat o vlastních očích. Nainstalujete GeekBye, ten požádá o přístup k mikrofonu, kliknete na Allow a přepis funguje. Skvělé. Ukončíte ho, druhý den ráno znovu otevřete — a on zase požádá o přístup k mikrofonu. Jdete zkontrolovat Nastavení systému → Soukromí a zabezpečení → Mikrofon, abyste to opravili ručně, a GeekBye v seznamu vůbec není. Není zamítnutý. Není povolený. Prostě chybí, jako by nikdy nepožádal.

Každý jednotlivý kousek vypadal správně. Výzva byla skutečná. Oprávnění v tu chvíli fungovalo. Aplikace byla řádně podepsaná a notarizovaná se správnými řetězci použití. A přesto se oprávnění při každém spuštění vypařilo. GeekBye v2.0.6 to opravil — a hlavní příčinou je jedna z nejzáludnějších věcí, které macOS dělá pro vaši ochranu.

Funkce, která skrývala aplikaci sama před sebou

Viníkem je macOS App Translocation, bezpečnostní funkce Gatekeeperu. Když stáhnete aplikaci a spustíte ji přímo z DMG nebo ze složky ~/Downloads — kdekoli, kde je stále „v karanténě" — macOS ji ve skutečnosti nespouští odtud, kde ji vidíte. Transparentně ji zkopíruje na náhodnou cestu jen pro čtení, hluboko pod /private/var/folders/.../AppTranslocation/… a spustí tuto kopii. Je to dobrá obrana: brání škodlivému stažení v manipulaci se soubory vedle sebe.

Ale tady je ten střet. Systém oprávnění macOS (TCC — ten, který sleduje, kdo může používat váš mikrofon, kameru, obrazovku) identifikuje aplikaci podle její cesty a kódové identity. Když je aplikace translokovaná, ta cesta je náhodná a dočasná. Takže když udělíte přístup k mikrofonu, macOS poslušně zaznamená udělení — proti cestě, která při dalším spuštění nebude existovat. Znovu otevřete aplikaci, macOS ji translokuje na jinou náhodnou cestu, uvidí aplikaci, o které nemá žádný záznam, a zeptá se znovu. A protože ta fantomová cesta nikdy není stabilním umístěním, aplikace nikdy nezíská trvalý řádek v Nastavení systému → Mikrofon.

Aplikace udělovala oprávnění duchovi.

Proto na to také narazili jen někteří lidé. Pokud vaše kopie GeekBye už bydlela ve složce /Applications — protože jste ji tam přetáhli, nebo se tam dostala přes automatickou aktualizaci — není žádná karanténa, žádná translokace, stabilní cesta, a všechno zůstává dokonale zachováno. Chyba byla neviditelná pro nás i pro každého po první instalaci, přesně ten druh chyby, který přežívá nejdéle.

Oprava: dejte aplikaci opravdový domov

Protože celý problém je nestabilní cesta, oprava spočívá v tom dostat aplikaci na stabilní. v2.0.6 detekuje, když GeekBye běží translokovaně (nebo prostě běží mimo /Applications), a nabízí „Move to Applications" jedním kliknutím — pomocí volání macOS pro přemístění, které zkopíruje bundle do /Applications a odtud ho znovu spustí. Od té chvíle má aplikace pevnou identitu: oprávnění k mikrofonu zůstává, nahrávání obrazovky zůstává a GeekBye se konečně objeví v Nastavení systému, kde byste to čekali.

Výzva je v tomto ohledu zdvořilá. Nabízí Move to Applications, Not Now a Don't Ask Again — a pamatuje si poslední volbu, takže aplikace nikdy neotravuje někoho, kdo má záměrný důvod ji spouštět odjinud. Rozhodnutí, zda výzvu vůbec zobrazit, je izolováno do malých, čistých funkcí (je tento build translokovaný? je mimo /Applications? potlačil to uživatel?), takže logiku lze jednotkově testovat, aniž by bylo nutné spouštět skutečný notarizovaný build na skutečném svazku v karanténě.

Stejné vydání také zjednodušilo samotný zážitek z oprávnění. GeekBye dříve vyskakoval vlastní, na míru vyrobené okno oprávnění uvnitř aplikace — několik set řádků UI, které se snažilo reprodukovat něco, co operační systém už dělá dobře. v2.0.6 ho smazal a opřel se o nativní výzvu k oprávnění macOS, podpořenou tichým, neblokujícím banerem, který se objeví jen tehdy, když nějaké požadované oprávnění skutečně chybí. Méně kódu a chování, které uživatelé už znají, protože každá jiná Mac aplikace funguje stejně.

Část, na kterou jsem nejpyšnější: dokázali jsme to, než jsme tomu uvěřili

Bylo by snadné translokaci uhodnout a vydat opravu. Místo toho vydání nejprve přineslo spouštěcí diagnostiku: při spuštění GeekBye nyní hlásí vlastní cestu ke spustitelnému souboru a to, zda je translokovaný, zda je uvnitř /Applications a aktuální stav oprávnění k mikrofonu a obrazovce. Tato telemetrie proměnila pravděpodobnou teorii v potvrzenou — produkční data ukázala, že zasažené relace skutečně běžely z translokovaných cest mimo /Applications, přesně jak bylo předpovězeno.

Na tom pořadí záleží. „Výzva se objeví, ale oprávnění nezůstane" má několik možných vysvětlení — problém s podpisem, chybějící řetězec použití, problém s entitlementem, výstřednost databáze TCC. Vyloučili jsme příčiny na úrovni API (cesta požadavku byla prokazatelně správná), pak jsme nechali reálná data ukázat na vrstvu identity/cesty, místo abychom vydali nadějeplnou opravu a doufali, že tikety podpory ustanou.

Tři věci, které tato chyba učí

  1. Oprávnění, které vyzve, ale nezůstane, je problém identity, ne problém API. Pokud je kód požadavku správný a oprávnění přesto mizí, přestaňte přepisovat požadavek. Ptejte se, k jaké cestě a kódové identitě operační systém udělení váže — a zda je tato identita stabilní napříč spuštěními.
  2. Vydejte diagnostiku spolu s opravou (nebo před ní). Několik polí — odkud běžím, jaký je stav mých oprávnění — proměnilo kvalifikovaný odhad v ověřenou hlavní příčinu a řeklo nám přesně, kteří uživatelé jsou zasaženi. Ozvučte hranici, kterou máte v podezření, dřív, než ji záplatujete.
  3. Chyby, které se skrývají před vývojáři, jsou ty, které běží ve „špatném" prostředí. Ta naše bydlela ve složce /Applications na každém vývojářském stroji, takže chyba byla pro nás strukturálně neviditelná, zatímco zasahovala uživatele při první instalaci. Když se hlášení nedaří reprodukovat, první otázka zní, co je jiné na tom, kde to běží, ne mýlí se uživatel.

GeekBye v2.0.6 vydal výzvu k přemístění a diagnostiku společně. Pro širší oblouk spolehlivosti, do kterého to zapadá, viz co ve skutečnosti obnáší verze 2 (v2.0.0) a proč nahrávání obrazovky zachytí špatný monitor (v2.0.10) — další chyba, která se vynořila jen ve specifickém prostředí. Pro sousední vydání o drobných detailech viz klidný software: oprava blikání a čip režimu odpovědi (v2.0.3 + v2.0.5).

Související články

Rozeznat hovor od otevřené aplikace
Steven
Steven8 min čtení

Rozeznat hovor od otevřené aplikace

GeekBye si umí všimnout, že ses připojil k videoschůzce, a nabídnout, že ji nahraje. Detekce se ukazuje být tou snadnou polovinou — Swift binary čtoucí titulky oken každých deset sekund. Tvrdá polovina je přesnost: nespustit se, když je Zoom jen otevřený, neptat se na schůzku, kterou už nahráváš, a neztlumit mikrofon v hovoru, ve kterém opravdu jsi. Tři vydání, a každé je pojistka, která se musela naučit neporazit sama sebe.

Inženýrství
macOS
Desktop
Ticho bylo nosné
Steven
Steven7 min čtení

Ticho bylo nosné

Poslední dvě vydání GeekBye v1 jsou o téže nepříjemné pravdě: přepis v reálném čase přes skutečnou síť není bezeztrátový a poctivý krok je přestat předstírat, že je. v1.8.20 uchovávalo kopii každého audio chunku na disku, než ho během reconnectu zahodilo, a začalo mezery v přepisu označovat nahlas. v1.9.0 přestalo posílat ticho kvůli úspoře šířky pásma — a zjistilo, že ticho bylo přesně ten signál, podle kterého přepisovač poznal, že věta skončila. Dvě vydání o ceně zahazování věcí.

Inženýrství
Audio
Spolehlivost
Tři slovesa, která udržují Web Audio naživu
Steven
Steven8 min čtení

Tři slovesa, která udržují Web Audio naživu

Dvě bodová vydání GeekBye, dva měsíce od sebe a ve dvou různých souborech, naučila náš audio kód stejné lekci z opačných konců: přestaň zacházet s AudioContext prohlížeče jako s jednorázovým. Jedno vydání se naučilo volat resume() na kontextu, který macOS tiše suspendoval uprostřed nahrávání; druhé se naučilo volat suspend() místo close(), aby po sobě jdoucí sesiony přestaly narážet do stropu Chromia zhruba šesti kontextů. Resume, suspend, close — to je celá zápletka.

Inženýrství
Audio
Desktop