#navi_header|技術| Contextクラスから取得出来るディレクトリのパスや、Contextクラス経由で作成できるファイルオブジェクトについてそのUNIXファイル上でのパーミッション設定を調べて見ました。 - ファイル(getFilesDir(), getDir(), openFileOutput()) - SharedPreferences - データベース(openOrCreateDatabase(), SQLiteOpenHelper経由) - 外部ストレージ サンプルアプリケーション:StorageExercise - https://bitbucket.org/msakamoto_sf/androidexercise/src/41e445a113b7/StorageExercise -- API Level 10 にしていますので、Android 2.3.3 以上のEmulatorで実行してください。 MODE_WORLD_READABLE/WRITABLEに注意すべきケースとしては、結論としては以下の3種類になります。 - Context.openFileOutput() - Context.getSharedPreferences() - Context.openOrCreateDatabase() Context.getDir()もmodeを指定できますが、こちらは心配要りません。 #more|| ---- #outline|| ---- * 各種PATH取得結果: 各種PATHの状況を取得し、以下のファイルに書き込みます。 /mnt/sdcard/Android/data/storage.exercise/files/dump.txt 実際のdump.txtの内容: #pre||> 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] ||< * "/data/data/(package)/"以下の状況 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にもその中のファイルオブジェクトをピンポイントでアクセスする権限は与えられています。 ※以下、パーミッションとファイルオブジェクト名のみに絞って記載します。 ** 復習:Directoryに対する"r", "x"bitの意味について UNIXのファイルシステムでの"Directory"とは、その下のオブジェクト名とi-nodeの目録が記録された、それ自体が一つのファイルオブジェクトです。「オブジェクト名」というのはファイル名とかディレクトリ名とかシンボリックリンク名とかのイメージです。 ということで、 : Directoryに対する"r"bit : 目録をReadする権限がある、すなわちそのDirectoryの下のオブジェクト名の一覧を取得することができます。 : Directoryに対する"w"bit : 目録をWriteする権限がある、すなわちそのDirectoryの下のオブジェクト名を書き換える事ができます。ファイルのOwnerとは無関係ですので、たとえ自分以外の所有者のファイルオブジェクトであっても名前を変更できます。ファイル名はあくまでもDirectoryの目録データであり、ファイルオブジェクトそれ自体とは切り離されている点に注意してください。なお目録をWrite出来る = そのDirectoryの下にファイルを作成できる、というわけではありません。ファイルを作成するのであればまずそのDirectoryに対して"x"bitがONになっている必要があります。(Directoryを直接open(2)して、使用しているファイルシステムに従って目録を書き換えれば無理矢理ファイルを「作ったことにする」のは可能とは思われるが、まず通常の用途ではあり得ないだろう) : Directoryに対する"x"bit : Directoryの下のオブジェクトにアクセス可能を意味します。目録のReadとは異なり、ピンポイントでその中の1オブジェクトにアクセス出来るかどうかに影響します。"Other"相当で"/usr/share/doc/abc.txt"をReadしようとしたら、"/usr", "/usr/share", "/usr/share/doc" それぞれに"o+x"がONで、"abc.txt"には"o+r"がONになっている必要があります。 Otherに対して: - そのDirectory内のオブジェクトにピンポイントでアクセスさせたいなら"x"だけで十分です。 - "ls"コマンド or opendir(3) でDirectory内のオブジェクト一覧の取得を許可するだけなら "r" だけで十分です。 - (非常に稀なケースとして)Directory内のオブジェクトの名前を変更させたい(mvコマンド or rename(2))だけなら "w" で十分です。 - そのDirectory内に対して一般的なRead権限を与えたいなら"r" + "x"になります。("ls"コマンド, opendir(3)許可) - そのDirectory内でのファイルの作成・削除を許可するなら"w" + "x"になります。(目録のWrite許可 + そのDirectoryの下でのファイルアクセス許可("x")) ** "/data/data/(package)/files" 以下 "files"ディレクトリ自体にはOtherの"x"bitがONになっています。これにより、MODE_WORLD_READABLE/WRITABLEを設定したファイルにもOther相当がアクセスできるようになっています。 #pre||> 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を制限しています。 ** "/data/data/(package)/databases" 以下 "databases"ディレクトリ自体にはOtherの"x"bitがONになっています。これにより、MODE_WORLD_READABLE/WRITABLEを設定したDBにもOther相当がアクセスできるようになっています。 #pre||> 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を使ってください、ということだと思います。 ** "/data/data/(package)/shared_prefs" 以下 "shared_prefs"ディレクトリ自体にはOtherの"x"bitがONになっています。これにより、MODE_WORLD_READABLE/WRITABLEを設定したshared_prefsにもOther相当がアクセスできるようになっています。 #pre||> 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()経由で作成したファイル getDir()ではmodeを指定できます。それによりnew File()したファイルオブジェクトのパーミッションがどうなるのか見てみます。 #pre||> 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になっています。これにより他のアプリから以下の処理が可能となります。 + このディレクトリ内のファイル名を変更("w" : 目録を書き換え可能) + このディレクトリ内にファイルを作成できる("x") + このディレクトリ内の(自分がセクシしたファイルを)削除できる とはいえ"r"bitがOFFになっているので、他のアプリからはこのディレクトリ内のファイルの一覧を取得できない=どんなファイルがあるかわかりません。仮にファイル名が分かったとしても、Otherには"r"も"w"もONになっていないので読み書きできません。 そもそもの話をすると、他のアプリが"app_dir_ww"の存在を知ることそれ自体が不可能です。"/data/data/(package)"にはOtherの"r"がOFFになっているので、直下のオブジェクトの一覧を取得できません。よって、他のアプリが"app_dir_ww"というディレクトリの存在を知るすべがありません(root化端末は考慮していません)。 よって現実的な危険度で言えば、getDir(MODE_WORLD_WRITABLE)については心配の必要は無いと思われます。 ** "/data/data/(package)/cache"、その他 その他のディレクトリ・ファイルのパーミッションです。 #pre||> 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も出来ません。) * 外部ストレージ(SDカード) マウント状態: /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した結果: #pre||> # 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 ||< #navi_footer|技術|