Steven
Steven7 phút đọc

App Mac của bạn cấp quyền micro — rồi quên sạch sau mỗi lần mở

GeekBye xin quyền micro, bạn đồng ý, và nó chạy được. Lần mở kế tiếp: mất tiêu. Và app chẳng bao giờ hiện ra trong System Settings → Microphone. Thủ phạm là một tính năng bảo mật của macOS âm thầm chạy app từ một đường dẫn biến mất — đây là chẩn đoán và bản sửa chỉ-một-lời-nhắc.

macOS
Quyền truy cập
Kỹ thuật
GeekBye Releases
App Mac của bạn cấp quyền micro — rồi quên sạch sau mỗi lần mở

Đây là một con bug khiến bạn nghi ngờ chính mắt mình. Bạn cài GeekBye, nó xin quyền micro, bạn bấm Allow, và phần chuyển giọng nói thành văn bản chạy ngon. Tuyệt. Bạn thoát ra, mở lại vào sáng hôm sau — và nó lại xin quyền micro lần nữa. Bạn vào System Settings → Privacy & Security → Microphone để sửa thủ công, và GeekBye thậm chí không có trong danh sách. Không bị từ chối. Không được cho phép. Đơn giản là vắng mặt, cứ như chưa từng xin quyền.

Từng mảnh riêng lẻ đều trông đúng. Lời nhắc là thật. Quyền chạy được ngay lúc đó. App được ký và công chứng (notarized) đàng hoàng với đúng chuỗi mô tả mục đích sử dụng. Vậy mà quyền cứ bốc hơi sau mỗi lần mở. GeekBye v2.0.6 đã sửa nó — và nguyên nhân gốc là một trong những thứ tinh vi nhất mà macOS làm để bảo vệ bạn.

Tính năng đã giấu app khỏi chính nó

Thủ phạm là macOS App Translocation, một tính năng bảo mật của Gatekeeper. Khi bạn tải một app về và chạy thẳng từ file DMG hoặc từ thư mục ~/Downloads — bất cứ chỗ nào mà nó vẫn còn bị "cách ly" (quarantined) — macOS thực ra không chạy nó từ nơi bạn nhìn thấy. Nó âm thầm sao chép app vào một đường dẫn ngẫu nhiên, chỉ-đọc, nằm sâu dưới /private/var/folders/.../AppTranslocation/… và chạy bản sao đó. Đây là một cơ chế phòng thủ tốt: nó ngăn một file tải về độc hại can thiệp vào các tệp nằm cạnh nó.

Nhưng đây là chỗ va chạm. Hệ thống quyền của macOS (TCC — thứ theo dõi ai được dùng micro, camera, màn hình của bạn) nhận diện một app bằng đường dẫn và danh tính mã (code identity) của nó. Khi app bị translocated, đường dẫn đó là ngẫu nhiên và tạm thời. Nên khi bạn cấp quyền micro, macOS ngoan ngoãn ghi lại quyền đó — gắn vào một đường dẫn sẽ không còn tồn tại ở lần mở kế tiếp. Mở lại app, macOS translocate nó tới một đường dẫn ngẫu nhiên khác, nhìn thấy một app mà nó không có hồ sơ nào, và hỏi lại. Và vì cái đường dẫn ma đó không bao giờ là một vị trí ổn định, app không bao giờ có được một dòng cố định trong System Settings → Microphone.

App đang cấp quyền cho một bóng ma.

Đây cũng là lý do vì sao chỉ một số người dính bug. Nếu bản GeekBye của bạn đã nằm sẵn trong /Applications — vì bạn kéo nó vào đó, hoặc vì nó tới đó qua tự động cập nhật — thì không có cách ly, không có translocation, một đường dẫn ổn định, và mọi thứ được giữ nguyên hoàn hảo. Bug này vô hình với chúng tôi và với bất kỳ ai đã qua lần cài đặt đầu tiên, đúng là kiểu bug sống dai nhất.

Bản sửa: cho app một mái nhà thật sự

Vì toàn bộ vấn đề là một đường dẫn bất định, bản sửa là đưa app về một đường dẫn ổn định. v2.0.6 phát hiện khi GeekBye đang chạy translocated (hoặc chỉ đơn giản là chạy từ ngoài /Applications) và đưa ra một cú nhấp "Move to Applications" — dùng lời gọi di dời của macOS để sao chép bundle vào /Applications và khởi chạy lại từ đó. Từ thời điểm đó app có một danh tính cố định: quyền micro được giữ lại, quyền ghi màn hình được giữ lại, và GeekBye cuối cùng cũng hiện ra trong System Settings đúng nơi bạn mong đợi.

Lời nhắc rất lịch sự. Nó đưa ra Move to Applications, Not Now, và Don't Ask Again — và nó nhớ lựa chọn gần nhất, nên app không bao giờ làm phiền người có lý do cố tình chạy nó từ nơi khác. Quyết định có nên hiện lời nhắc hay không được tách riêng vào các hàm nhỏ, thuần (bản build này có bị translocated không? nó có nằm ngoài /Applications không? người dùng đã tắt lời nhắc chưa?) để logic được kiểm thử đơn vị mà không cần khởi chạy một bản build đã công chứng thật trên một ổ đĩa bị cách ly thật.

Cùng bản phát hành đó cũng làm gọn lại chính trải nghiệm xin quyền. GeekBye từng bật lên một cửa sổ xin quyền tùy biến, tự viết trong app — vài trăm dòng UI cố tái tạo thứ mà hệ điều hành đã làm tốt. v2.0.6 xóa nó đi và dựa vào lời nhắc xin quyền gốc của macOS, kèm một banner yên tĩnh, không chặn, chỉ xuất hiện khi một quyền bắt buộc thực sự đang thiếu. Ít code hơn, và hành vi mà người dùng đã quen vì mọi app Mac khác đều hoạt động y như vậy.

Phần tôi tự hào nhất: chúng tôi chứng minh trước khi tin

Sẽ dễ dàng nếu chỉ đoán là translocation rồi tung ra bản sửa. Thay vào đó, bản phát hành đã ship một công cụ chẩn đoán lúc khởi động trước tiên: khi mở, GeekBye giờ báo cáo đường dẫn tệp thực thi của chính nó và liệu nó có bị translocated không, liệu nó có nằm trong /Applications không, cùng trạng thái quyền micro và màn hình hiện tại. Dữ liệu đo lường đó biến một giả thuyết hợp lý thành một sự thật đã xác nhận — dữ liệu thực tế cho thấy các phiên bị ảnh hưởng, quả thật, đang chạy từ những đường dẫn translocated bên ngoài /Applications, đúng như dự đoán.

Thứ tự đó quan trọng. "Lời nhắc hiện ra nhưng quyền không được giữ lại" có vài lời giải thích khả dĩ — một vấn đề về ký, một chuỗi mô tả mục đích bị thiếu, một vấn đề về entitlement, một trục trặc của cơ sở dữ liệu TCC. Chúng tôi loại trừ các nguyên nhân ở tầng API (đường dẫn yêu cầu rõ ràng là đúng), rồi để dữ liệu thực tế chỉ thẳng vào tầng danh tính/đường dẫn thay vì tung ra một bản sửa đầy hy vọng và mong sao ticket hỗ trợ ngừng lại.

Ba điều con bug này dạy ta

  1. Một quyền có hiện lời nhắc nhưng không chịu ở lại là vấn đề danh tính, không phải vấn đề API. Nếu code yêu cầu đã đúng mà quyền vẫn biến mất, đừng viết lại phần yêu cầu nữa. Hãy hỏi hệ điều hành đang gắn quyền vào đường dẫn và danh tính mã nào — và liệu danh tính đó có ổn định qua các lần mở không.
  2. Ship công cụ chẩn đoán cùng (hoặc trước) bản sửa. Vài trường thông tin — tôi đang chạy từ đâu, trạng thái quyền của tôi ra sao — đã biến một phỏng đoán có cơ sở thành nguyên nhân gốc đã kiểm chứng, và cho ta biết chính xác những người dùng nào bị ảnh hưởng. Hãy đo lường cái ranh giới bạn nghi ngờ trước khi vá nó.
  3. Những con bug ẩn khỏi lập trình viên là những con đang chạy trong môi trường "sai". Bug của chúng tôi sống trong /Applications trên mọi máy dev, nên nó vô hình về mặt cấu trúc với chúng tôi trong khi vẫn giáng vào người dùng lần đầu. Khi một báo cáo không tái hiện được, câu hỏi đầu tiên là có gì khác ở nơi nó chạy, chứ không phải người dùng có nhầm không.

GeekBye v2.0.6 ship lời nhắc di dời và công cụ chẩn đoán cùng lúc. Về vòng cung độ tin cậy rộng hơn mà bản này nằm trong đó, xem what a version 2 actually takes (v2.0.0) và why screen recording captures the wrong monitor (v2.0.10) — một con bug khác chỉ lộ ra trong một môi trường cụ thể. Về bản phát hành chăm chút chi tiết nhỏ ngay bên cạnh, xem calm software: the flicker fix and the answer-mode chip (v2.0.3 + v2.0.5).

Bài Viết Liên Quan

Phần mềm điềm tĩnh: Loại bỏ nút gạt nhấp nháy và dạy chat nói rõ nó đang ở chế độ nào
Steven
Steven8 phút đọc

Phần mềm điềm tĩnh: Loại bỏ nút gạt nhấp nháy và dạy chat nói rõ nó đang ở chế độ nào

Hai bản phát hành nhỏ của GeekBye, không có tính năng nổi bật nào — chỉ là một nút gạt trong cài đặt hết nhấp nháy và một trợ lý chat cuối cùng cũng cho bạn biết nó trả lời ở chế độ họp hay chế độ lập trình. Đây chính là cái giá thực sự của "phần mềm điềm tĩnh", từng chi tiết một.

Sản phẩm
Thiết kế
Kỹ thuật
Khi tường lửa chặn WebSocket, phiên âm thời gian thực sẽ ra sao
Steven
Steven6 phút đọc

Khi tường lửa chặn WebSocket, phiên âm thời gian thực sẽ ra sao

Mạng doanh nghiệp thích cho HTTPS đi qua nhưng âm thầm giết chết bước nâng cấp WebSocket. Điều đó lặng lẽ làm hỏng phiên âm thời gian thực. GeekBye v2.0.8 tự động fall back sang một transport thuần HTTPS — và trong lúc làm ra nó, chúng tôi đào được một con bug có thể khiến cả tính năng trở nên vô dụng.

Phiên âm
Mạng
Kỹ thuật
Vì sao ghi màn hình lại quay nhầm màn hình (và cách chúng tôi sửa)
Steven
Steven6 phút đọc

Vì sao ghi màn hình lại quay nhầm màn hình (và cách chúng tôi sửa)

Trên thiết lập hai màn hình, GeekBye luôn ghi và chụp màn hình chính bất kể bạn đang làm việc trên màn hình nào. Bản sửa chỉ là một hàm nhỏ — nhưng phiên bản đầu tiên của nó sai, và code review đã bắt được lý do.

Ghi màn hình
Đa màn hình
Kỹ thuật