Добавлен: 29.10.2018
Просмотров: 48048
Скачиваний: 190
10.8. Android
911
При запуске эта активность просто берет исходное намерение, запрашивает у диспетче-
ра пакетов список всех совпавших активностей и показывает их пользователю, чтобы
он выбрал одно желаемое действие. Когда выбрана одна из активностей, из исходного
намерения и выбранной активности создается новое явное намерение и вызывается
система, чтобы запустить эту новую активность.
У Android есть еще одно сходство с оболочкой Linux: графическая оболочка Android,
программа запуска, работающая в пользовательском пространстве подобно любому
другому приложению. Имеющаяся в Android программа запуска осуществляет вы-
зовы диспетчера пакетов для нахождения доступных активностей и их запуска после
выбора пользователем.
10.8.10. Песочницы приложений
Традиционно в операционных системах приложения рассматриваются код, выполняе-
мый как пользовательский, от лица пользователя. Такое поведение было унаследовано
от командной строки, где запускалась команда ls и ожидалось, что она работает под
вашими личными привилегиями (UID) с такими же правами доступа, какие имеются
у вас в системе. По аналогии с этим, когда графический пользовательский интерфейс
используется для запуска игры, в которую вы решили поиграть, эта игра будет фак-
тически работать от вашего имени с доступом к вашим файлам и ко многому другому,
что ей на самом деле не пригодится.
Но это отличается от наиболее частого способа использования компьютера в наши
дни. Мы запускаем полученные из не слишком надежных сторонних источников при-
ложения, у которых могут быть обширные функциональные возможности и которые за-
ймутся разнообразной деятельностью в своей среде, где у нас нет практически никакого
контроля. Тем самым создается расхождение между прикладной моделью, поддержива-
емой операционной системой, и той моделью, которая фактически используется. Это
расхождение можно смягчить такими стратегиями, как установление различий между
пользовательскими привилегиями обычного пользователя и пользователя с правами
администратора (admin), с предупреждением при первоначальном запуске приложения,
но это не позволяет решить проблемы основного расхождения.
Иными словами, традиционные операционные системы очень хороши при защите
пользователей от других пользователей, но не при защите пользователей от самих
себя. Все программы работают с полномочиями пользователя, и если любая из них по-
ведет себя неправильно, она может нанести любые повреждения, какие мог бы нанести
пользователь. Задумайтесь: какого масштаба урон вы можете нанести, скажем, в среде
UNIX? Вы можете устроить утечку всей информации, доступной пользователю. Вы
можете запустить на выполнение команду rm -rf *, чтобы у вас появился превосходный
пустой главный каталог. И если программа не просто дефектная, а еще и вредоносная,
она может за выкуп зашифровать все ваши файлы. Запуск всего с «вашими полно-
мочиями» опасен!
В Android эту проблему пытаются решить с помощью основной предпосылки: при-
ложение на самом деле имеет привилегии своего разработчика и запускается на поль-
зовательском устройстве в качестве гостя. Таким образом, приложению не доверяют
работать с чем-нибудь ценным, что не утверждено пользователем явным образом.
В реализации Android эта философия в некоторой степени непосредственно выражена
через идентификаторы пользователей. Когда устанавливается приложение Android, для
912
Глава 10. Изучение конкретных примеров: Unix, Linux и Android
него создается новый уникальный пользовательский идентификатор системы Linux
(UID) и весь его код запускается с привилегиями этого пользователя. Используемые
в Linux идентификаторы пользователей создают, таким образом, песочницу для каж-
дого приложения с их собственной изолированной областью файловой системы точно
так же, как они создают песочницы для пользователей на настольной системе. Иными
словами, в Android используется уже существующая в Linux возможность, но новым
способом. В результате достигается более надежная изоляция.
10.8.11. Безопасность
Безопасность приложений в Android выстраивается вокруг UID-идентификаторов.
В Linux каждый процесс работает под конкретным UID, а в Android UID используется
для идентификации и защиты барьеров безопасности. Единственный способ взаимо-
действия процессов заключается в применении механизма IPC, который обычно несет
в себе достаточно информации для идентификации UID вызывающего процесса. Binder
IPC включает эту информацию явным образом в каждую транзакцию, доставляемую
от одного процесса другому, поэтому получатель IPC может запросто затребовать UID
вызывающего процесса.
В Android предопределено несколько стандартных UID-идентификаторов для низко-
уровневых частей системы, но большинство приложений получают UID динамическим
путем при первой начальной загрузке или во время установки из диапазона UID-
идентификаторов приложений. В табл. 10.16 показан ряд наиболее распространенных
отображений значений UID на их цели. UID-идентификаторы ниже 10 000 являются
фиксированными назначениями внутри системы для специального оборудования или
других специфических частей реализации, в этом диапазоне здесь показан ряд типовых
значений. В диапазоне 10 000–19 999 находятся UID-идентификаторы, динамически
назначаемые приложениям диспетчером пакетов в то время, когда он их устанавлива-
ет. Это означает, что в системе может быть установлено не более 10 000 приложений.
Также нужно обратить внимание на диапазон, начинающийся со значения 100 000,
который используется для реализации традиционной многопользовательской моде-
ли для Android: приложение, получающее UID со значением 10 002 в качестве своего
идентификатора, при запуске в качестве приложения второго пользователя получит
идентификатор 110 002.
Таблица 10.16. Наиболее распространенные UID-назначения в Android
UID
Цель
0
Root
1000
Основная система (процесс system_server)
1001
Телефонные службы
1013
Медийные низкоуровневые процессы
2000
Доступ к оболочке командной строки
10 000–19 999
Динамически назначаемые UID-идентификаторы приложений
100 000
Начало вторичных пользователей
Когда приложению впервые назначается UID, для него создается новый каталог хра-
нилища с файлами, принадлежащими его UID. Там приложение получает свободный
10.8. Android
913
доступ к собственным файлам, но не может обращаться к файлам других приложений,
равно как и другие приложения не могут касаться его собственных файлов. Это придает
особую важность поставщикам контекста, поскольку они являются одним из немногих
механизмов, способных перемещать данные между приложениями.
Даже сама система, запущенная как UID 1000, не может касаться файлов приложений.
Именно поэтому существует демон installd: он работает со специальными привилеги-
ями, чтобы иметь возможность обращаться к файлам и каталогам других приложений
и создавать такие файлы и каталоги для этих приложений. Демон installd предостав-
ляет диспетчеру пакетов весьма ограниченный API-интерфейс для создания по мере
надобности каталогов данных приложений и управления ими.
В своем основном состоянии песочницы приложений Android должны запрещать
любые взаимодействия между приложениями, которые могут нарушить безопасность,
установившуюся между ними. Возможно, это сделано для надежности (чтобы не давать
одному приложению нарушать работу другого приложения), но более часто в качестве
причины выступают вопросы доступа к информации.
Рассмотрим наше приложение камеры. Когда пользователь делает снимок, приложение
камеры сохраняет это снимок в собственном пространстве данных. Получить доступ
к этим данным не может никакое другое приложение, что, собственно, нам и нужно,
потому что снимки могут содержать конфиденциальную информацию пользователя.
После того как пользователь сделал снимок, он может захотеть послать его другу по
электронной почте. Почта является отдельным приложением, находящимся в собствен-
ной песочнице и не имеющим доступа к снимкам в приложении камеры. Как почтовое
приложение может получить доступ к снимкам в песочнице приложения камеры?
Широко известной формой управления доступом в Android являются разрешения,
даваемые приложениям. Разрешениями называются четко определенные возмож-
ности, которые могут быть предоставлены приложению во время его установки.
Приложение перечисляет нужные ему разрешения в своем манифесте, и перед уста-
новкой приложения пользователь получает информацию о том, что будет разрешено
на их основе.
На рис. 10.41 показано, как почтовое приложение может воспользоваться разрешени-
ями на доступ к снимкам в приложении камеры. В данном случае приложение камеры
связано в отношении своих снимков с разрешением READ_PICTURES, говорящим
о том, что любое приложение, содержащее это разрешение, может обращаться к его дан-
ным снимков. Почтовое приложение объявляет в своем манифесте, что ему необходимо
такое разрешение. Теперь почтовое приложение может получать доступ к URI, которым
владеет камера, например
content://pics/1
. После получения запроса на этот URI по-
ставщик контента приложения камеры спрашивает у диспетчера пакетов, является ли
вызывающее приложение держателем необходимого разрешения. Если является, вызов
проходит успешно и соответствующие данные возвращаются приложению.
Разрешения не привязаны к поставщикам контента; любой IPC-обмен внутри системы
может быть защищен разрешением через запрос системы у диспетчера пакетов о на-
личии у вызывающего процесса нужного разрешения. Вспомним, что использование
песочниц приложений основано на процессах и UID-идентификаторах, поэтому барьер
безопасности всегда оказывается на границе процесса, а сами разрешения связаны
с UID-идентификаторами. С учетом этого проверка разрешения может быть выпол-
нена путем извлечения UID, связанного с входящим IPC-запросом, и запроса к дис-
914
Глава 10. Изучение конкретных примеров: Unix, Linux и Android
Диспетчер пакетов в процессе system_server
Процесс приложения камеры
PicturesProvider
Полномочия: «pics»
ComposeActivity
Процесс почтового приложения
Получить
данные
Открыть
content://pics/1
Про-
верка
Разре-
шено
UID пакета Email
Выданные разрешения
READ_CONTACTS
READ_PICTURES
INTERNET
UID пакета Browser
Выданные разрешения
INTERNET
Рис. 10.41. Запрашивание и использование разрешения
петчеру пакетов, выдавалось ли этому UID соответствующее разрешение. Например,
разрешения на доступ к местоположению пользователя обеспечиваются диспетчером
местоположения системы, когда приложение отправляет ему вызов.
На рис. 10.42 показано, что происходит, когда приложение не содержит разрешения,
необходимого для той операции, которую оно выполняет. Здесь приложение браузера
пытается обратиться напрямую к пользовательским снимкам, но единственным раз-
решением, которое оно содержит, касается сетевых операций через Интернет. В этом
случае PicturesProvider получает от диспетчера пакетов сведения, что вызывающий про-
цесс не содержит необходимого разрешения READ_PICTURES, и в результате выдает
обратно исключение нарушения безопасности — SecurityException.
Разрешения обеспечивают широкий, неограниченный доступ к классам операций
и данным. Они хорошо работают, когда функциональные возможности приложения
сконцентрированы вокруг таких операций. Например, нашему почтовому приложению
для отправки и получения электронной почты требуется разрешение INTERNET. Но
есть ли смысл хранить в почтовом приложении разрешение READ_PICTURES? О по-
чтовом приложении, которое непосредственно связано с чтением ваших снимков,
ничего не известно, и нет никакого смысла почтовому приложению иметь доступ ко
всем вашим снимкам.
Есть еще один вопрос, связанный с использованием разрешений, который можно за-
метить, вернувшись к рис. 10.35. Вспомним: для того чтобы поделиться снимком из
приложения камеры, мы можем запустить принадлежащую почтовому приложению
активность ComposeActivity. Почтовое приложение получает URI данных, которыми
нужно поделиться, но не знает, откуда они придут. На рисунке они приходят от камеры,
но воспользоваться этим может любое другое приложение, чтобы позволить пользо-
вателю отправить по электронной почте его данные, от аудиофайлов до документов
текстового процессора. Почтовому приложению, чтобы добавить данные к прикрепле-
нию, нужно лишь прочитать этот URI в виде байтового потока. Но при использовании
10.8. Android
915
Диспетчер пакетов в процессе system_server
Процесс приложения камеры
PicturesProvider
Полномочия: «pics»
Исключение
нарушения
безопасности
Открыть
content://pics/1
Про-
верка
Процесс приложения браузера
BrowserMainActivity
Откло-
нено
UID пакета Email
Выданные разрешения
READ_CONTACTS
READ_PICTURES
INTERNET
UID пакета Browser
Выданные разрешения
INTERNET
Рис. 10.42. Обращение к данным без разрешения
разрешений ему придется также заранее указать разрешение для всех данных всех
приложений, которые могут попросить у него отправки от них электронной почты.
Нам нужно решить две проблемы. Во-первых, мы не хотим давать приложениям до-
ступ к широкому ряду данных, в которых они на самом деле не нуждаются. Во-вторых,
им нужно получить доступ к любым источникам данных, даже к тем, о которых они
заранее ничего не знают.
Здесь нужно сделать важное замечание: действие по отправке снимка по электронной
почте является фактически пользовательским взаимодействием, где пользователь вы-
разил явное намерение использовать конкретный снимок с конкретным приложением.
Поскольку во взаимодействие вовлечена операционная система, она может воспользо-
ваться этим для идентификации конкретной дыры, открываемой в песочницах между
двумя приложениями и позволяющей данным проходить сквозь нее.
Android поддерживает эту разновидность неявного безопасного доступа к данным че-
рез намерения и поставщиков контента (на рис. 10.43 дан пример отправки снимка по
электронной почте). Приложение камера (в нижнем левом углу) запрашивает возмож-
ность поделиться одним из снимков, content://pics/1. Вдобавок к запуску приложения
по составлению сообщения электронной почты, которое мы видели раньше, добавля-
ется запись к списку предоставляемых URI-идентификаторов и отмечается, что новая
активность ComposeActivity теперь имеет доступ к этому URI. Когда ComposeActivity
обращается за открытием и считыванием данных из источника, указываемого предо-
ставленным URI, имеющаяся в PicturesProvider камера, владеющая данными, на кото-
рые указывает URI, может спросить у диспетчера активностей, имеет ли сделавшее
вызов почтовое приложение доступ к данным, и вернуть ему снимок.
Этот выверенный до мелочей контроль доступа с помощью URI может действовать
и другим способом. Есть еще одно намерение, android.intent.action.GET_CONTENT,
которое приложение может использовать, чтобы попросить пользователя выбрать не-
которые данные и вернуть их ему. Это может использоваться в нашем почтовом при-