エントリー
この記事では、カーネルよりも少し高いセキュリティ、つまりネイティブユーザー空間でのセキュリティの仕組みを検討します。 オペレーティングシステムのブートプロセスのトピックを取り上げ、Androidファイルシステムの構造を検討します。 先ほど言ったように、私はLinuxにはあまり強くないので、不正確なことに気付いたら修正してください。教えて記事を改善してください。 このトピックは非常に広範囲にわたるため、2つの部分に分けることにしました。 最初の部分では、オペレーティングシステムとファイルシステムの機能をロードするプロセスを検討します。 興味のある方、ようこそ!
記事一覧
このトピックからの私の記事へのリンクは次のとおりです。- Androidオペレーティングシステムのセキュリティの基本。 コアレベル
- Androidオペレーティングシステムのセキュリティの基本。 ネイティブユーザースペース、パート1
- Androidオペレーティングシステムのセキュリティの基本。 ネイティブユーザースペース、パート2
- Androidオペレーティングシステムのセキュリティの基本。 Application Frameworkレベルでのセキュリティ。 バインダーIPC
ネイティブユーザースペースの意味
ネイティブユーザースペースとは、Dalvik仮想マシンの外部で実行され、Linuxカーネルの一部ではないすべてのユーザースペースコンポーネントを指します。Androidファイルシステム
まず、Androidファイルシステムの構造を見てみましょう。 AndroidはLinuxカーネルに基づいていますが、ここで目にするファイルシステム構造はわかりません。 エミュレータを実行して、何があるか見てみましょう。 これを行うには、次のコマンドを実行します。
adb shell ls -al
Android 4.2のエミュレーター用の端末では、次の結果が表示されます。
drwxr-xr-x root root 2013-04-10 08:13 acct drwxrwx--- system cache 2013-04-10 08:13 cache dr-x------ root root 2013-04-10 08:13 config lrwxrwxrwx root root 2013-04-10 08:13 d -> /sys/kernel/debug drwxrwx--x system system 2013-04-10 08:14 data -rw-r--r-- root root 116 1970-01-01 00:00 default.prop drwxr-xr-x root root 2013-04-10 08:13 dev lrwxrwxrwx root root 2013-04-10 08:13 etc -> /system/etc -rwxr-x--- root root 244536 1970-01-01 00:00 init -rwxr-x--- root root 2487 1970-01-01 00:00 init.goldfish.rc -rwxr-x--- root root 18247 1970-01-01 00:00 init.rc -rwxr-x--- root root 1795 1970-01-01 00:00 init.trace.rc -rwxr-x--- root root 3915 1970-01-01 00:00 init.usb.rc drwxrwxr-x root system 2013-04-10 08:13 mnt dr-xr-xr-x root root 2013-04-10 08:13 proc drwx------ root root 2012-11-15 05:31 root drwxr-x--- root root 1970-01-01 00:00 sbin lrwxrwxrwx root root 2013-04-10 08:13 sdcard -> /mnt/sdcard d---rx--- root sdcard_r 2013-04-10 08:13 storage drwxr-xr-x root root 2013-04-10 08:13 sys drwxr-xr-x root root 2012-12-31 03:20 system -rw-r--r-- root root 272 1970-01-01 00:00 ueventd.goldfish.rc -rw-r--r-- root root 4024 1970-01-01 00:00 ueventd.rc lrwxrwxrwx root root 2013-04-10 08:13 vendor -> /system/vendor
ここでは、メインディレクトリと、今後役立つディレクトリのみをマークします。 インターネットでは、他のディレクトリの説明と目的を見つけることができます。 / dev 、 / proc 、 / sys 、 / mnt 、 / etcなど、一部のディレクトリはLinuxと同じであり、その目的は基本的にLinuxと同じであることに気付くかもしれません。 ところで、 / binおよび/ libディレクトリは表示されないことに注意してください。 彼らが隠れた場所については、少し後で説明します。
一方、Linuxにはまったくないディレクトリに気付くでしょう。 その中でも、 / data 、 / system 、 / cache 、 / init 、 / init.rcに興味があります。それらの目的をさらに詳しく見てみましょう。
/ systemこれは、Androidシステムの不変コンポーネントが保存されるメインディレクトリです。 類推すると、このフォルダーは読み取り専用のC:\ windows \フォルダーに似ています。 つまり このディレクトリのデータを変更することはできません。 これは、さまざまな実行可能ファイルと共有ライブラリが保存されている/ binおよび/ libディレクトリを見つけることができる場所です。 さらに、オペレーティングシステムに組み込まれ、既定では削除できないシステムアプリケーションもあります。 このディレクトリの内容は、オペレーティングシステムのコンパイル中に生成されます。
/データ /システムはここでは読み取り専用です。可変データが保存されるディレクトリが必要です。 /データはそれだけです。 たとえば、インストールされたアプリケーションのapkファイルは/ data / appのこのディレクトリに保存され、そのデータは/ data / dataに保存されます (このディレクトリについては、前の記事で詳しく調べました)。
/キャッシュこれは単なる一時的なストレージです。 また、このディレクトリが保存され、システム更新がそこから起動されます。
/ initファイルとは何か、そして* .rc拡張子のあいまいなファイルが必要な理由を理解するには、システムのブートプロセスを検討します。
Androidの起動プロセス

Androidオペレーティングシステムをロードするプロセスのいくつかのステップを見てみましょう。 この写真は「Embedded Android」という本から取られたもので、より詳細な説明を見つけることができます。 一般的に私はプロセスを理解していますが、私にとってはもっと魔法です:)
CPU 電源ボタンを押すと、デバイスのプロセッサに電圧が印加され始めます。 この瞬間までプロセッサはオフになっており、電圧を印加しないとその状態を維持できないため、起動直後は何らかの初期化されていない状態になります。 この場合、プロセッサは特別なレジスタからハードワイヤードアドレスを読み取り、それから始まる命令の実行を開始します。 ほとんどの場合、このアドレスは、ブートローダー(ブートローダー)が配線されているチップを指します。
ブートローダー。 ブートローダーはRAMを初期化し、Linuxカーネルをロードします。 さらに、ブートローダーはRAMdiskを作成します。
Linuxカーネル。 カーネルは、さまざまなサブシステム、組み込みドライバを初期化し、ルートファイルシステム(ルートファイルシステム)をマウントします。 その後、カーネルは最初のプログラムを実行できます。
これで魔法が終わり、すべてが多かれ少なかれ明確になります。
初期化
Androidの場合の最初のプログラムはinitです。 実行可能ファイルはルートディレクトリ( / init )にあります。 カーネルが起動後に起動するのはこのプログラムです。 ソースはsystem / core / init / folderにありますので、少し掘り下げてみましょう。 system / core / init / init.cに興味があります :
... int main(int argc, char **argv) { ... /* clear the umask */ umask(0); /* Get the basic filesystem setup we need put * together in the initramdisk on / and then we will * let the rc file figure out the rest. */ mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); ... init_parse_config_file("/init.rc"); ... }
最初に、作業に必要なディレクトリを作成してマウントし、次に/init.rcファイルを解析して、解析したものを実行します。 /init.rcファイルの形式はreadmeで非常によく説明されており、例を見つけることもできます。 要するに、このファイルはアクションのセットです(セクション-コマンドの名前付きシーケンス)。 コマンドの各シーケンスは、特定のトリガー(トリガー)によってトリガーされます。 たとえば、次のシーケンスはアクションであり、トリガーはfsであり、コマンドのシーケンスはマウントコマンドのセットです。
on fs # mount mtd partitions # Mount /system rw first to give the filesystem a chance to save a checkpoint mount yaffs2 mtd@system /system mount yaffs2 mtd@system /system ro remount mount yaffs2 mtd@userdata /data nosuid nodev mount yaffs2 mtd@cache /cache nosuid nodev
ソースファイル/init.rcはsystem / core / rootdir / init.rcにありますが、その主要部分のいくつかを見てみましょうが、その完全性を確認することを強くお勧めします。 その後、多くのことが明らかになります。 したがって、ファイルは次の行で始まります。
import /init.usb.rc import /init.${ro.hardware}.rc import /init.trace.rc
つまり、 init.rcファイルに加えて、 init.usb.rcファイル、 init.trace.rcファイル、およびinitという奇妙な名前のファイルから設定をインポートする必要があるということです。$ {Ro.hardware} .rcただし、 $ {ro.hardware}鉄のタイプを決定する値を持つ変数です。 エミュレーターの場合、たとえば、その値はgoldfishです。 次に、環境変数が定義されます。
... on init ... # setup the global environment export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin export LD_LIBRARY_PATH /vendor/lib:/system/lib export ANDROID_BOOTLOGO 1 export ANDROID_ROOT /system export ANDROID_ASSETS /system/app export ANDROID_DATA /data export ANDROID_STORAGE /storage export ASEC_MOUNTPOINT /mnt/asec export LOOP_MOUNTPOINT /mnt/obb export BOOTCLASSPATH /system/framework/core.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar ...
この後、デバイスの動作に必要な変数が初期化されます。 このトピックに興味がある場合は、特定のコマンドに関する情報を簡単に見つけることができます。 次のブロックを詳しく見てみましょう(この記事で既に引用しています)。
on fs # mount mtd partitions # Mount /system rw first to give the filesystem a chance to save a checkpoint mount yaffs2 mtd@system /system mount yaffs2 mtd@system /system ro remount mount yaffs2 mtd@userdata /data nosuid nodev mount yaffs2 mtd@cache /cache nosuid nodev
MTD-メモリ技術デバイス。 一般的に、MTDは不揮発性の特別なチップです(つまり、このチップ上のデータは再起動またはシャットダウン後に保存されます)フラッシュメモリ(NORやNANDなど)で、ディスクイメージが保存されます。 この記事では、このタイプのデバイスについて、制限と同様に詳細に説明します。 これらのタイプのフラッシュメモリ専用のファイルシステム、特にYAFFSなどが開発されました。 これらのタイプのメモリの最も重要な制限の1つは、一部のデータが既に書き込まれているセクタにデータを書き込むために、最初にセクタ全体を完全に消去する必要があることです。 そのため、メーカーは新しいタイプのブロックフラッシュメモリ(eMMC)に切り替え始めました。eMMCでは、通常のext4ファイルシステムを配置して、この制限を取り除くことができます。 なぜなら すべての作業がエミュレートされるエミュレーターのinit.rcファイルの例を示し、デフォルトでYAFFS2ファイルシステムを使用します(Android 2.2より前のすべてのデバイスにYAFFS2が使用されていたため、これらは過去の名残だと思います)。 実際のデバイスでは(これは特定のハードウェアにinit.rcファイルを使用する必要がある場合の1つの例にすぎません)、これらのコマンドは上書きされます。 たとえば、 ニシンデバイス(Google Nexus S)の場合、 init.herring.rcファイルでは、このセクションは次のようになります。
on fs mkdir /efs 0775 radio radio mount yaffs2 mtd@efs /efs noatime nosuid nodev chmod 770 /efs/bluetooth chmod 770 /efs/imei mount_all /fstab.herring ...
fstab.herringは、次の内容のファイルです 。
... /dev/block/platform/s3c-sdhci.0/by-name/system /system ext4 ro wait /dev/block/platform/s3c-sdhci.0/by-name/userdata /data ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait,encryptable=/efs/userdata_footer
お気づきかもしれませんが、 / system 、 / data 、 / cacheは、MTDデバイス(エミュレーターの場合)またはブロックデバイス(実際のデバイスの場合)を示す単純なマウントポイント(ファイルシステムのマウントポイント)です。対応するディスクイメージ(system.img、userdata.img、cache.img)。 よくわかりませんが、スマートフォンの内部にはフラッシュメモリを搭載した単一のチップがあり、パーティション(ボリューム)に分割され、それぞれに対応する画像が含まれていると思います。 フラッシュメモリを搭載したこのチップは、 Internal storageという名前で知られているもので、その容量はスマートフォンの主要なパラメーターの1つです。
/システムは読み取り専用(読み取り専用)でマウントされていることに注意してください。 つまり、このセクションの内容は、デバイスの操作中に変更されるのではなく、たとえばシステムの更新を使用してデバイスのシステムを更新する場合にのみ変更されます。
init.rcを引き続き検討します。 post-fs-dataトリガーは、 / dataパーティションファイルシステムの基本構造を生成します。 そこでは、一般に、すべてが明確です-mkdir 、 chown 、 chmodコマンドのセット。
次に、 init.rcはいくつかのデーモンを起動します。 記事の冒頭の図に戻ると、それらはネイティブデーモンブロックにリストされています。 今のところここで停止します。 図からわかるように、オペレーティングシステムのロードプロセスについては完全には考慮していません。 次の記事で検討する、いくつかの明らかになった手順。
おわりに
次のパートでは、system.img、userdata.img、cache.imgの画像の由来を説明し、ネイティブユーザースペースレベルでのセキュリティについて検討します。 いつものように、修正、追加、および何を書くべきかについての提案は大歓迎です。 そして、次の記事で何を書くかの計画をすでに持っていますが、それを修正する準備ができています。
参照資料
- MTDデバイスの使用
- Karim Yaghmourによる「組み込みAndroid」
- Marko GargentaによるAndroidセキュリティの基盤
更新する