home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/Android/FileAndDirPermissions

技術/Android/FileAndDirPermissions

技術 / Android / FileAndDirPermissions
id: 1027 所有者: msakamoto-sf    作成日: 2011-10-16 21:46:21
カテゴリ: Android 

Contextクラスから取得出来るディレクトリのパスや、Contextクラス経由で作成できるファイルオブジェクトについてそのUNIXファイル上でのパーミッション設定を調べて見ました。

  • ファイル(getFilesDir(), getDir(), openFileOutput())
  • SharedPreferences
  • データベース(openOrCreateDatabase(), SQLiteOpenHelper経由)
  • 外部ストレージ

サンプルアプリケーション:StorageExercise

MODE_WORLD_READABLE/WRITABLEに注意すべきケースとしては、結論としては以下の3種類になります。

  • Context.openFileOutput()
  • Context.getSharedPreferences()
  • Context.openOrCreateDatabase()

Context.getDir()もmodeを指定できますが、こちらは心配要りません。



各種PATH取得結果:

各種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]

"/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相当がアクセスできるようになっています。

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相当がアクセスできるようになっています。

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相当がアクセスできるようになっています。

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()したファイルオブジェクトのパーミッションがどうなるのか見てみます。

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になっています。これにより他のアプリから以下の処理が可能となります。

  1. このディレクトリ内のファイル名を変更("w" : 目録を書き換え可能)
  2. このディレクトリ内にファイルを作成できる("x")
  3. このディレクトリ内の(自分がセクシしたファイルを)削除できる

とはいえ"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"、その他

その他のディレクトリ・ファイルのパーミッションです。

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した結果:

# 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


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2011-10-16 22:02:08
md5:bb0d35fb841cbbfc9de318e6851d2fd5
sha1:3141cae8089bf9ce0a71144a137dbbcabd80b58f
コメント
コメントを投稿するにはログインして下さい。