演習問題の解答 い。プログラムは、たとえば root 特権を持っているのに ( 安全性の低いアクセス経路からでは ) ファイルの変更ゃある種の行為を実行できないことによって、この機構の存在を推測することが できる。 第 8 章 8-2 8.3 ( a ) 重み付けは、実行キューの選択において、プロセスの優先順位に異なった定数値によるバイア スを提供する。その他の、 CPU 利用度のような要素も他のプロセスとの優先順位の優劣を左右す るので、重み付けの効果が発揮されない場合もある。ゆえに、重み付けの効果は決定的というよ りは確率論的である。 (b) この機構をより有効にするためには、 CPU 利用度の積算か優先順位の減衰にも重みを考慮さ せることによって、それらの効果を変更することが考えられる。しかし、その結果としてプロセッ サ資源の利用に累積的な影響が及ぶ。この方法で、プロセスが ( 他の一時的な要素ではなく ) 重み だけによって、他のプロセスよりも優先してスケジューリングされると保証できれば、重みの確 率論的ふるまいをなくすることができるだろう。 ( a ) できない。シグナルが発見され、配送されるには、プロセスがいったんユーザーモードに戻る 必要がある。 (b) ERESTART の場合、シグナルが配送されたあとにシステムコールがもう一度発生され、制御 は tslee() の要求を発行した場所に戻される。このためループは ( おそらく ) 完了する。 EINTR の場合、システムコールは「システムコールに割込まれた」というエラーを返したので、エラーリ カバリーを行う必要がある。その違いは、システムコールによるシグナルの配送が透過的に行わ れるか、処理を強制されるかの違いである。 (a) マルチレベルのフィードバックを持った、ラウンドロビン形式による、プリエンテイプスケ ジューリング。 (b) キューイングモデル ( フィードバックに 3 つのレベルがある ) trap/syscall:swtch tsleep (.. tsleep (. .. 31. curproc 優先順位で分割された実行キュー wakeup ( ) 30 ( 0.01 秒 ) クロック割り込み curproc - - > p_cpu 十十 ( 1 秒 ) クロック割り込み schedcpu ( ) 0 1 swtch selqueue (ljmp tss) プロセッサ 573
第 7 章証明と特権 (kern/cred. c 、 kern/priv. c) ないということだ。地理的なアクセスというのは、つまり誰かが鍵を使う ( あるいは、この場合、特権 を使う ) には、ある場所にいなければならない、ということである。 私たちは、役柄によって地理的判定の規範を設け、その判定に基づいてアクセスのスコープを制限し ようと考えている。つまり、システム管理のための基本的なアクセスを得るためには ( これはコンピュー タが侵入されるときの一般的な経路である ) 、ただパスワードを知っているだけではなく、適切な地理的 条件の場所にいなければならない。このようにすれば、進入者は地理的条件を判定するための機構を完 全に転覆させなければならなくなるので、侵入はずっと難しくなる。 現在のところ、私たちは主として非常にシンプルな地理的判定を考えている。要するに「このユーザー はローカルターミナルからシステムに入ったのか、あるいはネットを介しているのか」ということだ。 のような判定ならば、完全にカーネルの内部で下せるので、転覆される危険のある外部プログラムについ て考慮する必要はない。このため、転覆される危険のある要素の範囲を非常に小さくすることができる。 このプロジェクトにはデモンストレーションという最小限の目的しかないので、例を示して説明する という目的にふさわしいアプローチを採択している。しかし注意深く構築すれば、このコンセプトには もっと大きな意味を持たせることができよう。それを行うには、より多くの慎重さと責任が必要となる。 そうした条件に関する厳密な議論は、「 AppendixB : 役柄をベースとするネットワークレベルのセキュ リティに関する計画案」を参照してほしい。 7.3 プロセス特権 : kern/priv.c kern/priv. c というファイルには、特権をカーネルの他の部分から使うための、きめ細かい定義を 提供する、マシンに依存しないコードが含まれている。これは基本的には、特権処理の実行を許可する ための " 関門 " である。 通常のユーザープロセスが行う種類の処理に含まれないものすべてを「特権」 (privileges) という。特 権にはそれぞれユニークなコードが割り当てられていて、カーネル内で使用される個々の特権は、 ( たと えある関数の中で同じ特権を似たような方法で数多く使っていて、関数の中の場所だけが異なるような 場合でも ) その特定のコードによって識別される。特権が要求されるのは、その処理に割り当てられて いるユーザー証明である * 28 。ューザー証明は、その処理を開始した者を、識別子と役柄という 2 つの独 立したプロバティによって記述する。 7.3.1 識別子 哉別子 (identification) は、この処理の実行を要求しているのは誰か、という情報を提供するものであ る。この識別子は、すでに何らかの方法で承認されている ( 通常はパスワード付きのログインを介して ューザーのアクセスを許可することによる ) 。多くのシステムでは、このレベルの制御でも十分だが、最 * 28 ユーザー証明の詳細については、本章の kern/cred. c と、その説明を参照してほしい。 二 1 一口 386
9.3 ファイル記述子機構 . kern/descrip. c 場合、ファイルはそのファイル記述子に割り当てられている既存のメッセージの数を管理する。ソケッ トが、いわば実際に存在するのは、それがオープンされている間だけだからである * 54 。 ファイルはファイル関数 * 55 への参照にそれぞれ対応する、高いレベルの実体である。この高いレベル のオプジェクトを、その下の抽象レベル ( vnode と socket) に結び付けるのは、動作をより低いレベル の層に伝える一連のファイル操作である。したがって、オープンされているファイルへの読み出しや書 き込みといった実際の操作のセマンティクスを実現するには、あるメソッド ( 上記の演算子のどれか ) を 介して、実行すべき操作を、具体的な vn 。 de なり s 。 cket なりに渡さなければならない。 開かれている ( オープンされている ) という概念は、ファイル層に特有の、状態付きの処理の概念であ る。それより下位のデータ抽象は、そのほとんどが状態を持たないからだ。さまざまなプロセスが同じ ファイルをオープンし、ファイルのさまざまな部分に対してさまざまな操作を行うかもしれない。そこ で、ファイルという抽象の役割は、あるファイルに対する特定のオープンイベントの独自の情報を保持 するための場所を提供することにある。 実際、たとえ 1 個のプロセスでも、同じ基本オプジェクトを別個のファイルインスタンスでオープン することができる ( そのファイルを何度も別個にオープンできる ) 。そうすると別々のファイルオフセッ トボインタを管理できるので、 1 個のファイルに対して何度も seek を行わずにすむというメリットがあ る。たとえば、パスワードデータベースなど認証に使うファイルで、ファイルの中の認証データの各部 分がファイルの中に分散されていて、それぞれ別のオフセットから連続的に格納されている場合、 1 つの ファイルをオープンして、別の種類のレコードをアクセスするたびに、 seek によってファイルオフセッ トボインタを前後させるよりは、そのファイルに対して数個のファイルインスタンスを持ち、それぞれ 次の処理に合わせて適切なオフセットを指すようにしておけば、 seek を行う必要はなくなる。読み出し または書き込みを要求された個々のファイルインスタンスは、それによって暗黙のうちにシーク動作を 行うだけである。認証の場合、いくつかの種類の抽象の中で、その認証機構が二次記憶のどこに存在し、 あるいはどのようにコード化されているかといったことを知るための秘密の経路を、 ( 副次的なシステ ムコールを挟むことによって ) seek が提供してしまう場合がある。こういった副次的な操作を防止すれ ば、物理的な情報を隠すことができる。 ファイルインスタンスは、 vnode や socket のような共有オプジェクトを指すことができるが、 UNIX の特異な性質として、複数のプロセスが 1 個のファイルを指すことによって、いわばファイルオフセッ トを共有することが可能である。このような特異性が生まれたのは、パイプによるプロセス間通信機構 で、ファイル記述子を親プロセスから子プロセスに渡す方法が必要だったからである。その結果、ファ イルを渡すためにファイルを共有しなければならなかったのである。この特別な性質は、 UNIX を、ク ラスタ環境で望まれるような完全なメッセージべースのオペレーティングシステムに変えようとする試 みにとって、ちょっとした悩みの種となっている。たとえばプロセッサクラスタの中の 2 つのマシンで、 * 54 クローズされたあとは永続しない。 * 55 POSIX 1003.1 仕様書で指定されている、 open 、 close 、 read 、 write 、 ioctl 、 stat など。 469
8.1 プロセスのプロッキングとスケジューリング : kern / synch. c 現在のシステムは、そのようなニーズに合わせて構成されてはいないが、そのような利用方法に対応す る準備は講じてある * 7 。 ソフトウェア管理のコストが増えるだけでなく、粒度の細かい再スケジューリングのオーバーヘッド 代わりに * 12 、システム全体にばらまくことになる。 ための代償として、本章で説明しているケースのように衝突が発生する個所を数個のファイルに集める よって、通常の UNIX におけるプリエンプションの制限を覆している。しかしながら、この利点を得る のは当然のことである。 Solaris のようなシステムは、高度にプリエンプテイプなシステムにすることに このアプローチでは、粒度の細かいプリエンプションが可能であり望ましいということが前提となる スレッドシステムでは優先順位の再計算のコストが主要なファクタとなるだろう。 かせないと考えている。この場合リスケジューリングの間隔が非常に短くなるので、このようなマルチ 式マルチプロセッサのスケーラブルな利用 ( つまりすべてのプロセッサを最大限に利用すること ) には欠 (Solaris など ) は、マルチプロセッサにおける粒度の細かいスレッドのスケジューリングが、共有メモリ を作るうえで重要なことのひとつは、動作のスケジューリングに関する考慮である。一部のシステム クラスタ方式 * 11 でも、並列処理システムでも使えるようにできるだろう。並行処理のためのシステム 386BSD は ( まだ ) マルチスレッドシステムではないが、メモリ共有式のマルチプロセシング * 10 でも、 ◆ 8.1 .4.1 マルチスレッドのスケジューリング いないが、このような形で実行できるようにするのは簡単だろう。 ために、キューイングが使われる。 386BSD は、まだこのようなスケジューリングの規範には対応して 行う能力である。したがって、メモリと時間を資源として同様に、しかも正確にスケジューリングする のスケジューリングされたトランザクションに追いつけるだけ迅速に、メモリ資源の割り当てと解放を るのだ * 9 。この場合、スケジューリングの規範となるのは転送要求の到着時間と、 2 次記憶ユニットへ はなく、ディスクをバッファリングするメモリへのディスクのバンド幅のスケジューリングが問題にな I / O を行うために巨大なメモリを作成しなければならないような場合 * 8 には当てはまらない。即時性で しかしながら、上記のどちらのケースも ( 時間的な拘東に関するものであるため ) 、大量のディスク * 8 * 9 * 10 * 11 * 12 * 7 リアルタイムシステムの特殊なケースとして、 ( たとえばネットワークのように ) 非常に大量の入出力を行 うものがある。このようなシステムでは、プロトコルおよびネットワークにデータストリームがよどみな く流れるようにするには、レスポンスタイムの保証が必要になるだろう。 たとえば商用データベースを実装する RAID クラスタなど。 このようなアプリケーションは、巨大な move 命令のようなものだ。これが実際に行っている仕事は、単 に大容量記憶装置の中のある種のレコードを、その記憶装置の別の場所に、可能な限り迅速に移すことだ こではディスクアームのポジショニングやプラッタの待ち時間の削減などを含めてマイクロ けである。 秒単位の時間でも貴重なのである。メインフレームというものが存在する理由はプロセッサ自身ではなく、 このような動作、すなわち実際のチャネルにある。 たとえばマルチプロセッサを搭載する Compaq Systempro など。 独立したマシンが超高速ネットワークで相互接続されているもの。 swtch プリミテイプを使うのは、このファイルと、マシンに依存しないシグナルを扱う ker Ⅱ / sig ・ c と、 マシン依存のトラップを扱う i386 / trap. c だけである。 401
第 5 章プロセスのライフサイクル (kern/fork. c 、 kern/exit. c) 現在の実装を、もっと実際的な視点から見て感じるのは、資源がオーバーロードした場合の処理が、 あまりよくできていないという点である。現在、回復が可能なのはプロセス数が限界に達した場合だけ である。もしメモリやプロセッサ時間がオーバーロードしたとしても、割り込まれない状態でメモリを 待ってプロックされる以外に、親がそれを知る機会はないのだ。このシステムの現在の使いかたでは、 プロセス数に関して過大な需要はなく、メモリも貴重品ではないので、これは特に重大な問題にはなっ ていない。しかし、もしそうだったら、この関数を設計しなおして、不可欠なステートを取得できない 場合もプロセス生成に失敗できるように実装しなければならなくなるだろう。このような " 改良 " では、 いったん行ったプロセス生成処理の一部を取り消さなければならないので、関数はずっと複雑になって しまう。このような実装がいまだに試みられていない理由は、主に 2 つある。それはカーネルに汎用で 割り込みを許可するメモリ割り当ての機構がないこと ( これは開発中である ) と、一時的なメモリ不足 の状態と、いつまで続くかわからない資源のプロックとを見分ける方法がないことである ( 後者は I / O バッファリングに対する需要がある以上、ずっと繊細で大きな問題である ) 。以上のようなケースについ て完全に対処していないと、 1 秒も続かないようなメモリ不足によっても、プロセス生成がアポートさ れなかったり、あるいは間違ってアポートされたりすることがありえる * 19 。 プロセスの関係についてより多くの情報を管理することによって、プロセスリストの線形な検索を避 けることも可能である。たとえばユーザー証明に、システム上のプロセス数に直接対応する参照カウンタ をつけてもいい。しかしプロセスのセッションを連結したり切り離したりする必要もあるので、こうす ると証明の管理方法が、ずいぶんと複雑になるだろう。また、 setgid の問題に対処するには * 20 、ユー ザー証明をユーザーフィールドとグループフィールドに分ける必要もあるだろう。これによって大きな 利益が得られるか、それとも問題をシステムの別の場所に移すだけなのかは不明である。 最後にもうひとつ改良が可能な領域として、共有ユーザースレッドに必要な共有基礎構造をサポート するための、残りの変更を完成させることである。ファイル記述子と統計情報への共有アクセスも追加 しなければならない * 21 。これが現在どう行われているかを調べるには、プロセスの限界と証明を使うこ とになるだろうが、このような共有の管理を集中して行うために p ー shareflags といったプロセスエン トリフィールドを使い、どの要素の変更が共有されているかを構造体に対応するビットによって示すほ うが賢明かもしれない。しかし、この改良も軽量級・重量級プロセスのサポートと同様に、今のところ は特に望まれていないようである。 * 19 * 20 * 21 278 それでも、ユーザープログラムが行儀よく書かれていて fo て k ( ) をリトライしてくれれば破滅的な状況に はならないのだが、残念ながらユーザープロセスのすべてがそうするとは限らない。 第 7 章の kern/cred. c 、および第 9 章の kern/execve . c を参照してほしい。 もっともユーザースレッドの統計情報は、解釈に議論の余地がある。
6.3 kern / sig. c の関数とファイル構成 次に、シグナルの結果としてプロセスステートを変更する。競合状態が起こらないように、プロセス の proc 工ントリへのアクセスを排他的に行う。プロセスが割り込みを禁じてスリープしている場合、 処理はこれで終了し、プロセスがスリープを終了してユーザーモードに戻るまでシグナルは発見されな い。もし、この条件が満たされなければ ( たとえばフロッピーディスクのようなプロックデバイスがオー プンされてもメディアがレディにならないときなど ) かなり長い ( 永久的な場合もある ) 時間が経過しな いとシグナルを受け取らない場合もある。ただしスリープが割り込み可能な場合、トレースされている ナルのビットをクリアし、プロセスはウェイクアップ待ちの状態で残される。スリープ中のプロセスに このシグナルのプロバティが、単にデフォルト動作として継続するだけであれば、ペンディングシグ = SIG_DFL) { goto out ; p->p-sig & = Nbit ; if ( (prop & SA—CONT) & & action [ FiIe : /usr/src/kernel/kern/sig ・ c , line : 531 ] プロセスだけは、シグナルを発見できるように実行させることが許されている。 対する継続は、ウェイクアップを意味しない。 [ FiIe : /usr/src/kernel/kern/sig ・ c , line : 537 ] if ( (prop & SA-STOP) ! = 効 & & action p->p-sig & = &bit ; StOP(), の , sig); goto out ; goto runfast ; 次は、スリープ中のプロセスを停止状態に変える場合である。 } else = SIG_DFL) { このシグナルのプロバティカゞデフォル トのストップであれば、ペンディングビットを削除し、補助関数 stop ( ) によりプロセスを強制的に停 止状態にして、継続の前に停止シグナルを提示する。こで注意すべきことは、スリープ中のプロセス が停止状態に変わったからといってスリープ状態の性質が変化したわけではないので、 SIGCONT シグ ナルによって継続させられれば、元のスリープ状態に戻ることがある。また、 psig Ⅱ al ( ) はプロセス のコンテクストにないときや、コンテクスト切替を安全に行えないときにも呼び出されることがあるの で、プロセスの再スケジューリング ( stop ( ) 関数のオプションのひとつである ) は行われない。 それ以外の場合、もしシグナルがプロセスのコンテクストに配送されてデフォルト以外の動作で扱わ れるのであれば ( たとえば捕獲されるかプロセスを終了させる ) 、シグナルが可能な限り迅速に配送され るように ( たとえば、上記の 2 つの場合のどちらも、プロセスは明示的ないし暗黙のうちに終了させら れる場合があり、資源がシステムに返却される ) 、そのプロセスは ( もし優先順位が下げられていたら ) 329
第 3 章 CPU 固有のプリミティブ ( i386 / t 「 ap. c 、 i386/cpu. c) 命令 invlpg の特殊なケースである。むやみにカーネルをパニックさせたりューザープログラムを終了 させたりしないように、これらの命令をインラインでエミュレートするのが、この機能の目的であり、 たとえソフトウェアがプロセッサに対して正しく対応していなくても、ある程度状況を修正して、とに かくシステムを実行できるようにしている。 フォールトを引き起こしたのが、これらの特殊な命令以外であった場合、カーネルがパニックするか、 あるいはユーザープロセスの場合であれば、不正命令のシグナル ( SIGILL ) を受けてこのシグナルに対 応するコードがフォールトの原因を示す ( この場合も、スーパーバイザモードかユーザーモードかは明 暸なので、それらについては考慮しない ) 。 [ FiIe : /usr/src/kerne1/kern/i386/trap. c , line : 243 ] = の case T—ASTFLT ー T—USER : case T_ASTFLT : goto out ; / * プロセス切替を行う * / コンテクスト切替のシグナルとして、 T-ASTFLT という透過的なフォールトが使用されている。これは 割り込みレベルのシグナル生成コードが使うもので、現在実行中のコンテクストにプロセスがシグナルを 受けたことを知らせ、 trap() を経由させてシグナルの評価と、場合によってはプロセスコンテクストの 切替を行う必要があることを通知する。このフォールトの名前は VAX/PDP-II の ast(asynchronous trap ) に由来する。この ast は、フォールト割り込みでカーネルからユーザーモードに戻る前に、自動的 にフォールトを発生するのに使用された。 [ Fi1e : /usr/src/kerne1/kern/i386/trap. c , line : 247 ] else if (cpu-dna-em) { / * ソフトウェア浮動小数点演算 ? * / break; if (cpu-dna & & (*cpu-dna) ( (void *)&frame) ) / * ハードウェア浮動小数点演算コンテクスト切替 ? * / case T-DNA ー T-USER : case T_DNA: S 1 gno ucode break; if ( (*cpu-dna-em) ( (void *)&frame) break; SIGFPE ; = FPE_FPU_NP_TRAP ; 浮動小数点演算コプロセッサは、プロセッサと同じチップの場合も、別チップの場合もあり、これをア クセスしようとすると、デバイスの不在を示すフォールトである T ー DNA ( devicenotava ⅱ able ) が発生 することがある。ハードウェアの浮動小数点演算ユニットが存在する場合、コンテクスト切替の存在を知 120
7.1 196 ] プロセス保護機構 : kern/cred. c [ Fi1e : /usr/src/kernel/kern/cred. c , int seteuid(), uap, retval) struct proc *p; line : struct args { int } *uap; int *retval ; euid; seteuid() の引数はシステムコールハンドラに適したものである。実効ユーザー ID を変更するのに 必要な特権を持っていない場合はエラー (EPERM) を返す。このプロシージャの副作用として、もし変 更が許可されたら、このプロセスが特権を使用したことを示すアカウントフラグがセットされる。前に 述べたように、特権があったら必ずその特権を使わなければならないというわけではない。 seteuid() は ( 希望する ) 新しいユーザー ID を受け取り、何も返さない。 ◆ 7.1.14.1 seteuid() の実装 seteuid() は非常にシンプルな関数であり、特権をチェックして、もし許可されたらユーザー証明を 新しいユーザー ID に変更する。ユーザー証明を変更する前に、変更できる証明のユニークな集合を確 保する。 [ Fi1e : /usr/src/kernel/kern/cred. c, line : 2 の 9 ] if (euid ! = pc—>p-ruid & & euid ! = pc->p-svuid & & (error = use-priv(pc—>pc-ucred, PRV—SETU 工 D, p) ) ) ザー ID であれば、その場合も必ず了承される。 に設定できる。また、設定しようとしているユーザー ID が実ユーザー ID か、あるいは保存されたユー 最初に特権を調べて、この動作を実行できるかどうかを確認する。自分自身のユーザー ID なら、常 return (error) ; プログラムを実行していて、保存されたユーザー ID が実行中のファイルのユーザー ID である場合 しかしながら、保存されたユーザー ID が実ユーザー ID と異なる場合もある。たとえば setuid 自分自身に特権がなくても同じプログラムからそれを入手することができる * 19 。 新しいユーザー証明 ( 保存されたユーザー ID ) を、相互に繰り返して設定することもできる。この場合、 (kern/execve . c 参照 ) 、その setuid プログラムは、古いユーザー証明 ( つまり実ューザー ID ) と、 373 ユーザ—ID は、 root の名義でその処理を行っているユーザーである。 * 19 たとえば root に対して setuid() を行う場合、それによって保存されるユーザー ID は root だが、その実 ザー ID で seteuid() を行い、そのユーザーの実効証明によって処理を行えばいいだけである。この間 そのプログラムがスーパーユーザーの特権を使いたくない期間は、 getuid() によって取得した実ユー
9.2 バイナリファイルの実行 : kern/execve. c このプロセスには、 exec 処理が施されたことを意味するマークが付けられる * 45 。その直後で、通常 のエミュレーションなしの場合と同様、エミュレートされたプロセスの処理も完了している。工ミュレー トされたプロセスの場合、 setusrid の処理と vfork() による同期 (kern/fork. c 参照 ) は行ってい いが、そのほかはすべてエミュレーションで行っているので、 こで処理してはならない。ゆえに、工 ミュレータはプログラムの実行に成功しなかったら setuserid の機能を放棄しなければならない。こ れはエミュレータの信頼性に関わる問題のひとつにすぎない。 もし親プロセスがあり、このプロセスを待っていたら、そのプロセスをウェイクアップし、待機のフ ラグをクリアする。これは vfork() を行ったプロセスに、子は実行を開始したので親も実行を継続して いいのだと知らせるために使用される。 vfork() では、常に親よりも前に子を実行するという順序が定 められている。これは初期の BerkeIey システムのなごりで、当時の vfork() は ( コピーオンライトで はなく ) 完全に実装されていたので、子プロセスは親プロセスの資源を、コピーする代わりに一時的に 借りて使っていたからである。このシステムでは vf 。 rk ( ) はコピーオンライトの代わりに使われている のではないので ( そのため、初期の BSD システムのように完全には実装されていない ) 、この手続きの 効果は、単にプロセスの同期を強制するというだけであり、親の資源を使用していないのだから資源を 返すことはない * 46 。 もし実行されたファイルに setuserid または setgroupid の属性が設定されていたら、そのプロセ スの証明を、ファイルのユーザー ID またはグループ ID ( あるいは、その両方 ) に合わせて更新する。た だしこれを行うのは、プロセスが ptrace されて ( STRC ) いない場合に限られる。ユーザーがデバッガ を使って不当な特権を入手し、資格の検査を回避するのを防ぐためである。もし setuserid あるいは setgro Ⅱ pid が呼び出されていたら、プロセス証明を変更しなければならない。その場合、ユニークな 証明の集合が必す作成されるように、 kern/cred. c の modpcred() 関数を介して、証明モジュールに 変更要求を送る。ユニークな証明の集合を入手したら、現在のものと、保存されたユーザー ID および グループ ID の証明を更新する。保存されたユーザー ID とグループ ID は、 setuserid プログラムに よって設定された特権を廃棄するときに使用される。 もし execve() のユーザーが実際にはエミュレーションであった場合、このファイルでの処理はこれ で完了し、内部的に実装されているエラー ( EEMULATE) を使って、システムコールのエントリハン ドラに対して、エミュレータによる処理の続行を命じる。 * 45 この機能は現在使われていないが、将来、 fork はしたが、そのあとに続く exec を行わないプロセスを検 出するために使われるかもしれない。 * 46 ェミュレータが 1 つではなく、複数使われる場合、親と子の資源をどのように共有するかという問題は、さ らに複雑になるだろう。 463
7.3 プロセス特権 : kern/priv. c 定されるかどうかチェックする。その場合、失敗は記録される * 34 。許可が得られなかった場合、エラー (EPERM) を返す。 もしユーザーが承認を得すに危険な特権をアクセスしようとした場合は、システムのロギング機能を 使って、このユーザー ID が危険な特権 ( 管理者以上の役柄を必要とするもの ) を使おうとしたことをシ ステム管理者に警告する。 [ Fi1e : /usr/src/kernel/kern/priv. c , line : 162 ] if ()v & & p & & p->p-acflag) acct-priv (p , ACCT-PRIV-SUCCESS , cr , prv) ; acct—priv(), ACCT-PRIV—FAIL, cr , prv) ; return ()v ? : EPERM) ; else 役柄をチェックして許可が得られるかどうかチェックしたあと、その証明チェックの結果を見て、プロ セスが特権をアクセスできるユーザー ID ( またはグループ ID 、補助グループ (D) を持っているか判定 する。もしすべてが正しければ、同様にアカウントフラグを更新して特権の使用を記録する ( もしプロ セス存在フラグがセットされていれば ) 。現在のプロセスアカウンティングでは、特権の使用をこれ以上 複雑にトレースすることはできない。 特権が無事に与えられた場合、エラーは返されないが、証明が不適切と判定された場合はエラー (EPERM) を返す。 ◆ 7.3.5.2 386BSD の use ー p ⅱ v ( ) に関する設計上の選択肢とトレードオフ 私たちが役柄べースのセキュリティという道を選んだ理由は、暗号化などの技術に依存せずに、シス テムのセキュリティを向上させる、他の方法を探究したかったからである。すべてのセキュリティの基 本として暗号化を用いたくない理由のひとつは、 ( 特に国境を越えるのに ) 政府によって制限が課せられ るような、厳しく管理された技術だからである。 386BSD のような国際的に支持されている研究システ っした制限は、あまりにも重い障害となる。また、多くの暗号化技術は、知識と資源のレ ムの場合ー、 ベルが高い攻撃に弱い傾向がある。 この分野は長い年月をかけて研究されてはいるものの、暗号化を基本とした機構が平均的なユーザー すなわち、ほとんどの仕事をローカル PC で行い、ただネットワークからシステムをいたずらされたく はないと思っているユーザーにとって、どれほど便利なものかは、まだ明らかではない。そこで、管理 の手数をほとんど ( あるいはまったく ) 増やさずに、このシステムの典型的なエンドユーザーのために システムとその資源に対するアクセスを制限できるような、代わりの機構を探し始めたのである。 * 34 現在は、もしプロセスがあれば、そのアカウントフラグに対して行うが、 度なアカウンティングシステムの代わりである。 これは将来行われる、もっと高 393