5.4 ACLの処理

表 5.1. 「ACLエントリタイプ」に、考えられる6つのACLエントリタイプをまとめています。各エントリで、ユーザまたはユーザグループのパーミッションが定義されます。所有者エントリでは、ファイルまたはディレクトリを所有しているユーザのパーミッションが定義されます。所有者の所属グループエントリでは、ファイルの所有者の所属グループのパーミッションが定義されます。スーパーユーザは、chownまたはchgrpを使用して所有者または所有者の所属グループを変更できます。その場合、所有者と所有者の所属グループエントリは、新しい所有者と所有者の所属グループを参照します。各名前付きユーザエントリでは、エントリのクォリファイアフィールドで指定されたユーザのパーミッションが定義されます。各名前付きグループエントリでは、エントリのクォリファイアフィールドで指定されたグループのパーミッションが定義されます。名前付きユーザと名前付きグループのエントリのクォリファイアフィールドだけが指定されます。その他のエントリでは、他のすべてのユーザのパーミッションが定義されます。

マスクエントリでは、名前付きユーザ、名前付きグループ、および所有者の所属グループのエントリで与えられたパーミッションをさらに制限するために、それらのエントリのパーミッションのどれが有効で、どれをマスクするかが定義されます。パーミッションは、マスク内と同様にこのいずれかのエントリ内にも存在する場合に有効です。マスクだけまたは実際のエントリだけに指定されているパーミッションは有効ではありません。つまり、パーミッションは与えられません。所有者と所有者の所属グループのエントリで定義されているすべてのパーミッションは常に有効です。表 5.2. 「アクセスパーミッションのマスキング」の例に、このメカニズムを示しています。

基本的なACLクラスには、次の2つがあります。最小ACLには、所有者、所有者の所属グループ、およびその他というタイプのエントリだけが含まれます。これらのエントリは、ファイルやディレクトリの従来のパーミッションビットに対応しています。拡張ACLは、このACLを越えるものです。このACLには、マスクエントリが必ず含まれ、名前付きユーザと名前付きグループのタイプのエントリがいくつか含まれている場合があります。

表 5.1 ACLエントリタイプ

タイプ

テキスト書式

所有者

user::rwx

名前付きユーザ

user:name:rwx

所有者の所属グループ

group::rwx

名前付きグループ

group:name:rwx

マスク

mask::rwx

その他

other::rwx

表 5.2 アクセスパーミッションのマスキング

エントリタイプ

テキスト書式

パーミッション

名前付きユーザ

user:geeko:r-x

r-x

マスク

mask::rw-

rw-

有効なパーミッション:

r--

5.4.1 ACLエントリとファイルモードのパーミッションビット

図 5.1. 「最小ACL: ACLエントリとパーミッションビットとの比較」図 5.2. 「拡張ACL: ACLエントリとパーミッションビットとの比較」に、最小ACLと拡張ACLの2つのケースを示しています。図は、3つのブロックから成ります。左側のブロックはACLエントリのタイプを示し、中央のブロックはACLの例を示しています。右側のブロックは、従来のパーミッション概念に基くそれぞれのパーミッションビット(ls -lなどで表示される)を示します。どちらのケースも、所有者クラスのパーミッションは、ACLエントリ所有者に割り当てられます。その他のクラスのパーミッションは、それぞれのACLエントリに割り当てられます。しかし、グループクラスのパーミッションの割り当ては、2つのケースで異なります。

図 5.1 最小ACL: ACLエントリとパーミッションビットとの比較

最小ACL: ACLエントリとパーミッションビットとの比較

最小ACL(マスクなし)の場合、グループクラスのパーミッションは、ACLエントリ所有者の所属グループに割り当てられます。このようすを図 5.1. 「最小ACL: ACLエントリとパーミッションビットとの比較」に示しています。拡張ACL(マスクあり)の場合、グループクラスのパーミッションは、マスクエントリに割り当てられます。このようすを図 5.2. 「拡張ACL: ACLエントリとパーミッションビットとの比較」に示しています。

図 5.2 拡張ACL: ACLエントリとパーミッションビットとの比較

拡張ACL: ACLエントリとパーミッションビットとの比較

この割り当て方法により、アプリケーションがACLをサポートしているかどうかにかかわらず、アプリケーションとのスムーズなインタラクションができます。パーミッションビットによって割り当てられたアクセスパーミッションは、ACLで他のすべてのパーミッションを「微調整」する場合の上限を表します。パーミッションビットの変更は、ACLに反映されます。その逆も同様です。

5.4.2 アクセスACLが設定されたディレクトリ

コマンドラインにgetfaclおよびsetfaclを指定すると、ACLにアクセスできます。これらのコマンドの使用法については、次の例に示します。

ディレクトリを作成する前に、umaskコマンドを使用して、ファイルオブジェクトを作成するたびにどのアクセスパーミッションをマスクする必要があるかを定義します。コマンドumask 027では、デフォルトパーミッションを設定するために、所有者にすべてのパーミッションを与え(0)、グループ書き込みアクセスを拒否して(2)、その他のユーザにはパーミッションを与えません(7)。umaskは、実際に対応するパーミッションビットをマスクするか、それらをオフにします。詳細については、対応する umaskmanページを参照してください。

mkdir mydirは、umaskで設定されたデフォルトパーミッションでmydirディレクトリを作成します。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行には、所有者、所有者の所属グループ、およびその他という3つのACLエントリが表示されています。実際には、この最小ACLの場合、getfaclコマンドではlsで取得できなかった情報は生成されません。

読み取り、書き込み、実行の各パーミッションをさらにユーザgeekoとグループmascotsに割り当てるには、次のようにします。

setfacl -m user:geeko:rwx,group:mascots:rwx mydir

オプション-mを指定すると、setfaclに対して既存のACLの変更が求められます。このオプションの後の引き数は、変更するACLエントリを示します(複数のエントリはカンマで区切られます)。最後の部分には、こうした変更を適用するディレクトリの名前を指定します。設定されたACLを確認するには、getfaclコマンドを使用します。

# 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です(表 5.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を使用すれば、いつでも元のパーミッションに戻すことができます。

5.4.3 デフォルトACLが設定されたディレクトリ

ディレクトリには、デフォルトACLを設定できます。デフォルトACLとは、ディレクトリのオブジェクトを作成するときにそうしたオブジェクトが継承するアクセスパーミッションを定義する特別な種類のACLのことです。デフォルトACLは、サブディレクトリとファイルに作用します。

5.4.3.1 デフォルトACLの作用

ディレクトリのデフォルトACLのパーミッションをそのディレクトリ内のファイルやサブディレクトリに渡す方法は、次の2種類があります。

  • サブディレクトリは、そのデフォルトACLおよびアクセスACLとして親ディレクトリのデフォルトACLを継承します。

  • ファイルは、そのアクセスACLとしてデフォルトACLを継承します。

ファイルシステムオブジェクトを作成するすべてのシステムコールは、新たに作成したファイルシステムオブジェクトのアクセスパーミッションを定義するmodeパラメータを使用します。親ディレクトリにデフォルトACLが設定されていない場合、umaskで定義されたパーミッションビットは、modeパラメータで渡されるパーミッションから取り去られ、その結果が新しいオブジェクトに割り当てられます。親ディレクトリのデフォルトACLが存在する場合、新しいオブジェクトに割り当てられるパーミッションビットは、modeパラメータのパーミッションとデフォルトACLで定義されているパーミッションの重複部分に相当します。この場合、umaskは無視されます。

5.4.3.2 デフォルトACLのアプリケーション

次の3つの例は、ディレクトリとデフォルトACLの主要な操作を示しています。

  1. 次のコマンドで、既存のディレクトリmydirにデフォルトACLを追加します。

    setfacl -d -m group:mascots:r-x mydir
    

    setfaclコマンドのオプション-dを指定することによって、setfaclは、後続の変更(オプション-m)をデフォルトACLに加えるように求められます。

    このコマンドの結果を詳しく見てみます。

    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コマンドを実行しただけですが、setfaclで他のすべてのエントリが自動的にアクセスACLからコピーされ、有効なデフォルトACLが作成されました。デフォルトACLが、アクセスパーミッションに即時に作用することはありません。デフォルトACLは、ファイルシステムオブジェクトが作成された場合にのみ作用し始めます。こうした新しいオブジェクトは、それぞれの親ディレクトリのデフォルトACLからのみパーミッションを継承します。

  2. 次の例では、mkdirmydirにサブディレクトリを作成しています。このサブディレクトリは、デフォルト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が継承されます。

  3. touchコマンド(touch mydir/myfileなど)でmydirディレクトリにファイルを作成します。次に、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コマンドは、新しいファイルの作成時に値0666を指定してmodeを使用します。この値は、umaskおよびデフォルトACLにほかに制限がなければ、すべてのユーザクラスのファイルが読み取りと書き込みのパーミッションで作成されることを表します(5.4.3.1項 「デフォルトACLの作用」を参照)。つまり、mode値に含まれていないアクセスパーミッションはすべて、それぞれのACLエントリから削除されます。パーミッションは、グループクラスのACLエントリから削除されていませんが、マスクエントリは、modeで設定されていないパーミッションをマスクするように変更されています。

    この方法により、ACLが設定されたアプリケーション(コンパイラなど)とのスムーズなインタラクションができます。制限付きアクセスパーミッションでファイルを作成し、作成たファイルを後で実行可能ファイルとしてマークすることができます。maskメカニズムでは、正当なユーザやグループが必要に応じて実行可能ファイルを実行できることが保証されます。

5.4.4 ACLチェックアルゴリズム

任意のプロセスまたはアプリケーションがACL保護されたファイルシステムオブジェクトにアクセスできるようになる前に、チェックアルゴリズムが適用されます。基本的なルールとして、ACLエントリは、所有者、名前付きユーザ、所有者の所属グループまたは名前付きグループ、およびその他の順に調べられます。アクセスは、プロセスに最も適したエントリに従って処理されます。パーミッションは累積しません。

プロセスが複数のグループに属し、複数のグループエントリに適する可能性がある場合は、さらに複雑になります。エントリは、必要なパーミッションを備えた適切なエントリから無作為に選択されます。どのエントリによって最終結果「アクセス許可」が実行されるかには関係ありません。同様に、適切なグループエントリのどれにも必要なパーミッションが設定されていない場合は、無作為に選択されたエントリによって最終結果「アクセス拒否」が実行されます。