Contextクラスから取得出来るディレクトリのパスや、Contextクラス経由で作成できるファイルオブジェクトについてそのUNIXファイル上でのパーミッション設定を調べて見ました。
サンプルアプリケーション:StorageExercise
MODE_WORLD_READABLE/WRITABLEに注意すべきケースとしては、結論としては以下の3種類になります。
Context.getDir()もmodeを指定できますが、こちらは心配要りません。
各種PATHの状況を取得し、以下のファイルに書き込みます。
/mnt/sdcard/Android/data/storage.exercise/files/dump.txt
実際のdump.txtの内容:
ApplicationInfo.className = [null] ApplicationInfo.dataDir = [/data/data/storage.exercise] ApplicationInfo.nativeLibraryDir = [/data/data/storage.exercise/lib] ApplicationInfo.processName = [storage.exercise] ApplicationInfo.publicSourceDir = [/data/app/storage.exercise-2.apk] ApplicationInfo.sourceDir = [/data/app/storage.exercise-2.apk] -------------- getPackageName() = [storage.exercise] getPackageCodePath() = [/data/app/storage.exercise-2.apk] getPackageResourcePath() = [/data/app/storage.exercise-2.apk] getFilesDir() =[/data/data/storage.exercise/files] getCacheDir() =[/data/data/storage.exercise/cache] fileList(): default_file file_private file_wr file_ww databaseList(): stddb db_private db_wr db_ww -------------- Environment.getExternalStorageState() = [mounted] Environment.isExternalStorageRemovable() = [true] Is ExternalStorage available ? [true] Is ExternalStorage writable ? [true] Environment.getRootDirectory() = [/system] Environment.getDataDirectory() = [/data] Environment.getDownloadCacheDirectory() = [/cache] Environment.getExternalStorageDirectory() = [/mnt/sdcard] getExternalStoragePublicDirectory(DIRECTORY_DCIM) = [/mnt/sdcard/DCIM] getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS) = [/mnt/sdcard/Download] getExternalStoragePublicDirectory(DIRECTORY_MOVIES) = [/mnt/sdcard/Movies] getExternalStoragePublicDirectory(DIRECTORY_MUSIC) = [/mnt/sdcard/Music] getExternalStoragePublicDirectory(DIRECTORY_PICTURES) = [/mnt/sdcard/Pictures] getExternalStoragePublicDirectory(DIRECTORY_RINGTONES) = [/mnt/sdcard/Ringtones] -------------- getExternalCacheDir() = [/mnt/sdcard/Android/data/storage.exercise/cache] getExternalFilesDir(null) = [/mnt/sdcard/Android/data/storage.exercise/files] getExternalFilesDir(DIRECTORY_DCIM) = [/mnt/sdcard/Android/data/storage.exercise/files/DCIM] getExternalFilesDir(DIRECTORY_DOWNLOADS) = [/mnt/sdcard/Android/data/storage.exercise/files/Download] getExternalFilesDir(DIRECTORY_MUSIC) = [/mnt/sdcard/Android/data/storage.exercise/files/Music] getExternalFilesDir(DIRECTORY_PICTURES) = [/mnt/sdcard/Android/data/storage.exercise/files/Pictures] getExternalFilesDir(DIRECTORY_PODCASTS) = [/mnt/sdcard/Android/data/storage.exercise/files/Podcasts]
busyboxを導入し(http://benno.id.au/blog/2007/11/14/android-busybox)、以下のコマンドで"/data/data/(package)/"以下のパーミッションを確認して見ました。
# find /data/data/storage.exercise/ | xargs /data/busybox/ls --color=never -ld
まず "/data/data/(package)/" ディレクトリ自体のパーミッションは:
drwxr-x--x 1 10039 10039 2048 Oct 16 10:34 /data/data/storage.exercise/
Otherに対して"x"bitがONになっています。従って一応、Otherにもその中のファイルオブジェクトをピンポイントでアクセスする権限は与えられています。
※以下、パーミッションとファイルオブジェクト名のみに絞って記載します。
UNIXのファイルシステムでの"Directory"とは、その下のオブジェクト名とi-nodeの目録が記録された、それ自体が一つのファイルオブジェクトです。「オブジェクト名」というのはファイル名とかディレクトリ名とかシンボリックリンク名とかのイメージです。
ということで、
Otherに対して:
"files"ディレクトリ自体にはOtherの"x"bitがONになっています。これにより、MODE_WORLD_READABLE/WRITABLEを設定したファイルにもOther相当がアクセスできるようになっています。
drwxrwx--x /data/data/storage.exercise/files new File(getFilesDir(), "default_file"): -rw------- /data/data/storage.exercise/files/default_file openFileOutput("file_xxyy", MODE_XXYY)): -rw-rw---- /data/data/storage.exercise/files/file_private -rw-rw-r-- /data/data/storage.exercise/files/file_wr -rw-rw--w- /data/data/storage.exercise/files/file_ww
getFileDir()経由でnewしたFileオブジェクトが"default_file"になりますが、MODE_PRIVATEよりさらに厳しく、uidにのみRead/Writeを制限しています。
"databases"ディレクトリ自体にはOtherの"x"bitがONになっています。これにより、MODE_WORLD_READABLE/WRITABLEを設定したDBにもOther相当がアクセスできるようになっています。
drwxrwx--x /data/data/storage.exercise/databases Context.openOrCreateDatabase()経由: -rw-rw---- /data/data/storage.exercise/databases/db_private -rw-rw-r-- /data/data/storage.exercise/databases/db_wr -rw-rw--w- /data/data/storage.exercise/databases/db_ww SQLiteOpenHelper経由: -rw-rw---- /data/data/storage.exercise/databases/stddb
基本的にSQLiteOpenHelperしか使わないと思います。そちらであれば、PRIVATEとして作成されるので安心です。どうしても外部公開したければContentProviderを使ってください、ということだと思います。
"shared_prefs"ディレクトリ自体にはOtherの"x"bitがONになっています。これにより、MODE_WORLD_READABLE/WRITABLEを設定したshared_prefsにもOther相当がアクセスできるようになっています。
drwxrwx--x /data/data/storage.exercise/shared_prefs -rw-rw---- /data/data/storage.exercise/shared_prefs/private.xml -rw-rw-r-- /data/data/storage.exercise/shared_prefs/wr.xml -rw-rw--w- /data/data/storage.exercise/shared_prefs/ww.xml
特筆すべき点はありません。
getDir()ではmodeを指定できます。それによりnew File()したファイルオブジェクトのパーミッションがどうなるのか見てみます。
new File(getDir("dir_private", MODE_PRIVATE), "file1"): drwxrwx--x /data/data/storage.exercise/app_dir_private -rw------- /data/data/storage.exercise/app_dir_private/file1 new File(getDir("dir_wr", MODE_WORLD_READABLE), "file2"): drwxrwxr-x /data/data/storage.exercise/app_dir_wr -rw------- /data/data/storage.exercise/app_dir_wr/file2 new File(getDir("dir_ww", MODE_WORLD_WRITEABLE), "file3"): drwxrwx-wx /data/data/storage.exercise/app_dir_ww -rw------- /data/data/storage.exercise/app_dir_ww/file3
最終的なファイル自体はuidにしかRead/Writeが与えられていないので、他のアプリからはRead/Writeの両方が禁止されます。
但しMODE_WORLD_WRITABLEでgetDir()されたディレクトリ("app_dir_ww")自体はOtherの"w"と"x"がONになっています。これにより他のアプリから以下の処理が可能となります。
とはいえ"r"bitがOFFになっているので、他のアプリからはこのディレクトリ内のファイルの一覧を取得できない=どんなファイルがあるかわかりません。仮にファイル名が分かったとしても、Otherには"r"も"w"もONになっていないので読み書きできません。
そもそもの話をすると、他のアプリが"app_dir_ww"の存在を知ることそれ自体が不可能です。"/data/data/(package)"にはOtherの"r"がOFFになっているので、直下のオブジェクトの一覧を取得できません。よって、他のアプリが"app_dir_ww"というディレクトリの存在を知るすべがありません(root化端末は考慮していません)。
よって現実的な危険度で言えば、getDir(MODE_WORLD_WRITABLE)については心配の必要は無いと思われます。
その他のディレクトリ・ファイルのパーミッションです。
new File(getCacheDir(), "cache_file"): drwxrwx--x /data/data/storage.exercise/cache -rw------- /data/data/storage.exercise/cache/cache_file ApplicationInfo.nativeLibraryDir: drwxr-xr-x /data/data/storage.exercise/lib
"cache"ディレクトリにはOtherの"x"bitがONになっていますが、new File()で作成したファイルにはuidにしか"rw"が設定されていないので、他のアプリからは非公開になります。(たとえファイルのフルパスが公開されたとしても、他のアプリからはReadもWriteも出来ません。)
マウント状態:
/dev/block/vold/179:0 /mnt/sdcard vfat rw,dirsync,nosuid,nodev,noexec,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020, codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0
VFATで"rw"オプション付きですので、誰でもRead/Write可能です。それ以外ではパーミッションについて特筆すべき内容は見当たりませんでした。
StorageExercise実行後にfindした結果:
# find /mnt/sdcard/Android/data/ | xargs /data/busybox/ls --color=never -ld d---rwxr-x /mnt/sdcard/Android/data/ ----rwxr-x /mnt/sdcard/Android/data/.nomedia d---rwxr-x /mnt/sdcard/Android/data/storage.exercise d---rwxr-x /mnt/sdcard/Android/data/storage.exercise/cache d---rwxr-x /mnt/sdcard/Android/data/storage.exercise/files d---rwxr-x /mnt/sdcard/Android/data/storage.exercise/files/DCIM d---rwxr-x /mnt/sdcard/Android/data/storage.exercise/files/Download d---rwxr-x /mnt/sdcard/Android/data/storage.exercise/files/Music d---rwxr-x /mnt/sdcard/Android/data/storage.exercise/files/Pictures d---rwxr-x /mnt/sdcard/Android/data/storage.exercise/files/Podcasts ----rwxr-x /mnt/sdcard/Android/data/storage.exercise/files/dump.txt