2013年12月26日木曜日

*nixの入門にBSDはどうですか

ディストリビューション/パッケージマネージャ Advent Calender 25+1日目の記事です.
最終日なのにておくれましたが、神は寛大なので赦してくれるとおもいます.

さて、みなさんディストリビューションと言うと、Linuxばかりです.
たしかにカーネルだけを開発するLinuxと違いユーザーランドも作るBSD系は
ディストリビューションがあまりないです.
しかし、FreeBSDにいくつかディストリビューションがあるのはご存知でしょうか

Debian GNU/kFreeBSD
Gentoo BSD
ArchBSD
PC-BSD

上3つは、みなさんもどこかで目にした名前だとおもいます.

に上2つ、DebianとGentooは本家がカーネルだけをBSDに挿し替えたプロジェクトとしてやっています.
FreeBSDのカーネルと同時に開発されてるユーザーランドのツール郡は、それをパッケージ化していますが、
その他追加としてインストールするパッケージはLinux同様それぞれのチームが保守管理しています.
しかし、FreeBSDはPortsで独自にパッチを当てていることが多く、普通にビルドしようとしてもコケることが多いです(ビルドシステムを提供するGentooはBSDで使うと割と悲惨です)

しかし、下二つ(ArchBSDとPC-BSD)はPortsからビルドしパッケージ化しているため、
比較的多くのパッケージが容易に使用できます.




ArchBSDはArchチームは関係なく、Archファンがやってるプロジェクトで、
今年の始めに*.isoなインストールメディアがリリースされた新しいプロジェクトです.
最初は全くパッケージがありませんでしたが最近はGnome等のパッケージも用意されています.
pacmanが使えるFreeBSDという感じなので、pacman以外のメリットはあんまりないかもしれません.







して、最後に上げたPC-BSD、これを特に今回は紹介します

PC-BSDは、他3つと違い、純粋にFreeBSDのためだけのディストリビューションです.
Linux向けディストリビューションの派生とかじゃありません.
プロジェクトは2005年から始まっていますが2006年にiXsystemsが買収し、
現在もiXsystems社の元開発が行われています.



Debian、Gentoo、Arch どれもLinuxでもXが最初からなかったり、インストーラーが付属してない
といった"硬派"なディストリビューションです.
FreeBSD自体、Xは後に手動でインストールせねばなりません.



PC-BSDはそれらと一線を画す"軟派"なディストリビューションで、
GUIのインストーラが付いている上にデフォルトでXがインストールされます
また、インストール時にデスクトップ環境を選択することができます(デフォルトはKDE)
そして、これまたBSDらしくはないのですが、
AppCafeというGUIのパッケージマネージャまで付いています.
おそらく、この時点でも、「おや、BSDとはいってもかなり簡単そうだ」とおもっていただけるでしょう.



さらに最近のことですが、PC-BSDが以前から使用していた*.pbi形式の独自パッケージを止めて
FreeBSD 10から正式採用されるpkg(8)の形式のパッケージに変更しました.
パッケージはPC-BSDがFreeBSDのものとは別に管理しているサーバーからインストールしますが、以前のPC-BSDと違い本家と互換性があります
(pkg(8)についてはこの同アドベントカレンダー8日目の拙著記事を参考にしてください)

もう一点、最近のこととしては、PC-BSDがローリングリリースモデルを採用しました.
ArchやGentooで採用されているモデルで、ディストリビューションがバージョンを持たず、
カーネル含むコアシステムや、各種ソフトウェア、それら全てをパッケージマネージャが
管理して、常に最新にするモデルです.



PC-BSDの概説は以上ですが、ここで記事タイトル通り、ちょっとした主張をしたいとおもいます.
情報技術を学ぶのに、*nix OSを勉強しよう、Ubuntuがラクだよ!というのを見かけることは多いです.
しかし、たとえばwebデザインを学ぶにはAdobeのソフトウェアが使え、コードもブラウザが動作すれば十分だったりしてWindowsやMacで良かったりします.
そうでなくとも、近年はMacがBSDベースだったりしてちょっとしたコマンドの学習に良いかもしれません.
Ubuntuやその派生(たとえばMint)がよくインストールの簡易な*nix入門向けディストリビューションとしてよく紹介されますがそもそも極端にGUI化が進んで独自要素の強いUbuntu派生が初学者に向くのでしょうか.

そこで、インストールが簡易で、安定し、歴史的にもUNIXらしいUNIXライクなOSとして、
PC-BSDを使うという選択はどうでしょうか.
なにもLinuxばかりがUNIXライクOSではありません.
仮想環境にインストールするにも悪くないOSだと考えるのですが、どうでしょうか


記事は以上です

2013年12月22日日曜日

The Rust Programming Language

Rust Advent Calender 21 + 1日目の記事です. (ておくれました)

といっても特に良いTipsとかあるわけではないのですが、
今回初めて知って、インストールして使用してみた雑感などをば.

インストール

私が普段使用しているArch Linuxなら、
なんと公式のレポジトリ ( community repo )入りを果たしているために
最新のRust ( rust-0.8 )が特に特別な操作をしなくともインストールできます
# pacman -S rust
Gentooの場合は
# layman -a gentoo-rust
としOverlayを追加した上でrustをemergeしてください.
rust-0.8のebuildのIUSEが間違っててそもそもemergeが開始できなかった問題は修正されたはず
ただ、私の環境ではなぜかstage0のビルドでコンパイラがエラーを吐いたので、
rust-0.8でなくrust-9999をemergeしました.

Debian/Ubuntu/Mintの場合はnightly buildのPPAがある模様

Mac OS Xならhomebrewやmac portsですんなり入るっぽいです.

RedHat系は知りません.

つかってみる

公式にmanualtutorialがあります.
結構詳しくて良いですね.学習しやすそう.

とりあえず定番、フィボナッチ数を表示してみる
実行結果
0 term: 0
1 term: 1
2 term: 1
3 term: 2
4 term: 3
5 term: 5
6 term: 8
7 term: 13
8 term: 21
9 term: 34
変数は基本immutable、mutableな変数の宣言はmutで修飾しています.
パターンマッチが簡単に使えるのが良いです.
また、記法の雰囲気が従来のC系の言語に近いので
この言語を使ってみる精神的障壁が低いかもしれませんね.

見てわかる通り、ifやwhileの条件式(conditioal)は()で括ったりはしません.
関数の返り値はreturnで返しますが、実行の最後の値を返り値とみなせるようです
(returnの省略)
;セミコロンは文末やセパレータではなく、nilまたは()を返す文として;が使われるようです
(return ()と等価)

この言語でおもしろいなーと思ったのがメモリの確保です
    let x = 10;
は普通に領域をスタックに取るようですが
{
    let y = ~5;
}
という風に~を使うと領域がヒープに確保され、{}を抜けた時点で
デストラクタが呼ばれ領域が解放されるようです.
文法としてメモリアロケートがあるのがおもしろい.
システムプログラミングを意識してるためでしょうか.

また、変数の値に@を付けて宣言するmanaged boxというものもあるようで、
これは参照カウントで領域を解放するか判断するっぽいです.

この言語の特徴はこういった変数の取り扱いがシンタクスレベルで豊富なことにあるのではないかと考えます.

おわりに

本記事はテキトーにチュートリアルみながら思った雑感を書いていきましたが、
私の英語力不足による誤解や誤記が含まれているかもやしれないので、
もしそれらを見つけた場合はコメントとかでつっこんでくださると幸いです.
そして、これから低レイヤでこういう言語つかえると楽しそうですね

2012/12/26追記
オンラインのC++実行環境として有名な、めるぽんさんのwandboxにRustが追加されました
これで、いつでもどこでもだれでも、RustのGit最新版を試すことが可能です

2013年12月21日土曜日

2013年12月8日日曜日

@toshi_a被害者の会


これは mikutter Advent Calender 2013 8日目の記事になります.



@toshi_a というておくれの教祖については、
mikutterユーザーの皆様はよくご存知だと思います.

そんな彼は今年のAdvent Calenderにかような記事を出しました

mikutter Advent Calendar 2013 3日目 mikutterのマルチアカウント・マルチサービス

mikutterは次期メジャーアップデートのver0.3からマルチアカウント・マルチサービスに対応しています.
その例として彼は*プレイしたこともない*艦これをプレイするプラグインをリリースしました.


私がこれに気がついたのはこの記事が書かれた実に2日後でしたが、
まだmikutterで艦これという声は聞こえてきていませんでした.
そこで、!!純粋に!!mikutterで艦これをしてみたいという欲求の元このプラグインをインストールしました.


結果



そして


おい……


おい!

これは許さんぞ…… おのれ……!! 純粋な気持ちを踏みにじった@toshi_aめ…!!


それからどーした



パッチ作って、
  ( ^ω^) これを
  ⊃)  (⊂

  ( ^ω^) こうして
  ≡⊃⊂≡

  ( ^ω^) こうじゃ
  ⊃)  (⊂


@toshi_a だけが妙高大破状態になるようになりました.


このネタのためだけにmikutterのプラグインにちょっとだけ詳しくなれたので、
みんなもこういう改変で復讐しましょう!!!(????)


この件ですごい久々に50fav&RTいきました(しかも2つのpostそれぞれかなりfav&RTくらった)
普段はあんまりfav&RTされないのでびっくりしましたが、
みんなfavもRTも妙高さんにされているように見えて正直恐怖でした.


ちなみに先の画像のタブのとおり、結局艦これプラグインなんやかんやで使ってます.

FreeBSDの進化

これは ディストリビューション/パッケージマネージャ Advent Calender 8日目の記事です.

最近OSSというとLinuxがフィーチャーされがちで、BSDは古臭いイメージを持たれている方が多いかとおもいます.

ports? make install? めんどくせー、バイナリパッケージないのかよ.
えっバイナリパッケージあるけどインストールと削除とインストール済みリスト表示が全部別々のコマンドだって?
しかも削除するときはバージョン番号まで指定?
やってらんねー.

そんなあなたでも大丈夫、次期リリースのFreeBSD 10からはpkg(8)がパッケージ管理の標準になります.
現行の最新版リリースであるFreeBSD 9.2でも、このパッケージマネージャは試すことができるので、試してみてください

これで記事を終えるのは流石にひどいのでざっと使い方など説明

なにができるのか
# pkg                                                                                                        
usage: pkg [-v] [-d] [-l] [-N] [-j <jail name or id>|-c <chroot path>] [-C <configuration file>] <command> [<args>]

Global options supported:
        -d             Increment debug level
        -j             Execute pkg(1) inside a jail(8)
        -c             Execute pkg(1) inside a chroot(8)
        -C             Use the specified configuration file
        -l             List available command and exit
        -v             Display pkg(1) version
        -N             Test if pkg(1) is activated and avoid auto-activation

Commands supported:
        add            Registers a package and installs it on the system
        annotate       Add, modify or delete tag-value style annotations on packages
        audit          Reports vulnerable packages
        autoremove     Removes orphan packages
        backup         Backs-up and restores the local package database
        check          Checks for missing dependencies and database consistency
        clean          Cleans old packages from the cache
        convert        Convert database from/to pkgng
        create         Creates software package distributions
        delete         Deletes packages from the database and the system
        fetch          Fetches packages from a remote repository
        help           Displays help information
        info           Displays information about installed packages
        install        Installs packages from remote package repositories
        lock           Locks package against modifications or deletion
        plugins        Manages plugins and displays information about plugins
        query          Queries information about installed packages
        register       Registers a package into the local database
        remove         Deletes packages from the database and the system
        repo           Creates a package repository catalogue
        rquery         Queries information in repository catalogues
        search         Performs a search of package repository catalogues
        set            Modifies information about packages in the local database
        ssh            ssh packages to be used via ssh
        shell          Opens a debug shell
        shlib          Displays which packages link against a specific shared library
        stats          Displays package database statistics
        unlock         Unlocks a package, allowing modification or deletion
        update         Updates package repository catalogues
        updating       Displays UPDATING information for a package
        upgrade        Performs upgrades of packaged software distributions
        version        Displays the versions of installed packages
        which          Displays which package installed a specific file

Commands provided by plugins:

For more information on the different commands see 'pkg help <command>'.
以上がpkgコマンドのusageです.
pkgにはコマンドというものがあって、upgrade, install, remove, infoなどがそうです.
たとえば、
# pkg install パッケージ名
# pkg info
# pkg remove パッケージ名
でそれぞれ、指定パッケージのインストール、インストール済みパッケージのリスト表示、
指定パッケージのアンインストールが可能です.
# pkg autoremove
とすることで、pkg removeで消したパッケージの依存関係にあって要らなくなったパッケージを自動削除することができます.
# pkg search 検索文字列
で指定した文字列を使ってレポジトリからパッケージを検索することも可能です.

こうして見るとわかる通り、DebianやUbuntuのaptライクなコマンドで、現代的にパッケージ管理をすることができます.なので、Debian系Linuxユーザーが移行しても苦もなく使えるのではないでしょうか.

パッケージ追加でpkg_add -r パッケージ名、  インストール済みリスト表示にpkg_info、
パッケージ削除でpkg_delete パッケージ名なんて別々のコマンドを使う必要はもうありません

また、既存のバイナリパッケージシステムを使ってた人でも、
# pkg2ng
とするだけでpkg(8)での管理に移行できます! このコマンドを実行するとpkg(8)を管理するためのsqliteなデータベースが生成されます.
(: ただしこれは非可逆な操作なので気をつけてください )

FreeBSD 10.x以前のものなら/etc/make.confに
WITH_PKGNG=yes
と書き加える必要もあります


古いFreeBSDでpkgコマンドが入っていない場合でも、
# pkg_add -r pkg
ないしは
# cd /usr/ports/ports-mgmt/pkg && make && make install
でpkgコマンドを入手し、pkg2ngをつかうことでpkg(8)を使えます.

すでにこの管理システムのためのバイナリのミラーは国内に存在しています
http://ftp.jaist.ac.jp/pub/FreeBSD-pkgng/ [JAIST]

これを/usr/local/etc/pkg.confに書いてあげることで、より高速に使用することができるでしょう.


FreeBSD 10の追加される機能

ついでにFreeBSD 10自体の紹介も
今回のアップデートはかなり大規模で、さまざまな追加/変更が存在します.
そのなかで個人的におもしろそうなものをピックアップ

・ デフォルトコンパイラをGCCからClangに変更
・ DNSサーバーソフトをBINDからLDNSとUnboundに置き換え
・ Raspberry Piのサポート(!!)
・ BHyVe(ハイパーバイザ)
・ Hyper-V
・ AMD(Radeon)のGPUのKMSドライバ追加
・ SMP(マルチコア)フレンドリィなファイアウォール(pf)
・ 802.11nスタックの改善、AtherosのPCI/PCIeインターフェースな無線LANカードのサポート追加
  などなどといった無線LAN関係の改善
・ ZFSでTRIMやLZ4圧縮のサポート
・ FUSEのサポートをBaseシステムに追加
・ USBオーディオ2.0のサポート追加

などなどおもしろい機能が目白押しです.
Radeonと無線LANサポートの向上はデスクトップユースに嬉しいですね
(このマシン(ThinkPad x121e AMD)がグラフィックも無線もダメで悲しい思いをしていました)


おわりに

今回紹介した内容は、公式のwikiを参考にするともっとよく理解できるとおもいます
https://wiki.freebsd.org/pkgng
https://wiki.freebsd.org/WhatsNew/FreeBSD10

LinuxでwikiといえばArchかGentooだったりしますが、実はFreeBSDも公式のwikiやハンドブックが
充実しているので是非参考にしましょう.

正直、pkg(8)は既存のバイナリパッケージのコマンドの単なる置き換えなのですが、
aptライクになっていてユーザーフレンドリィでしかもいくつか機能が便利になってるように思われます.
また、FreeBSD10自体色々な機能の進化が見られるので、もう古臭いとか言わせません.
wikiなどが充実しているということは初心者にも安心です.

ということで、Linuxも良いですがFreeBSDも使ってみませんか?という話でした.


PC-BSDというディストリビューション(もし余裕があれば別記事で紹介します)なら
最初からXが入っておりpkg(8)を採用しててローリングリリースなので、
WindowsユーザーがUNIXライクOSの手習いにUbuntuだけじゃなくてこっちも候補に挙がるようになると、それはとってもうれしいなって.

2013年12月7日土曜日

カーネルおさんぽまっぷ超入門

Kernel/VM Advent Calender 2013 7日目

カーネル/VMはておくれなすごい人がけっこう集って、ネタとか披露しているようです.
今年のAdvent Calenderも既に濃い内容が集っています.

でも、私達パンピーにはカーネルとかちょっと難しすぎてそもそも
カーネル/VMという主題自体敬遠しちゃう……

ということで本当にカーネルの第一歩をやってみよう、というのがこの記事です.
記事タイトルはえりっく氏(@siritori)から無断で肖ってます.ありがとうございます


今年の他の記事が高度な内容なので
この記事が低レベル(低レイヤということでなく本当に程度が低いという意味で)ですいません.
普段からカーネル/VMに参加してる皆様、さようなら.
カーネル/VM界隈わいわいしてておもしろそうだけど怖くて敬遠してる方々、こんにちは.

前置きはこのぐらいで本文行きます. 少々長め.


1. イントロ

まず、いきなりカーネルのソースを読むのは無理です.どこから読んでいいやら、
よしんば読み始めてもどう読んで良いやらでさっぱりです.完全に未知の領域なわけですから.

最初は自分の興味のある場所から読んでいくのが良いかもしれません.

今回のネタはこれで行きましょう.ついさっきTLに流れてきました.
 実装が気になる? なら見てみればいいじゃない提督!

2. はじめかた

ということで、今回はsuコマンドがどうやってコマンドを発行したユーザーを判別しているか、
追ってみます

まずsuコマンドのソースについて.
ArchLinuxで、
$pacman -Qo /usr/bin/su
とすると、util-linuxパッケージに入ってることがわかります.
util-linuxで検索すると、ここからソースのtarballが入手できることが判明.
あ、ArchならabsのPKGBUILDに対してmakepkg -o、Gentooならportageのebuildに対してebuild unpackでソースが簡単に読める状態になります、良いですね!

こんな感じで解凍したファイル達が並びます.今回見たいのはログイン関連のコマンド(su)なので、login-utilsを見てみましょう.


su.cがありました.  まさにこれです.
中身は、こう
ひどい、これじゃなにもわからない

しかし、su.cの近くにsu-common.cというのがありましたね.これを読みましょう
https://gist.github.com/orumin/7837125
わー、長いナー. さすがにブログに埋め込むのも躊躇います.
とはいっても1000行ぐらいなので、ふつうといえばふつうです.
とりあえず、su.cにあったエントリポイントになっているsu_main(742行目)から読みましょう.

3. ユーザー空間からカーネル空間へ
けっこうこの時点で記事長くなってしまいましたがこれから本番なのでしばしのお付き合いを

su_main、850行目まではsuに渡されたオプションの処理とか前準備とか変数宣言やらで
興味深い場所はあまりないので、飛ばします.

ここで851行目に次の文が表れました
restricted = evaluate_uid ();
uidを評価する関数のようですね、おもしろそう.
uidとはUNIXのユーザーを識別する一意な値で、つまりuser idです
これは732行目に関数の実体が存在してて、
このような非常に短い関数です. ユーザーがrootかどうか判別するようですね.
おっ、 目的である、ユーザーの判別が出てきましたよ.
しかもgetuid();だなんてそのままな関数まで出てきました!

しかしこのgetuid()、utils-linuxのどのソースコードにも関数の実体はあらわれません.
manページでgetuidを引いてみると、getuid(2)はシステムコール、つまり、
OSに処理を依頼する特別な関数(OSのAPI)であることが判明します.

そう、ここがユーザー空間からカーネル空間への入口なのです!

4. うさぎの穴から不思議の国へご招待

OSにシステムコールを発行する時は、まずユーザー関数としてglibcのような
Cの標準ライブラリに実装されてるシステムコール関数を呼んでいます.
たとえば、glibc-2.18なら、sysdeps/unix/sysv/linux/i386/getuid.cを見ると、
INTERNAL_SYSCALLマクロでシステムコールが発行されていて、
これはsysdeps/unix/sysv/linux/i386/sysdep.SにアセンブリでINTERNAL_SYSCALLの実体が
書いてあります.
このアセンブリ命令がプロセッサに割り込み命令を出して割り込みベクタとか割り込みハンドラがどーたらこーたらって話は割愛します.

もし、興味があるのならば上記のglibcなどを読むのも良いでしょうが、
私達が知りたいのはgetuid(2)がLinuxでどう実装されてるかであって、どう呼ばれるかではありません.そこらへんは、OSの教科書を読むほうがわかりやすいでしょう.

さて、Linuxカーネルのソースコードは/usr/src/linux/にあったりします.
もしなければ、https://www.kernel.org/からダウンロードしましょう
今回私が読むのはLinux-3.12.2です.

LinuxやBSDといった現代のUNIXライクOSのソースコードはきちんとディレクトリにソースが分かれていて、目的のものを見つけやすいです.
これはLinuxカーネルのソースディレクトリですが、だいたいディレクトリ名で何が入ってるか
想像が付くとおもいます.
わかりにくいのは省略された名称であるmmやipc、archとかですが、mmはメモリ管理 archはCPUの命令の違いとかを吸収するためのアーキテクチャ依存のコード、ipcはプロセス間通信といった具合です.

重要なのは、ユーザー空間の普通のアプリの常識はカーネル空間ではそのまま通用するわけじゃありません
2つの空間はメモリアドレスで分離されてたりするため、別の空間のアドレスをそのままCで読みにはいけないです.
また、カーネル空間に標準Cライブラリがあるわけではありません
(だってカーネル空間の機能をAPI(システムコール)で呼びだして、glibcとかを実装していますから)


では今回はシステムコールを読みたいので、kernelディレクトリに移動しましょう.


さすがに、ここらへんになるとソースが膨大で、目的のソースを勘や総当たりで読むだけじゃ
目的の関数に到達できません
そこで、Linuxの便利なコマンドを紹介します
find ./ -name \*.c -or -name \*.h -exec grep 目的の関数名 {} /dev/null \;
これで目的の関数(今回はgetuid)を探せますね.
最近は
grep -R '目的の関数名' *.c
 でも再帰的に探してくれそうな気がしますし、-execより-printでパイプを使ってxargsのほうが速いかもしれません.


また、VimやEmacsのユーザーならばctags, etags, gtags等々のソフトを使ってクロスリファレンスをまず作成すると簡単に目的の関数にアクセスできます


とにかくこれで探してみると
kernel/sys.c:831の中にこういう関数がみつかります.
このSYSCALL_DEFINE0というマクロを、またまたgrepで探すと
include/linux/syscall.h:170にそのマクロを発見できます.
引数で渡した文字列(この場合getuid)をつかってsys_渡した文字列(今回はsys_getuid)という名前をリンカに渡すようにするマクロのようで、実装とはあんまり関係ありません.

関数のなかでuidを取得する実装に関係ありそうなのは、current_uid()な気がしますね


grepによるとcurrent_uid()はinclude/linux/cred.h:331に定義してあり、
#define current_uid()        (current_cred_xxx(uid))
 また、current_cred_xxx(uid)は同ファイル:326にて
#define current_cred_xxx(xxx)            \
({                        \
    current_cred()->xxx;            \
})
と定義されています.current_cred_xxx(uid)はcurrent_cred()の返り値のメンバuidを参照してるわけです.
同ファイル:252によると
ということらしいので、currentというのは現在のタスクを示しているようです.

ここででてくるRCUというのは、Read Copy Updateの略で、
読み込み、コピー、更新の動作を排他的に行うAPIらしいです リード・コピー・アップデート[Wikipedia ja]
ここで使われてるマクロ関数はinclude/linux/rcupdata.hに定義がありますが、
つまるところ引数で渡されたcurrent->credというポインタ値が指す先の値を取得してるようです.

そして、取得した構造体のメンバにあるuidを
curent_cred_xxx(uid) ( == curent_uid())で取得することで、
現在動作してるタスクのuidが判明し、
それが、getuidシステムコールの中で使われていることが判明しました.

ここでcred構造体は、include/linux/cred.hに戻って79行目をみると
と、たしかにuidというメンバを持っています.
currentの定義については、arch/x86/include/asm/current.hやarch/x86/include/asm/percpu.hに
あって、currentはカレントタスクを取得するget_current()の別名であることがわかりますが、
ここにはx86のアセンブリがマクロを多用しつつ書かれており、主題から逸れるので
興味のある人は読んでみてください


さて、もうあとはラストスパートです

一度kernel/sys.cの831行目に帰ってみると、先に判明したcurrent_uid()ほか
current_user_ns()を引数にfrom_kuid_munged()の返り値を、システムコールの
返り値にしてますね.

このfrom_kuid_mungedはkernel/user_namespace.cに定義されており、
これらがその関数です.
コメントを読むに、current_uid()で取得したのはカーネル空間のid(kid)なので、
それをユーザーの名前空間に変換してやってるみたいで、
実際にその処理をしているのがmap_id_up()のようです.
ここで使われてるmapという構造体の型はstruct uid_gid_mapで、
定義はgrepするとinclude/linux/user_namespace.hに発見できます

getuid(2)がfrom_kuid_mungedの引数としてcurrent_user_ns()の返り値を渡しているので、
current_user_ns()がstruct uid_gid_mapを返り値にしててnsはname spaceの略であることに
気がつけるかとおもいます.
current_user_nsについては今回は追いません(わたしが疲れましたし記事も長くなりました).

5. カーネル空間からの帰還

かくして、カーネル空間での仕事を終えたgetuid(2)は値を返してまたsu_common.cの
851行目に帰ってきます.
ここからさらにsuの仕事は続きます(カンジンの権限昇格はまだしてないですね)

しかし、これでカーネルに潜っていって、カーネルのソースを"読む"ことを体験できたのではないでしょうか.
正直最後のほうはちょっと丁寧さがなくなってて雑になってる解説でしたが、ここまで読んだ方は
ご苦労さまでした.

私はパンピーなので(大事なことなので二回(ry)今回読んだソースの解釈には
誤りがあるかもしれません.しかし、考え推測しながら読むことで、
一歩か二歩ぐらいはOSの仕組みへの理解に近づけたことでしょう.
そして、読んでいく上でどういう法則でソースコードが分割してあるかもなんとなく
想像が付くかもしれません


これから、current_uid()の返り値を常に0に置き換えてみたりとか(常にrootで動作!)
そういった改変や遊びをしたり、今回端折ったアーキテクチャ依存の部分や割り込みの仕組みに
ついても調べてみると、いろいろと楽しかったり理解が深まったりするんじゃないかな!
そしてようこそカーネル空間の不思議な国へ!

以上でした

2013年12月5日木曜日

ArchLinuxでHaskell Platform!

みなさん、Haskellしてますか? (挨拶)

Haskellの環境といえばHaskell Platformですが、
ArchLinuxにはHaskell Platformのバイナリパッケージがありません.

しかしご安心、Archには心強いAURという仕組みがありますね!
AURにはHaskell Platformがあります https://aur.archlinux.org/packages/haskell-platform/

しかし問題なのは、ArchのextraレポジトリのGHCのバージョン等の兼ね合いで
ビルドが通らないことがあります.
現時点は2013.02がビルトが通りますが、2012.04の時にはGHC7.4.2をAURからビルドするハメになりました.
それにパッケージは常に最新を使いたいのがArch-erですね?

そこで、次のようにしましょう.

1. まず、/etc/pacman.confの編集
[haskell-core]
Server = http://xsounds.org/~haskell/core/$arch
これを[extra]の前に置くことでghcやhaskellの各パッケージはここから持ってくることができます

2. つぎに署名の追加
pacman-key -r 4209170B
pacman-key --lsign-key 4209170B
これで先に追加したレポジトリが使用可能になります.
ここで署名を追加してよいか(haskell-coreレポジトリを信用するかどうか)は、個々人の責任の元に行いましょう

3. パッケージのインストール
pacman -S $(cat haskellplatform)
これだけで大丈夫です.
ここで読み込んでるhaskellplatformは次のgistを使いましょう(これがミソですよ).


このリストはちゃんとHaskell Platformのパッケージを網羅できてるとおもいます.
インストールも成功できるはず.

これでパッケージ郡をインストールすれば、Haskell Platformと同等の環境が手に入りますね
 以上でした