ファイルの属性情報を探る 権限編
前回からの続き。
伝統的なUNIXのアクセス権限
- 伝統的なUNIXでは、すべてのファイルやディレクトリにアクセス権限が設定されている。
- ここで言うアクセス権限とは、読み・書き・実行を許可するか、しないかの選択である。
- 以上のアクセス権限を、所有者・グループ・その他のユーザーに区分して、それぞれ設定するのである。
- アクセス権限は、lsコマンドで確認できる。
$ cd ~/Desktop $ ls -l drwxr-xr-x 6 zari staff 204 4 9 10:53 folder -rw-r--r-- 1 zari staff 10 4 4 17:05 sample.txt
- 太字部分がアクセス権限を表現している。
- 先頭の1文字、dまたは-がファイルの種類を意味している。(d=ディレクトリ、-=通常のファイル)
- 次の9文字、rwxはたは-がアクセス権限を意味している。(r=読み許可、w=書き許可、x=実行許可、-=許可しない)
- つまり、sample.txtのアクセス権限は、以下のように解釈できるのだ。
- 所有者は、読み書きOK。
- グループは、読みOK。
- その他のユーザーも、読みOK。
種別 | 所有者 | グループ | その他 |
---|---|---|---|
- | rw- | r-- | r-- |
通常ファイル | 読み・書き | 読み | 読み |
実行ファイルのsビット(setuid・setgid)
- 以下のlsコマンドを実行してみる。
$ sudo find /{,usr/,usr/local/}{,s}bin -type f -perm -4000 -print0 | xargs -0 ls -l -rwsr-xr-x 1 root wheel 46800 9 19 2012 /bin/ps -r-sr-xr-x 1 root wheel 29424 9 19 2012 /bin/rcp -r-sr-xr-x 4 root wheel 75664 3 19 13:23 /usr/bin/at -r-sr-xr-x 4 root wheel 75664 3 19 13:23 /usr/bin/atq -r-sr-xr-x 4 root wheel 75664 3 19 13:23 /usr/bin/atrm -r-sr-xr-x 4 root wheel 75664 3 19 13:23 /usr/bin/batch -rwsr-xr-x 1 root wheel 39296 9 19 2012 /usr/bin/crontab -rws--x--x 1 root wheel 23008 9 24 2012 /usr/bin/ipcs -r-sr-xr-x 1 root wheel 68480 3 19 13:23 /usr/bin/login -r-sr-xr-x 1 root wheel 44560 3 19 13:23 /usr/bin/newgrp -r-sr-xr-x 1 root wheel 44560 9 19 2012 /usr/bin/quota -r-sr-xr-x 1 root wheel 24832 9 19 2012 /usr/bin/rlogin -r-sr-xr-x 1 root wheel 19856 9 19 2012 /usr/bin/rsh -rwsr-xr-x 1 root wheel 21472 9 19 2012 /usr/bin/su -r-s--x--x 1 root wheel 164496 9 24 2012 /usr/bin/sudo -r-sr-xr-x 1 root wheel 178000 9 19 2012 /usr/bin/top -rwsr-xr-x 1 root wheel 25192 1 16 17:12 /usr/local/bin/timer-add-schedule -rwsr-xr-x 1 root wheel 25024 1 16 17:33 /usr/local/bin/timer-rm-schedule -r-sr-xr-x 1 root wheel 20720 3 19 13:23 /usr/sbin/scselect -r-sr-xr-x 1 root wheel 33680 9 19 2012 /usr/sbin/traceroute -r-sr-xr-x 1 root wheel 29344 9 19 2012 /usr/sbin/traceroute6 $ sudo find /{,usr/,usr/local/}{,s}bin -type f -perm -2000 -print0 | xargs -0 ls -l -rwxr-sr-x 1 root mail 24512 9 19 2012 /usr/bin/lockfile -rwxr-sr-x 1 root mail 92864 9 19 2012 /usr/bin/procmail -r-xr-sr-x 1 root tty 20800 9 19 2012 /usr/bin/wall -r-xr-sr-x 1 root tty 19920 9 19 2012 /usr/bin/write -rwxr-sr-x 1 root _postdrop 203088 3 19 13:23 /usr/sbin/postdrop -rwxr-sr-x 1 root _postdrop 234976 3 19 13:23 /usr/sbin/postqueue
- すると、アクセス権限に見慣れないsが表示されている!
- 本来なら実行を許可するxが表示されるべき位置である。
このsは何なのか?
- 実行権限xの位置に表示されるsは、sビットと呼ばれる。
- 通常は(xが表示されていれば)、そのファイルを起動したユーザーの権限で実行される仕組みであるが...
- そんな必要性があるのかと言えば、意外と身近な状況で起こりうる。例えば、crontabコマンド。
- 誰もが自分のcron設定を変更できるべきなのだが、cronの設定を保存する/var/at/tabs/はroot権限で厳重に管理されている。
- よって本来ならcrontabを実行する時はroot権限の場所にアクセスする必要があるのだが、一般ユーザーのままでもちゃんと設定を変更できている。
- なぜ一般ユーザーのままroot権限のファイルを変更できているかと言えば、所有者のsビット(setuid)がセットされているからである。
-rwsr-xr-x 1 root wheel 39296 9 19 2012 /usr/bin/crontab
- 所有者rootの権限がrwsとなっている!
- つまり、誰がcrontabを実行しても、root権限で実行されるのだ。
設定方法
-rwsr-xr-x 1 root wheel 39296 9 19 2012 /usr/bin/crontab -rwxr-sr-x 1 root mail 24512 9 19 2012 /usr/bin/lockfile
- sビットが設定されている8進数のアクセス権限は、以下のように表示された。
$ stat -f '%N %A' /usr/bin/crontab /usr/bin/crontab 4755 $ stat -f '%N %A' /usr/bin/lockfile /usr/bin/lockfile 2755
- 4桁目のアクセス権限が4=setuid、2=setgid となるのだ。
- つまり、chmodコマンドで、以下のように設定できるのだ。
$ chmod 4755 /usr/bin/crontab $ chmod 2755 /usr/bin/lockfile
- あるいは+sを利用しても設定可能である。
$ chmod u+s /usr/bin/crontab $ chmod g+s /usr/bin/lockfile
危険性
- root権限のsビット(setuid・setgid)をセットすると、誰もがroot権限で実行できるため、
- 悪意のあるユーザーが利用したとしても、OS環境に不要な攻撃をされない工夫が必要である。
- 標準インストールされるコマンドには、そう言った工夫がされている筈である。
参考ページ
以下のページがたいへん参考になりました。感謝です!
実は以前、timerコマンドを作った時にも利用している。
ディレクトリのsビット(setuid・setgid)
- ディレクトリに対するsビットの扱いは、実行ファイルとは違うらしい。
但し、ディレクトリのsビットの扱いは、OS環境によってずいぶん変わってくるようだ。
スティッキービット
- スティッキービットという仕組みもある。
- ちなみに、sビットとスティッキービットは、まったくの別もの。
- ベリラボ - s-bit(sビット) と sticky bit(スティキービット)(感謝!)
- 例えば、/private/tmpや/Users/Sharedのアクセス権限の最後のフラグはtとなっている。
$ ls -ld /private/tmp drwxrwxrwt 14 root wheel 476 4 9 14:41 /private/tmp/ $ ls -ld /Users/Shared drwxrwxrwt 11 root wheel 374 4 10 15:11 /Users/Shared/
- この、その他のユーザーの実行権限xの部分に表示されるtが、スティッキービットである。
- 上記のようにスティッキービットが有効になっていると...
- 誰もが/private/tmp/以下にファイルやディレクトリを作成できるが、
- それらを削除できるのは、所有者だけとなる。
- 仮にもしスティッキービットが無効であれば...
- 誰もがファイルやディレクトリを作成できて、
- 誰もがそれらを削除できる扱いになる。
設定方法
- sビットが設定されている8進数のアクセス権限は、以下のように表示された。
$ stat -f '%N %A' /private/tmp /private/tmp 1777 $ stat -f '%N %A' /Users/Shared /Users/Shared 1777
- 4桁目のアクセス権限が1=スティッキービットが有効となるのだ。
- よって、chmod 1777 あるいは chmod a+t コマンドで設定する。(o+t、u+t、g+t では設定できなかった)
$ mkdir sticky_folder $ ls -ld sticky_folder drwxr-xr-x 2 zari staff 68 4 10 08:53 sticky_folder $ chmod a+rwxt sticky_folder $ ls -ld sticky_folder drwxrwxrwt 2 zari staff 68 4 10 08:53 sticky_folder
- その他のユーザーの実行権限を無効(アクセス不可)にした場合は、大文字のTが表示された。
$ chmod o-x sticky_folder $ ls -ld sticky_folder drwxrwxrwT 2 zari staff 68 4 10 08:53 sticky_folder/
ファイルフラグ
- 以前調べたファイルフラグの設定も、権限の1つと言える。
- ファイルフラグの状態はls -lOコマンドで確認できるのだ。
$ command ls -lO ~ total 0 drwx------+ 16 zari staff - 544 4 10 14:15 Desktop drwx------+ 399 zari staff - 13566 3 14 14:03 Documents drwx------+ 234 zari staff - 7956 4 8 14:26 Downloads drwx------@ 67 zari staff hidden 2278 4 3 09:05 Library drwx------+ 7 zari staff - 238 3 28 09:51 Movies drwx------+ 9 zari staff - 306 2 28 09:28 Music drwx------+ 11 zari staff - 374 10 23 16:53 Pictures drwxr-xr-x+ 11 zari staff - 374 9 16 2012 Public drwxr-xr-x 4 zari staff - 136 2 25 10:59 Sites
- ファイルフラグの設定は、chflagsコマンドで行う。
- マニュアル chflags(1) によると、以下のフラグを可能だという。
必要なユーザー権限 | ファイルフラグ | 意味 |
---|---|---|
管理者権限 | arch archived | ? |
所有者 | opaque | ? |
所有者 | nodump | ? |
管理者権限 | sappnd sappend | フォルダにおいて追加のみ可能。変更はできない。 |
管理者権限 | schg schange simmutable | 変更不可フラグ。設定するとFinderのロック属性がオンになる。 |
所有者 | uappnd uappend | フォルダにおいて追加のみ可能。変更はできない。 |
所有者 | uchg uchange uimmutable | 変更不可フラグ。設定するとFinderのロック属性がオンになる。 |
所有者 | hidden | GUI環境からアイテムを隠す。 |
- さらに、リンク先のchflags(2) を見てみると、ソースコードのsys/stat.hも紹介されているので見てみた。
/* * Definitions of flags stored in file flags word. * * Super-user and owner changeable flags. */ #define UF_SETTABLE 0x0000ffff /* mask of owner changeable flags */ #define UF_NODUMP 0x00000001 /* do not dump file */ #define UF_IMMUTABLE 0x00000002 /* file may not be changed */ #define UF_APPEND 0x00000004 /* writes to file may only append */ #define UF_OPAQUE 0x00000008 /* directory is opaque wrt. union */ /* * The following bit is reserved for FreeBSD. It is not implemented * in Mac OS X. */ /* #define UF_NOUNLINK 0x00000010 */ /* file may not be removed or renamed */ #define UF_COMPRESSED 0x00000020 /* file is hfs-compressed */ #define UF_TRACKED 0x00000040 /* file renames and deletes are tracked */ /* Bits 0x0080 through 0x4000 are currently undefined. */ #define UF_HIDDEN 0x00008000 /* hint that this item should not be */ /* displayed in a GUI */ /* * Super-user changeable flags. */ #define SF_SETTABLE 0xffff0000 /* mask of superuser changeable flags */ #define SF_ARCHIVED 0x00010000 /* file is archived */ #define SF_IMMUTABLE 0x00020000 /* file may not be changed */ #define SF_APPEND 0x00040000 /* writes to file may only append */ /* * The following two bits are reserved for FreeBSD. They are not * implemented in Mac OS X. */ /* #define SF_NOUNLINK 0x00100000 */ /* file may not be removed or renamed */ /* #define SF_SNAPSHOT 0x00200000 */ /* snapshot inode */ /* NOTE: There is no SF_HIDDEN bit. */
- すると興味深いことに、chflagsのマニュアルで紹介されている8つのフラグ以外に、さらに2つのフラグが用意されていることに気付いた。
#define UF_COMPRESSED 0x00000020 /* file is hfs-compressed */......ファイルがHFS圧縮されている #define UF_TRACKED 0x00000040 /* file renames and deletes are tracked */......ファイルの名称変更と削除を追跡する
- UF_COMPRESSED
- UF_COMPRESSEDは、HFS+に備わる圧縮機能に関するフラグらしい。
- 例えば、/usr/binやプレビュー.appやテキストエディット.appのアプリケーションバンドルの中を覗いてみると、compressedが確認できた!
$ ls -lO /usr/bin total 163656 ...中略... -rwxr-xr-x 6 root wheel compressed 925 9 19 2012 2to3* -rwxr-xr-x 6 root wheel compressed 925 9 19 2012 2to3-* lrwxr-xr-x 1 root wheel - 74 9 19 2012 2to3-2.7@ -> ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/2to3-2.7 lrwxr-xr-x 1 root wheel - 73 9 19 2012 2to32.6@ -> ../../System/Library/Frameworks/Python.framework/Versions/2.6/bin/2to32.6 -rwxr-xr-x 1 root wheel compressed 18832 3 22 14:09 BuildStrings* -rwxr-xr-x 1 root wheel compressed 25264 3 22 14:09 CpMac* -rwxr-xr-x 1 root wheel compressed 100960 3 22 14:09 DeRez* -rwxr-xr-x 1 root wheel compressed 14480 3 22 14:09 GetFileInfo* -rwxr-xr-x 1 root wheel compressed 62480 3 22 14:09 MergePef* -rwxr-xr-x 1 root wheel compressed 18976 3 22 14:09 MvMac* ...中略... $ ls -lO /Applications/TextEdit.app/Contents total 0 -rw-r--r-- 1 root wheel compressed 7868 9 19 2012 Info.plist drwxr-xr-x 3 root wheel - 102 6 23 2012 MacOS/ -rw-r--r-- 1 root wheel compressed 8 9 19 2012 PkgInfo drwxr-xr-x 42 root wheel - 1428 9 19 2012 Resources/ drwxr-xr-x 3 root wheel - 102 6 23 2012 _CodeSignature/ -rw-r--r-- 1 root wheel compressed 456 9 19 2012 version.plist
- UF_TRACKED
- UF_TRACKEDは、バージョン機能をサポートするアプリケーションが保存した書類に設定されていた。
- 2度目の保存をして、バージョン管理され始めると UF_TRACKED が設定された。
- 但し、UF_TRACKEDは、ls -lOコマンドでは確認できない...。
$ ls -lO /Users/zari/Desktop/UF_TRACKEDのテスト.txt
-rw-r--r--@ 1 zari staff - 24 4 11 06:06 /Users/zari/Desktop/UF_TRACKEDのテスト.txt
-
- statコマンドで表示される st_flags=64 を見て確認できた。
- (UF_TRACKED = 0x00000040 = 64)
$ stat -s /Users/zari/Desktop/UF_TRACKEDのテスト.txt st_dev=16777218 st_ino=8135828 st_mode=0100644 st_nlink=1 st_uid=501 st_gid=20 st_rdev=0 st_size=24 st_atime=1365627974 st_mtime=1365627972 st_ctime=1365627972 st_birthtime=1365627885 st_blksize=4096 st_blocks=8 st_flags=64
設定方法
- ファイルをロックしてみる。
$ touch flag_test $ ls -lO flag_test -rw-r--r-- 1 zari staff - 0 4 11 06:39 flag_test $ chflags uchg flag_test $ ls -lO flag_test -rw-r--r-- 1 zari staff uchg 0 4 11 06:39 flag_test
- ロックしたファイルを削除すると...
$ rm -f flag_test
rm: flag_test: Operation not permitted
- ファイルフラグは複数設定できる。
$ chflags hidden flag_test $ ls -lO flag_test -rw-r--r--@ 1 zari staff uchg,hidden 0 4 11 06:39 flag_test
- すべてのファイルフラグを削除する。
- 8進数コードで指定可能なのだ。
- この場合ゼロ0を指定している。
$ chflags 0 flag_test $ ls -lO flag_test -rw-r--r-- 1 zari staff - 0 4 11 06:39 flag_test
以上、ファイルフラグはすべての設定が権限とは言えないが、全10種類のフラグを設定できる仕様なのであった。
ACL
- 突然ではあるが、デスクトップを削除するという実験をしてみる。
- 本当に削除されてしまうので、バックアップしてから作業に入るのだ。
- さっそく、rmコマンドで削除してみると...
$ rm -fr ~/Desktop
rm: Desktop: Permission denied
- デスクトップ上のアイテムはすべて削除されてしまったが、
- デスクトップ(ディレクトリ)だけは、しっかり残るのだ。
- デスクトップでは、伝統的なアクセス権限 所有者=rwxになっているし、ファイルフラグの設定もない。
$ ls -lOd ~/Desktop drwx------+ 18 zari staff - 612 4 11 06:39 Desktop
- 普通に考えれば削除できる筈なのだが、現実はPermission denied(アクセス権がない)と表示される。
なぜ削除できないのか?
- よ〜く観察すると、伝統的なアクセス権限を示す項目の末尾に+が付加されている。これが重要なヒントになる。
- この+は、ACL(Access Control Lists=アクセス制御リスト)という情報が付加されていることを示している。
- このACLの中身は、lsコマンドのオプションにeを指定することで確認できる。
$ ls -lOed ~/Desktop drwx------+ 18 zari zari - 612 4 11 15:50 Desktop 0: group:everyone deny delete......ACLの中身
- なるほど!と思って改めてホーム直下のACLを確認してみると、標準インストールされるフォルダにはすべて everyone deny delete が設定されている。
$ ls -lOe ~
total 0
drwx------+ 18 zari staff - 612 4 11 15:50 Desktop
0: group:everyone deny delete
drwx------+ 399 zari staff - 13566 3 14 14:03 Documents
0: group:everyone deny delete
drwx------+ 235 zari staff - 7990 4 11 14:30 Downloads
0: group:everyone deny delete
drwx------@ 67 zari staff hidden 2278 4 3 09:05 Library
0: group:everyone deny delete
drwx------+ 7 zari staff - 238 3 28 09:51 Movies
0: group:everyone deny delete
drwx------+ 9 zari staff - 306 2 28 09:28 Music
0: group:everyone deny delete
drwx------+ 11 zari staff - 374 10 23 16:53 Pictures
0: group:everyone deny delete
drwxr-xr-x+ 11 zari staff - 374 9 16 2012 Public
0: group:everyone deny delete
設定方法
- ACLを設定する。
$ touch acl_test $ ls -lOe acl_test -rw-r--r-- 1 zari staff - 0 4 11 16:45 acl_test $ chmod +a "everyone deny delete" acl_test $ ls -lOe acl_test -rw-r--r--+ 1 zari staff - 0 4 11 16:45 acl_test 0: group:everyone deny delete
- 削除してみると...
$ rm -f acl_test rm: acl_test: Permission denied
- ACLは複数設定できる。
$ chmod +a "guest deny read" acl_test $ chmod +a "admin allow write" acl_test $ ls -lOe acl_test -rw-r--r--+ 1 zari staff - 0 4 11 16:45 acl_test 0: user:Guest deny read 1: group:everyone deny delete 2: group:admin allow write
- ACLを1つ削除する。
$ chmod -a# 1 acl_test $ ls -lOe acl_test -rw-r--r--+ 1 zari staff - 0 4 11 16:45 acl_test 0: user:Guest deny read 1: group:admin allow write
- ACLをすべて削除する。
$ chmod -N acl_test $ ls -lOe acl_test -rw-r--r-- 1 zari staff - 0 4 11 16:45 acl_test
その他
- 基本的にOSをインストールした時に設定されたACLは、無闇に変更しない方が良さそう。
- 基本的に自分の使い方では、ACLを積極的に活用する状況は思い浮かばない。
- ほとんどの状況で、伝統的なアクセス権限とファイルフラグで十分だと思う。
複数ユーザー・複数グループの追加
- そう言えば、いつの頃からか所有者以外に、自由に好みのユーザー権限を追加できるようになっていた。
- 伝統的なUNIXの権限では、所有者以外のユーザーは追加できないと思っていたので、不思議に思っていた。
- 例えばFinderの情報を見る(command-I)で通常のacl_testファイルを開くと...
- このacl_testファイルには、複数のユーザーやグループを自由に追加できるのだ!
- AliceとBobを追加してみた。
どんな仕組みになっているんだ?
$ ls -lOe /Users/bebe/Desktop/acl_test -rw-r--r-- 1 bebe staff - 0 4 11 16:45 acl_test
-
- AliceとBobを追加後、確認してみると...
$ ls -lOe ~/Desktop/acl_test -rw-r--r--+ 1 bebe staff - 0 4 11 16:45 acl_test 0: user:bob allow read,write,append,readattr,writeattr,readextattr,writeextattr,readsecurity 1: user:alice allow read,write,append,readattr,writeattr,readextattr,writeextattr,readsecurity
なんと!ACLが追加されていたのであった。