umaskは引き算ではない、新しいファイルの権限から消すビット

淡い桃色の穴あき板の下に青と緑の柱が並び、いくつかの場所が空いている。

同じプログラムでファイルを作ったのに、端末で実行したときとサービスとして動かしたときで、他の利用者から読める範囲が違う。こんな場面では、作成時に要求した権限だけでなく、プロセスが持つumask(ファイル作成マスク)も手掛かりになります。

umaskは、要求した権限から特定のビットを取り除く仕組みです。「666から022を引けば644」という覚え方では、たまたま答えが合う組合せしか説明できません。Linux man-pages 6.19の定義に沿って、何を取り除き、何を追加しないのかを見ていきます。

簡単にまとめると?

  • 親ディレクトリに既定ACLがない場合、新しく作るファイルの通常の権限ビットは、要求したmodeからumaskが指定するビットを消して決まります。
  • 計算は引き算ではなくビット単位の処理です。0666と0077なら0600、0600と0077でも0600となり、要求していない権限を追加することはありません。
  • 既定ACLがあるディレクトリでは決め方が変わります。umaskだけで結果を予測せず、作成するプロセス、要求mode、親ディレクトリのACLを分けて調べます。

読み書き実行の三つを、三組に分ける

通常のファイル権限には、所有者・グループ・その他という三組があり、各組に読み取りr、書き込みw、実行xのビットがあります。八進数ではrが4、wが2、xが1なので、6は読み書き、7は読み書き実行、4は読み取りだけを表します。ここでは特殊な権限ビットを除き、この九つのビットに注目します。

たとえばmodeの0666は、三組それぞれに読み書きを要求し、実行は要求しない指定です。先頭の0を含む表記は八進数を示しています。対してumaskの0022は、グループとその他の「書き込み」を取り除く指定です。数字の桁が対応していても、umaskは最終的に与えたい権限そのものではありません。

「要求する側」と「消す側」を別に置くと、結果が分かりやすくなります。0666から0022の書き込みビットを消せば0644、つまり所有者は読み書き、グループとその他は読み取りだけです。

引き算と一致しない例が、役割をはっきりさせる

親ディレクトリに既定ACLがない場合、通常の権限ビットの計算は mode & ~umask です。~はビットの反転、&は両側で1になっているビットだけを残す演算を表します。九ビットに限れば、umaskが1にした箇所をmodeから落とす操作と考えられます。

0666と0077を例にすると、umaskはグループとその他の読み取り・書き込み・実行をすべて落とします。要求modeに実行ビットは初めからありませんが、それを消そうとしても他のビットへ影響は出ません。残るのは所有者の読み書きだけで、結果は0600です。

一方、八進数として0666から0077を算術的に引くと0567になります。これは所有者に実行ビットを生じさせるなど、要求modeとは異なる権限を作ってしまいます。umaskの処理では、このような繰り下がりは起こりません。

さらにmodeが最初から0600なら、umaskが0077でも結果は0600のままです。すでに存在しないグループとその他の権限を消しても、所有者の権限は減りません。逆にumaskを0000にしても、0600が0666へ増えることはありません。umaskは要求の上限を狭めることはできますが、要求していないビットを足す役割は持たないのです。

要求0666とマスク0077のビット除去は0600になる。算術的な引き算は0567となり一致しない。要求0600なら同じ0077でも0600のまま。
九つの通常権限ビットだけを使った計算例。既定ACLがない場合を対象とする。独自の整数演算による図で、特定のLinux環境にファイルを作成した実測ではない。

同じumaskでも、作り手が要求するmodeで結果が変わる

次の表は、通常の権限ビットに対する計算例です。いずれも既定ACLがない場合に限ります。

要求mode umask 結果
0666 0022 0644
0666 0027 0640
0666 0077 0600
0777 0022 0755
0600 0022 0600

0666を要求する通常ファイルと、0777を要求するディレクトリでは、同じ0022でも0644と0755に分かれます。これはファイル種別を見てumaskが実行ビットを足した結果ではありません。作成を要求する側が渡したmodeの違いです。実際にどのmodeを渡すかはプログラムが決めるため、すべてのファイルが必ず0666を出発点にするとは限りません。

この違いは原因を調べる順序にも関わります。結果が0600だからといって、直ちに「umaskが0077だった」とは断定できません。プログラムが0600だけを要求していれば、0022でも同じ結果になるからです。最終的な権限から原因を逆算するときには、複数の組合せが同じ結果を作ることに注意が必要です。

既定ACLがあると、同じ式をそのまま使えない

ACLは、通常の所有者・グループ・その他の区分を拡張してアクセスを表現する仕組みです。Linuxでは親ディレクトリに既定ACL(default ACL)があると、新しいファイルはそのACLを継承し、umaskは使われません。そのうえで、作成時のmodeに含まれていない権限ビットが取り除かれます。

umaskの説明を覚えても、ここを飛ばすと共有ディレクトリで予測を外します。同じumaskで同じプログラムを実行しているのに保存場所によって結果が異なるなら、親ディレクトリの既定ACLは確認する対象です。既定ACLの存在は「必ずより広い権限になる」という意味ではなく、決定の経路が変わるということです。

ここではACLの各エントリや実効権限の詳細までは扱いません。表や図の計算をそのまま当てはめられるのは、既定ACLがない場合だという境界を保つことが大切です。

プロセスの設定と、既存ファイルの権限を分けて調べる

umaskは呼び出したプロセスが持つ設定です。Linuxの仕様ではforkで作った子プロセスに継承され、execveでプログラムを置き換えても維持されます。そのため端末とサービスの結果を比べるときは、対話シェルで見た値だけで結論を出さず、実際にファイルを作ったプロセスの条件を確認します。

また、umaskを変えても、すでにあるファイルの権限を一括して変更することにはなりません。新規作成時の制限と、既存ファイルの権限変更は別の操作です。「これから作るファイルの初期権限が違う」のか、「作成後に別の処理が変更した」のかを分けると、調べる対象を絞れます。

プログラムから値を調べる場合にも注意があります。umask()は以前の値を返しますが、同時に新しい値を設定します。取得後に元へ戻す二回の呼び出しは一つの不可分な操作ではないため、複数スレッドが同時にファイルを作るプログラムでは競合の原因になります。Linux 4.7以降では、/proc/pid/statusのUmask欄で対象プロセスの値を変更せずに確認できるとマニュアルに記されています。

結果が想定と違うときは、まず「誰が作ったか」「どのmodeを要求したか」「既定ACLがあるか」をそろえ、その後で保存された権限と比較します。umaskを単独の答えにせず、作成時に権限を決める入力の一つとして扱うと、同じ数字が違う結果になる理由を説明できます。

出典

  • Linux man-pages 6.19, umask(2)(ページ日付2026年2月8日)。DESCRIPTIONの権限ビットと既定ACL、NOTESの継承・取得時の競合・/proc表示を参照。図と表はこの定義に基づく独自の整数計算例。