Дмитрий Мячин
Продолжение. Начало в номере 699.
Открытость создаёт большую проблему. Потому что одно дело натыкаться на проблемы, которые вызваны ошибкой в драйверах и только, ведь производителей аппаратных начинок не так, чтобы очень много, а другое — натыкаться на проблемы, которые вызваны тем, производитель прошивки решил, что он умнее Google, который рулит AOSP. Другими словами, нет проблемы поддержки устройств, есть проблема работы приложений на конкретных версиях конкретных прошивок на конкретных аппаратах в конкретных странах.
Это звучит страшно, наверное. И хотя разработчики справляются (ну а куда деваться?), но производители всё равно не дают скучать и постоянно выкидывают что-нибудь эдакое. Я расскажу о реальных ситуациях, которые произошли только за последний год, и которые не были обнаружены ни мной, ни моими коллегами, и в результате о которых сообщали уже пользователи и для которых пришлось искать обходные решения.
PIN коды Samsung, Meizu и других производителей
Как я уже рассказывал, имея права администратора устройства, приложения могут ставить свои пароли. Чем отличается пароль от PIN-кода? С точки зрения самого Android разницы нет. И пин-код, и пароль, и рисунок — всё это пароли. Но для каждого из этих вариантов показывается разный интерфейс. Например, для пин-кодов поднимается клавиатура, где доступны только цифры, а для паролей — и цифры, и буквы.
Это различие определяется так называемой политикой пароля. Перед тем, как установить пароль, приложение с правами Device Admin передаёт системе политику, которая и сообщает, каким должен быть этот пароль. Если сообщается, что нужно и буквы, и цифры, то пользователю будет отображаться интерфейс пароля (то есть клавиатура с полным набором символов). Если в политике будет сказано «только цифры», то пользователь будет видеть интерфейс для ввода пин-кода.
Таково поведение самого Android. В AOSP графический интерфейс строго следует этому поведению на всех уровнях, от той «низкой» части Android, которая занимается безопасностью, до той «верхней» части Android, графической оболочки, рисующая кнопочки, в которые и тычет пользователь.
Но Meizu и некоторые другие китайские производители решили внести свои улучшения. Они решили, что пин-код может иметь длину строго в четыре цифры. Ни больше, ни меньше. Это своё решение они реализовали в самой «верхней» части — в графической оболочке. При этом нижний уровень Android они не меняли, он сохранил своё поведение. Так вот, с точки зрения базового Android, всё это пароли, длина которых не имеет такой фиксации.
И что получилось? Многие пользователи для приложений-антиворов задавали пароли длиной пять и более символов. И решили проверить работу антивора, отправив команду блокировки. Антивор честно отработал команду, заблокировал устройство, передав пароль системе, которая честно его и поставила. И любые другие она принимать не будет. Политика задавала только цифры, потому что их вводить и удобнее, и быстрее. Итог — прошивки от Meizu и подобных принимали четыре введённые цифры и даже не дожидались ввода пятой и дальше. Сразу после четвёртой, безо всяких нажатий на Enter, они сразу посылали их в Android. И тот, само-собой, не принимал эти коды. Всё, устройство нельзя разблокировать! Так что если у вас на смартфоне используется сильно изменённая оболочка Android, лучше не рискуйте с PIN-кодами и используйте строго 4 цифры.
Теперь про Samsung. Начнём с того, что некоторые устройства из линейки Neo имеют баг в прошивке, который отправляет устройства в вечный цикл перезагрузок при попытке установить пустой пароль. Я говорил, что пустые пароли нужны для снятия блокировки. Так вот конкретно этий девайсы, уходят в вечную перезагрузку. И для этой проблемы нет решения, потому что низы не могут (то есть приложения не могут исправить это со своей стороны), а верхи — не хотят (Samsung вообще очень быстро отказывается от поддержки своих нетоповых устройств).
Но это я отвлёкся. Ранее я рассказывал про баг в Android 5.0, когда пустой пароль становился реально паролем. Нужно нажимать Enter. Если бы Samsung просто ничего не трогали, то проблемы бы и не было — разработчики уже давно сделали обходные решения, со времён Android L. Но разработчики в Samsung решили, что делать доступной кнопку Enter, если ничего не введено в поле пин-кода — это баг. И просто блокируют её нажатие, если ничего не введено, либо был введено, а затем стёрто. А «что-нибудь» — это уже не пустой ввод и, понятное дело, не принимается Android.
Имитация поведения старших версий Android
Быстрее всех обновляются, как известно, Nexus-устройства. Многие производители не поддерживают свои девайсы и в этом даже есть определённый плюс с точки зрения разработки и тестирования. Плюс в том, что будешь чётко уверен, что и у Васи и у Джона в телефонах прошивки одинаковые С точки зрения безопасности это, конечно, огромный минус, но если смотреть именно с позиции безопасности, то кроме Nexus ничего брать нельзя вообще. Тогда ваши данные будут слиты только АНБ 🙂
Но бывают ситуации, когда производитель не желает обновлять прошивку до новой версии Android, а выпускает обновление, которое пытается имитировать фишки новой версии. Абсолютно всегда получается мерзость. Приведу конкретные примеры и снова только за последний год.
В Android 6 появился режим Doze, я о нём писал в блоге. Это специальный режим, который создан для экономии заряда батареи, если устройство, а) неподвижно, б) не на зарядке, в) с погашенным экраном, г) лежит в таком состоянии некоторое время. Он реализован очень толково и его внедрение не повлекло никаких проблем, хотя немного и изменило поведение многих приложений. Но это изменение чётко описано в документации и не приводит к ошибкам. Тот, не очень частый случай, когда всё сделано так, что я аж доволен результатом.
Но некоторые производители решили, что обновлять свои устройства до Android 6 — это слишком невыгодно для них. Потому они выпустили обновления «не идентичные «натуральным. К, примеру один крупный производитель добавил «режим сна», вроде Doze. Только в отличие от случая с Doze, приложения, попавшие в список «Оптимизированные», тупо останавливались.
Поясню. В Android есть разница между «убить» приложение и «остановить» его. Kill, как правило, неэффективен, о чём я писал в первой части лекции. Если приложение имеет модуль приёмника широковещательных сообщений или, скажем, службу, то оно будет поднято. Служба может поднять его прямо сразу, а бродкаст ресивер — при рассылке ожидаемых широковещательных сообщений. А вот если остановить приложение специальной кнопкой Force Stop, то будут остановлены все компоненты приложения и их запуск будет невозможен до тех пор, пока пользователь самолично не запустит приложение (это не касается администраторов устройств и приложений, имеющих доступ к чтению уведомлений). По причинам безопасности, остановку можно сделать либо вручную, либо в режиме отладки. Одно приложение может убить другое, но не может его остановить. А вот система — может. И это использовал производитель. Он останавливал приложения и запускал их заново исходя из своего видения прекрасного. Очень многие приложения были не готовы к такому поведению и падали. Такое поведение даже не предусмотрено в AOSP!
Но ещё дальше пошёл один китайский бренд. Они решили, что если экономить батарею, то по-крупному. И просто вырезал бродкаст «система загрузилась». Автозапуска в классическом понимании в Android нет. Можно подписаться на бродкаст, который система будет рассылать, когда она загрузилась, и тогда приложение будет подниматься при получении этого сообщения. Но не у этого производителя. Такая экономия батареи получается, если приложения не запускаются, пока пользователь сам этого не сделает! Так что если на вашем устройстве WhatsApp какой-нибудь не запускается после перезагрузки, то именно поэтому.
Ранее я рассказывал, что Meizu изменил поведение графической оболочки при обработке PIN-кодов. В прошлом году или около того было обновление прошивки, которое принесло ещё одно непоправимое улучшение и касалось оно безопасности.
В Android 5 впервые был реализован так называемый Kill Switch. Причём реализован несколько… странно.
Kill Switch, если кто не знает, это превращение устройства в кирпич с экраном и батарейкой, если тот, кто держит его в руках, не прошёл «тест на владение», то есть не доказал, что он является реальным владельцем. В чём же странность? Google поддержал Kill Switch в Android 5.0, но работает он в 5.1 и выше. Причём работает ТОЛЬКО если устройство изначально шло с Android 5.0 и выше. Вдумайтесь, Nexus 5, который изначально был на Android 4.3 и имеет сейчас Android 6, не защищён Kill Switch’ем, а Nexus 6, который шёл с предустановленным Android 5.0 — защищён.
Конкретно в Android подтверждение реализовано достаточно просто. Если устройству был сделан сброс в то время, когда оно было защищено паролем, то в мастере первоначальной настройки нужно ввести логин и пароль учётной записи Google, которая там была перед сбросом. Не знаешь их — можешь выбросить устройство. Прошить его нельзя.
Meizu решили, что нужно и им такое заиметь. Но так как они из Китая, то там всё плохо с Google Services. Вот и сделали свою реализацию. На самом деле сделали её, в целом, правильно, гораздо лучше, чем Google. После сброса, а также при попытке попасть в загрузчик, нужно ввести пароль блокировки, который был до сброса… Вы поняли, да? Там был ровно тот же самый баг с обработкой PIN-кодов и его нельзя ввести, если он не равен строго четырём символам. Всё, только замена по гарантии!
P. S. А изменения в API всё ещё вносят. Теперь, в Android N, администраторы устройства могут устанавливать пароли, но не могут их изменить или сбросить, если пароль уже был установлен. Изменение и сброс теперь разрешены только владельцу устройства (Device Owner) — сущности, которая используется в Android for Works.