POSIX ACL (アクセス制御リスト) は、ファイルシステム内のオブジェクト (ファイルやディレクトリなど) に対して設定することのできる、従来型のパーミッション (アクセス許可) の拡張です。 ACL を使用することで、従来型のパーミッションよりも柔軟な構成をとることができるようになります。
POSIX ACL という名称からもおわかりのとおり、こちらは正式な POSIX ( Portable Operating System Interface ) 標準として規定されています。関連するドラフトは POSIX 1003.1e と POSIX 1003.2c で、いずれも諸事情により撤回されています。しかしながら、 Unix ファミリに属する多くのオペレーティングシステムと同様に、 ACL はこれらのドラフトをベースにしているほか、ファイルシステム側の ACL (本章で説明しています) 実装は、これら 2 つの標準に従って行われています。
openSUSE Leap で提供されている全てのファイルに対するアクセス権 (パーミッション) は、よく考えられて設定されています。そのため、追加のソフトウエアやファイルをインストールする場合は、パーミッションの設定に注意してください。 ls
コマンドに -l
オプションを指定することで、正しく設定されていないパーミッションを即時に見つけることができます。なお、パーミッションの設定は、ファイルの内容の変更や削除に影響するだけではありません。 root
が実行するプログラム自身を書き換えることもできてしまいますし、設定を書き換えて不正な動作を行わせることもできてしまいます。このように、パーミッションの設定は攻撃の可能性を増やすことにも繋がります。
openSUSE® Leap システム内の /etc
ディレクトリには、 permissions
, permissions.easy
, permissions.secure
, permissions.paranoid
の各ファイルが用意されています。これらのファイルは、全てのユーザが書き込みできるディレクトリやファイル、 setuser ID (setuid) ビットなどの特殊なパーミッションを定義するためのファイルです。 setuser ID ビットが設定されたプログラムは、そのプログラムを起動したユーザの権限で動作することはなく、ファイルの所有者 (通常は root
) の権限で動作します。管理者側では、 /etc/permissions.local
というファイルを利用することで、独自の設定を行うことができます。
利用可能なプロファイルからいずれかを選択したい場合は、 YaST の /etc/permissions
内のコメント (英語) もしくは man chmod
で表示されるマニュアルページをお読みください。
従来型のファイルパーミッションに関する詳しい説明については、 GNU coreutils の info ページ内にある File permissions ( info coreutils "File permissions"
) (英語) の項をお読みください。 setuid, setgid, sticky の各ビットに対する説明も用意されています。
状況によっては、アクセスパーミッションの仕組みでは制限が大きすぎることがあります。そのため Linux には、特定の処理に対して現在のユーザやグループを一時的に変更することのできる機能が用意されています。たとえば passwd
プログラムは /etc/passwd
ファイルにアクセスすることから、通常であれば root の権限が必要となります。ただし、このファイルには各ユーザのホームディレクトリのほか、ユーザやグループの ID などの重要な情報が含まれています。このような構造から、一般ユーザに passwd
ファイルへの書き込み許可を与えてしまうと、自分以外の情報も変更できてしまいますので、実質的には管理者権限を与えるのと同じになってしまい、セキュリティの意味がなくなってしまいます。このような状況下でも、自分自身のパスワードだけを書き換えることができるようにする必要があることから、 setuid という仕組みが考えられました。 setuid (set user ID) は特殊なファイル属性で、そのファイルの所有者に成り代わってプログラムを実行することができます。たとえば passwd
コマンドは下記のようになっています:
-rwsr-xr-x 1 root shadow 80036 2004-10-02 11:08 /usr/bin/passwd
ユーザパーミッションの欄に s
が書かれていることで、 setuid ビットが設定されていることが分かります。 setuid ビットの意味により、 passwd
コマンドは root
の権限下で動作することになります。
setuid ビットはユーザに対して適用される仕組みです。それと同様に、グループに対する仕組みも用意されています。これを setgid ビットと呼びます。このビットが設定されたプログラムは、どのユーザから実行された場合であっても、そのプログラムに設定されたグループ ID で実行されることになります。 setgid ビットが設定されたディレクトリ内では、新しく作成されたファイルやサブディレクトリは、そのディレクトリに対して設定されているグループに割り当てられます。たとえば下記のようなディレクトリが存在するものとします:
drwxrws--- 2 tux archive 48 Nov 19 17:12 backup
グループパーミッションの欄に s
が書かれていることで、 setgid ビットが設定されていることが分かります。このディレクトリの所有者と archive
グループのメンバーは、パーミッションに書かれているとおり、このディレクトリにアクセスすることができます。このグループのメンバーではないユーザは、対応するグループに 「マッピング」 されます。さらに、書き込まれた全てのファイルの実効グループ ID は archive
に設定されます。たとえば、グループ ID archive
で実行されたバックアッププログラムは、 root の権限を取得することなく、このディレクトリにアクセスすることができます。
このほか、 sticky ビット と呼ばれる仕組みも用意されています。これは実行可能なプログラムに対して設定されているのか、もしくはディレクトリに対して設定されているのかによって、異なる意味を持ちます。プログラムに対して設定されている場合、このプログラムはメモリに読み込まれ、使用されるごとにハードディスクから読み込む処理を行わなくなります。新しいハードウエアであれば、ハードディスクも十分に高速なものであることから、この仕組みはあまり使用されていません。ディレクトリに対して設定されている場合は、異なるユーザが作成したファイルを削除できないようにするフラグとして動作します。一般的には /tmp
や /var/tmp
ディレクトリに設定します:
drwxrwxrwt 2 root root 1160 2002-11-19 17:15 /tmp
従来の Linux システムでは、 3 種類のパーミッションセット (ファイルの所有者に対するセット/所有グループに対するセット/その他に対するセット) を各オブジェクトに設定していました。各セット内には読み込み ( r
), 書き込み ( w
), 実行 ( x
) のパーミッションが存在し、これらでアクセス許可を構築していました。これに加えて、 set user id , set group id , sticky の各ビットが追加されて、従来型のパーミッションを構成していました。このような無駄のない仕組みは、ほとんどの動作環境で十分なものではありましたが、より複雑なシナリオや高度な用途では不足することもあります。このような場合は、システム管理者が様々な回避策を講じることで、従来型のパーミッションの考え方に収まるよう、うまく設計する必要がありました。
ACL (Access Control List) は従来型のファイルパーミションの考え方に対する拡張として使うことのできる仕組みです。この ACL の仕組みでは、所有者や所有グループ以外の任意のユーザやグループに対して、アクセス許可を設定することができるようになっています。 ACL は Linux カーネルの機能であり、 ext2, ext3, ext4, jfs, xfs などで使用することができます。この仕組みにより、システム管理者が複雑なパーミッションモデルを構築することなく、複雑なシナリオを構成することができるようになります。
ACL の利点は、 Windows サーバを Linux サーバで入れ替えたりするような場合に顕著に働きます。移行前に Windows サーバに接続されていた作業端末は、移行が終わった後も引き続き使い続けることができなければなりませんが、 Linux では Windows クライアント向けのファイルおよび印刷サービスとして、 Samba が提供されています。 Samba には ACL へのサポートが提供されているため、 Linux サーバ内でも Windows 側のグラフィカルなインターフェイスを使用した場合 (Windows NT もしくはそれ以降が必要です) でも、ユーザへのアクセス許可を自由に設定できるようになります。また、 Samba スイートの一部として提供されている winbindd
を使用することで、 Linux サーバ内には存在していない Windows ドメインのユーザに対して、アクセス許可を設定することもできます。
従来の POSIX 型のパーミッションでは、ユーザを 3 種類の クラス (所有者/所有グループ/その他) に分類して、それぞれに許可を設定していました。クラス内では、それぞれ読み込み ( r
), 書き込み ( w
), 実行 ( x
) の各権限を設定していました。
全ての種類のファイルシステムオブジェクト (ファイルやディレクトリ) に対するユーザおよびグループへのアクセス許可は、 ACL によって決定されます。
既定の ACL はディレクトリに対してのみ適用されるものです。この既定の ACL は、新しくファイルシステムオブジェクトが作成された際に、親ディレクトリのものを引き継いで設定するために使用されます。
それぞれの ACL には 1 つ以上の ACL エントリが含まれます。 ACL エントリには種類のほか、そのエントリが参照するユーザやグループの修飾子、そして許可情報が含まれます。また、エントリの種類によっては、ユーザやグループに対する修飾子が未定義になることもあります。
表19.1「ACL エントリの種類」 には、 ACL エントリとして存在しうる 6 つの種類が示されています。それぞれはユーザ自身やユーザのグループを表す仕組みで、所有者 はファイルやディレクトリを所有しているユーザの許可を、 所有グループ はファイルを所有しているグループの許可をそれぞれ表しています。スーパーユーザは chown
や chgrp
のコマンドで所有者や所有グループを変更することができますが、これらのコマンドで変更を行うと、変更後の所有者や所有グループに対して作用することになります。また、 特定ユーザ はエントリ内の修飾子内で指定されているユーザに対する許可を、 特定グループ はエントリ内の修飾子内で指定されているグループに対する許可をそれぞれ表します。 特定ユーザ および 特定グループ のエントリである場合にのみ、修飾子に値が設定されます。 その他 のエントリでは、それ以外の全てのユーザに対する許可を表します。
マスク は特定ユーザや特定グループ、所有グループの各エントリに対して許可された内容のうち、どの項目を無効化して、どの項目を有効化するのかを表します。上述のいずれかのエントリ内で許可されていて、マスクエントリでも有効として設定されている場合、その許可はそのまま許可されます。逆に、マスクエントリ内にのみ存在した場合や、上述のいずれかのエントリ内にのみ存在した許可については、有効化されません。つまり、許可されなくなります。なお、所有者と所有グループに対するエントリは、マスクにかかわらず常に有効となります。詳しい仕組みについては、 表19.2「アクセス許可のマスク」 をご覧ください。
ACL は 2 種類に分類することができます。 1 つは 最小 ACL と呼ばれ、所有者/所有グループ/その他に対するエントリのみを持ちます。これらはファイルやディレクトリに対する従来のパーミッションと同じ意味を持ちます。それに対して 拡張 ACL では、それより多くのエントリを持ちます。拡張 ACL ではマスクエントリを持たなければならないほか、必要に応じて特定ユーザや特定グループのエントリを持ちます。
タイプ |
テキスト形式 |
---|---|
所有者 |
|
特定ユーザ |
|
所有グループ |
|
特定グループ |
|
マスク |
|
その他 |
|
エントリの種類 |
テキスト形式 |
パーミッション |
---|---|---|
特定ユーザ |
|
|
マスク |
|
|
適用されるパーミッション: |
|
図19.1「最小 ACL: ACL エントリと許可ビットとの比較」 と 図19.2「拡張 ACL: ACL エントリと許可ビットとの比較」 には、最小 ACL と拡張 ACL の例を示しています。この図は 3 つのブロックから構成され、左から順に 「ACL エントリの種類指定」, 「ACL の例」, 「対応する従来型のパーミッションビット」 (たとえば ls
-l
で表示されるもの) をそれぞれ示しています。いずれの場合であっても、 所有者クラス のビットは ACL の所有者エントリに紐づけられ、 その他のクラス はその他の種類のエントリに紐づけられます。ただし、 グループクラス の部分については、この 2 つの例で対応付けが異なることに注意してください。
最小 ACL の (マスクエントリがない) 場合、グループクラスのパーミッションは、 図19.1「最小 ACL: ACL エントリと許可ビットとの比較」 に示されているとおり、そのまま ACL の所有グループのエントリに対応します。拡張 ACL の (マスクエントリがある) 場合は、 図19.2「拡張 ACL: ACL エントリと許可ビットとの比較」 に示されているとおり、グループクラスのパーミッションはマスクエントリに対応することになります。
このようなマッピングの仕組みが存在することで、アプリケーション側が ACL に対応していない場合でも、問題なく動作できるようになっています。つまり、 ACL は従来のパーミッションビットに対する 「微調整」 として働くことになります。なお、パーミッションビット側を変更することで ACL 側も反映されますし、逆に ACL を変更することでパーミッションビット側にも反映されます。
コマンドラインで getfacl
と setfacl
の各ツールを使用することで、 ACL を参照したり制御したりすることができるようになります。本章では、これらのコマンドの使用方法について説明しています。
まずはディレクトリを作成する前に、 umask
コマンドを利用してファイルオブジェクトの作成時におけるパーミッションのマスク値を設定してください。 umask
027
のように実行することで、所有者には全ての許可を ( 0
) 、グループに対しては書き込みビットを禁止し ( 2
) 、その他に対しては全てを禁止する ( 7
) ように設定します。 umask
では、パーミッションのビットのうち、マスク (無効化) したいビットを 1 にします。詳しくは 11.4項 「既定の umask」 もしくは umask
のマニュアルページをお読みください。
次に mkdir mydir
を実行して、 mydir
ディレクトリを umask
で設定したパーミッションビットで作成します。作成したディレクトリに対して ls
-dl mydir
のように実行し、まずはどのようなパーミッションが設定されているのかを確認します。このコマンドの出力は、たとえば下記のようになっているはずです:
drwxr-x--- ... tux project3 ... mydir
次に getfacl
mydir
を実行して、 ACL の初期状態を確認します。出力は下記のようになっているはずです:
# file: mydir # owner: tux # group: project3 user::rwx group::r-x other::---
最初の 3 行には、ディレクトリの名前と所有者、および所有グループに関する情報が表示されています。次の 3 行には、それぞれ所有者と所有グループ、そしてその他に対する ACL エントリが表示されています。この時点では最小 ACL であることから、 getfacl
の出力で得られる情報と ls
で得られる情報は、書式は違うものの違いがありません。
次に、 geeko
というユーザと mascots
というグループに対して、読み込み/書き込み/実行の各許可を設定します:
#
setfacl -m user:geeko:rwx,group:mascots:rwx mydir
setfacl
コマンドで -m
を指定することで、既存の ACL を修正しています。その後ろのパラメータは修正すべき ACL エントリを表していて、エントリ同士の間はカンマ区切りで指定しています。最後のパラメータは ACL の修正を適用したい先の名前 (ここではディレクトリ) を指定しています。上記のように実行したあとは、 getfacl
コマンドで再度 ACL を表示してみてください。
# file: mydir # owner: tux # group: project3 user::rwx user:geeko:rwx group::r-x group:mascots:rwx mask::rwx other::---
すると、ユーザ geeko
およびグループ mascots
に対するエントリと、マスクエントリがそれぞれ追加されていることが分かります。マスクエントリでは、全てのアクセス許可がそのまま動作するように、全ての許可が指定されています。 setfacl
では、 -n
を指定しない限り、マスクエントリを自動調整する処理を行います。マスクエントリは特定ユーザや特定グループ、そして、所有グループに対する最大限の許可を指定する項目です。ここで再度 ls
-dl mydir
を実行してみます。すると、 mask
の設定に対応してパーミッションが表示されるようになります。
drwxrwx---+ ... tux project3 ... mydir
行頭には従来型のパーミッションビットが表示されていますが、ここに +
という表示が追加されているのが分かります。これにより、この項目に対して 拡張 ACL が存在していることを表しています。
ls
の出力にもあるとおり、マスクエントリの許可には書き込み許可が含まれています。従来型のパーミッションの仕組みでは、このビットが設定されていれば、所有グループ (上記の例では project3
) が、そのディレクトリ (上記の例では mydir
) に対して書き込み権限があることを表していました。
しかしながら、所有グループに対する実際の許可は、所有グループに対するアクセス許可とマスクエントリの許可に従って動作することになります。この例では r-x
が適用されます (表19.2「アクセス許可のマスク」 をお読みください) 。そのため、この例における所有グループに対する実際の許可については、 ACL を追加したあとも特に変わっていないことになります。
さらに setfacl
や chmod
でマスクエントリを編集します。たとえば chmod
g-w mydir
のように実行します。こちらを実行後、 ls
-dl mydir
を実行すると、下記のような表示になります:
drwxr-x---+ ... tux project3 ... mydir
getfacl
mydir
の出力は下記のようになります:
# file: mydir # owner: tux # group: project3 user::rwx user:geeko:rwx # effective: r-x group::r-x group:mascots:rwx # effective: r-x mask::r-x other::---
chmod
を実行してグループクラスのビットから書き込み権限を取り除くと、 ls
の出力でマスクビットが適切に変更されていることがわかるようになります。これにより、書き込み権限は mydir
の所有者に限定されることになります。 getfacl
でも同じ内容を確認することができます。出力には上記のようなコメント部分 (#) が含まれるようになり、マスクエントリによって実際に作用するアクセス許可と元々のアクセス許可に差異があることを示すようになります。元のアクセス許可に戻したい場合は、 chmod g+w mydir
を実行してください。
ディレクトリには既定の ACL を設定することができます。既定の ACL は特殊な ACL で、ディレクトリ内に作成されたオブジェクト (サブディレクトリやファイル) に対して適用される、既定のアクセス権として動作します。
ディレクトリに対して設定された既定の ACL が、ファイルやサブディレクトリに適用される場合は、下記の仕組みで動作します:
サブディレクトリに対しては、親ディレクトリ側での既定の ACL が自分自身の既定の ACL として適用され、自分自身の (通常の) ACL としても適用されます。
ファイルが作成された場合、既定の ACL を自分自身の ACL として引き継ぎます。
ファイルシステムのオブジェクトを作成する際、全てのシステムコールは mode
パラメータを使用します。このパラメータは、新しく作成するファイルシステムオブジェクトに対して、アクセス許可を設定するためのものです。親ディレクトリに既定の ACL が設定されていない場合、 mode
パラメータで指定された値から、 umask
で指定されたビットを取り除いてアクセス許可を生成し、新しいオブジェクトに適用します。親ディレクトリに既定の ACL が存在する場合は、既定の ACL と mode
パラメータとの間で重複するビットのみを新しいオブジェクトに設定します。この場合、 umask
の設定は無視されます。
下記に示す 3 つの例では、ディレクトリと既定の ACL に対する主な操作を説明しています:
既存のディレクトリである mydir
に対して、既定の ACL を追加するには、下記のように実行します:
>
setfacl -d -m group:mascots:r-x mydir
setfacl
コマンドに対して -d
オプションを指定することで、既定の ACL 内での編集作業 (-m
オプション) を実施することを表します。
このコマンドを実行すると、下記のような結果になります:
>
getfacl mydir
# file: mydir
# owner: tux
# group: project3
user::rwx
user:geeko:rwx
group::r-x
group:mascots:rwx
mask::rwx
other::---
default:user::rwx
default:group::r-x
default:group:mascots:r-x
default:mask::r-x
default:other::---
getfacl
は (通常の) ACL と既定の ACL の両方を返します。既定の ACL は default
で始まる部分です。既定の ACL に対して、 mascots
グループに対するエントリを指定しただけですが、 setfacl
は通常の ACL から既定の ACL をコピーして作成しています。既定の ACL は、アクセスの際の許可に直接影響するものではなく、新しいファイルシステムオブジェクトを作成した場合にのみ影響があります。新しく作成したオブジェクトは、親ディレクトリの既定の ACL のみを引き継ぎます。
次の例では、 mydir
内に mkdir
でサブディレクトリを作成しています。これにより、既定の ACL を引き継ぐようになります。
>
mkdir mydir/mysubdir
getfacl mydir/mysubdir
# file: mydir/mysubdir
# owner: tux
# group: project3
user::rwx
group::r-x
group:mascots:r-x
mask::r-x
other::---
default:user::rwx
default:group::r-x
default:group:mascots:r-x
default:mask::r-x
default:other::---
期待のとおり、新しく作成したサブディレクトリである mysubdir
は、親ディレクトリの既定の ACL を引き継いでいます。 mysubdir
の ACL は、 mydir
の既定の ACL に対する正確なコピーになっています。このディレクトリ内にさらにファイルやディレクトリを作成した場合も、この既定の ACL をコピーして適用することになります。
さらに touch
コマンドを利用して mydir
ディレクトリ内にファイルを作成します。今回は touch
mydir/myfile
と入力して実行します。 ls
-l mydir/myfile
の結果は下記のようになります:
-rw-r-----+ ... tux project3 ... mydir/myfile
getfacl
mydir/myfile
の結果は下記のようになります:
# file: mydir/myfile # owner: tux # group: project3 user::rw- group::r-x # effective:r-- group:mascots:r-x # effective:r-- mask::r-- other::---
touch
コマンドは新しいファイルを作成する際、 mode
パラメータに 0666
を指定しますので、 umask
や既定の ACL (詳しくは 19.4.3.1項 「既定の ACL の効果」 をお読みください) で制限を設定しない限り、全てのユーザクラスに対して読み込みと書き込みを許可する形でファイルを作成します。つまり、 mode
パラメータに含まれていない全てのアクセス権限が、対応する ACL エントリから削除されていることになります。ただし、グループクラスの ACL エントリからはビットを削除せず、マスクエントリを変更して mode
で指定されていないビットが設定されないようにします。
このような仕組みにより、 ACL とアプリケーション (たとえばコンパイラ) を円滑に作用させることができるようになっています。たとえばコンパイラなどでは、不用意に実行されたりしないように、いったん厳しめのアクセス権を設定しておいて、あとから実行可能にすることがあります。 mask
の仕組みにより、必要なユーザやグループに対してだけ、実行できるようにすることができます。
ACL で保護されたファイルシステムオブジェクトに対して、プロセスやアプリケーションがアクセスを行う場合、事前にチェックアルゴリズムが適用されます。基本的な考え方としては、所有者エントリ, 特定ユーザエントリ, 所有グループエントリ, 特定グループエントリ, その他の順で確認が行われます。アクセスは、そのプロセスに最も適したエントリに従って処理されます。また、権限では複数のエントリを合成して判断するようなことはおこないません。
プロセスが複数のグループに属していて、複数のグループエントリに該当するような場合は、さらに複雑な処理になります。この場合は、該当する複数のエントリの中からランダムにエントリが選択され、必要なアクセス許可を得ることになります。この処理は、どのエントリが最終的に 「アクセスを許可する」 という結果を引き出すのかはわかりません。同様に、該当する複数のエントリグループの中のどれであってもアクセスが許可されない場合、ランダムに選択されたエントリから、最終結果である 「アクセス拒否」 が発行されます。
ACL は新しいアプリケーションの要件を満たすため、複雑な許可シナリオを実装しています。従来型のパーミッションと ACL の両方の考え方は、賢く組み合わせることができます。基本的なファイルコマンド ( cp
, mv
, ls
など) も、 Samba, Nautilus と同様に ACL に対応しています。
vi, vim, emacs はいずれも ACL に完全対応していて、バックアップを含め、ファイルへの書き込み時にアクセス許可を保持することができます。ただし、残念なことに多くのエディタやファイルマネージャには、 ACL への対応がありません。その他のエディタでファイルを修正した場合は、エディタのバックアップ方式によって、ファイルの ACL が保持される場合と保持されない場合があります。エディタ側が元のファイルに対して書き込みを行うような場合であれば、 ACL は保持されるものの、古いほうのファイルをバックアップファイルとしてリネームしてから、新しいファイルに更新後のものを書き込むような場合は、エディタ側が ACL に対応していない限り、 ACL が失われてしまうことになります。また、 star
以外のアーカイバを使用した場合は、 ACL を保持したままバックアップを行うことはできません。
ACL に関する詳細については、 getfacl(1)
, acl(5)
, setfacl(1)
の各マニュアルページをお読みください。