2007年06月03日

ThinkPad X60 の無線LANドライバ

Linux では無線LANを使えるようにするのに苦労するケースが多いそうですが、 CentOS には ThinkPad X60 用の無線LANドライバが含まれていないために無線LANを使えず、4月のサンフランシスコ出張ではネットワーク接続に難儀しました。あちらでは無線LANが常識のようです。

で、6月のオタワ出張でも有線LANが使えない可能性が高いので、LANポート用無線子機を探してみたのですが、電圧が100V専用のものばかりでした。外国では電圧が100Vとは限りませんからねぇ。

そんな中、耳寄りな情報が見つかりました。 ThinkPad のいくつかの機種では ath_pci というドライバを使っており、 madwifi というパッケージに含まれているとのこと。早速 SourceForge.net からダウンロードして、インストールしました。

yum -y install kernel-devel
tar -jxf madwifi-0.9.3.1.tar.bz2
cd madwifi-0.9.3.1
make -s
make -s install

これで解決・・・かと思ったら、もう少し続きがありました。

http://www.clustcom.com/content/view/69/32/ によると、ThinkPad X60 に対応するためにはスナップショット版を使う必要があったのです。

tar -zxf madwifi-hal-0.9.30.13-r2351-20070519.tar.gz
cd madwifi-hal-0.9.30.13-r2351-20070519
make -s
make -s install

これで認識されるところまで来ましたが・・・接続テストを行う環境がありません。(^x^;;

posted by 熊猫さくら at 22:13| Comment(0) | TrackBack(0) | Linux

2007年05月02日

特定のカーネルだけをコンパイルする方法について

Fedora Core 6 用のカーネルをコンパイルする時に使用する SPEC ファイルには、特定のカーネルだけをコンパイルするための条件分岐が定義されているようです。

例えば、 xen カーネルだけを作成したい場合は、

rpmbuild -bb --target i686 --without up --without smp --without pae --without kdump --without debug --without doc --without headers kernel-2.6.20-1.2948.fc6.spec

のように指定します。 "%define with_XXX" で始まる行の XXX の部分を指定します。

posted by 熊猫さくら at 20:06| Comment(0) | TrackBack(0) | Linux

2007年04月29日

ThinkPad X60 に CentOS 4.4 をインストールする場合の注意について

私は ThinkPad X60 に CentOS 4.4 をインストールして使っていますが、2つ悩みがありました。

1つは、 CIFS 経由での書き込みアクセスが異常に遅い(通常5MB/s〜10MB/s出るはずが64KB/s〜1MB/s程度しか出ない)という問題です。

これは、 CIFS モジュール側ではなく e1000 ドライバ側の問題のようです。 CentOS 4.4 で使われている e1000 のバージョンは 7.0.33-k2-NAPI ですが、 http://sourceforge.net/projects/e1000 からバージョン 7.4.35-NAPI をダウンロードしてインストールすることで、通常の速度が出せるようになりました。

もう1つは、 AC 電源ケーブルの抜き差しや画面の出力先の切り替えを行おうとすると、システムがフリーズしてしまうという問題です。

これは、 NMI watchdog の問題のようです。カーネルのコマンドラインに nmi_watchdog=0 というパラメータを指定してやることで回避できるようになりました。これを見つけるまでは、 AC 電源ケーブルを抜き差しするためにシステムをわざわざシャットダウンしてやらなければいけないという、まるでデスクトップみたいな状況でした。(^x^;

posted by 熊猫さくら at 22:08| Comment(0) | TrackBack(0) | Linux

2007年04月05日

GRUBを使ってPCの電源を切る方法について

/sbin/poweroff コマンドでシャットダウンしても Power Down というメッセージが表示されるだけで電源をオフにする所まで行かずに止まってしまう環境に遭遇することがあるかと思います。私は ThinkPad X60 上で SMP 対応の CentOS 4.4 カーネルを稼動させていますが、 /sbin/poweroff コマンドで電源を切ることができません。

/sbin/poweroff で直接電源を切ることができないのであれば、電源を切るためだけのカーネルがデフォルトで選択されるように GRUB を設定しておき、 /sbin/reboot で再起動させることにより間接的に電源を切ることができないかなと思い、MLで質問してみました。
すると http://mail.nl.linux.org/kernelnewbies/2007-04/msg00023.html で予想外の方法を教えてもらったので紹介します。

なんと、 GRUB 自身の中に電源を切るための halt コマンドが備わっていたのです。

つまり、 /boot/grub/grub.conf の中に

title Power Off
    halt

というエントリを追加し、そのエントリがデフォルトで選択されるようにしておくだけでよいということでした。

http://kumaneko-sakura.sblo.jp/article/3392253.html では VMware で複数のゲストを順番に実行する方法について紹介しましたが、その時の前提条件であった「ゲストが poweroff コマンドによって電源断できること。」という条件を「ゲストのデフォルトエントリが( GRUB の) halt コマンドを実行するように設定されていること。」という条件に置き換えることができるのです。
SMP 対応カーネルを動作させている故に電源断ができないという問題を解決でき、夜間バッチが可能になりました。\(^^)/

posted by 熊猫さくら at 21:41| Comment(2) | TrackBack(0) | Linux

2007年03月21日

cat を使わずにテキストファイルを読み出す方法について

普通、テキストファイルの内容を表示する際には cat コマンドや less コマンドを使います。
例えば、 README を読む場合には、

cat README

のようにします。しかし、 cat コマンドや less コマンドが使えないという状況もあるかもしれません。(具体的には、プログラム自体が存在しなかったり、強制アクセス制御により実行が禁止されているといったケースです。)そんな時でも、 bash を実行することができるのであれば、以下のようにして内容を表示することができます。

exec 4<README; while read -u 4; do echo $REPLY; done

4 というのはファイルディスクリプタ番号で、 0 〜 1023 の間の未使用の数値を指定してください。

ちなみに、 TOMOYO Linux ではプログラムの実行時には読み込み権限のチェックはしません。これは、読み込み権限のチェックを行うようにすると、上記の方法によりプログラムの内容を読み出すことができるようになってしまい、スクリプトファイルの中に機密情報を埋め込めなくなってしまうためです。

posted by 熊猫さくら at 20:18| Comment(0) | TrackBack(1) | Linux

2007年02月22日

VMware で複数のゲストを順番に実行する方法について

VMware でいろんなディストリビューションのカーネルをコンパイルしていますが、一度に全てのゲストを並列実行させられるだけのCPUもメモリも無いので、1個ずつ順番に行っています。しかし、コンパイルが終わったゲストをシャットダウンして次のゲストを起動するために人手が必要になってしまっては夜間バッチができません。

幸い、 VMware には -x と -q という起動オプションが存在しているため、以下の条件を満たせば自動的に切り替えできます。

条件は、以下の2点です。
(1)ゲストの起動時に「ハードウェアが見つからない」などのダイアログが表示されないようになっていること。
(2)ゲストが poweroff コマンドによって電源断できること。

準備としては、ゲストを起動して、バッチコマンド(例えば rpmbuild や make-kpkg )を開始した直後にサスペンドさせます。バッチコマンドが始まった瞬間に応答が遅くなってしまうのを避けるために、バッチコマンドの開始前に sleep 10 とかを入れておくとサスペンド操作がスムーズに行くかもしれません。また、バッチコマンドの終了後に poweroff が実行されるようにしておきます。これをゲストの数だけ繰り返します。

準備ができたら、全ての VMware を閉じます。

その後、仮想マシンを順番に実行させるスクリプトを作成します。

Linux の場合はこんな感じです。(runvmware.sh)

#! /bin/sh
for i in "$@"
do
  vmware -x -q $i
done

chmod 755 runvmware.sh; ./runvmware.sh /var/vmware/*/*.vmx みたいに使います。

Windows の場合はこんな感じです。(runvmware.bat)

@ECHO OFF
FOR /F "usebackq tokens=2 delims==-" %%I IN (`FTYPE VMware.Document`) DO SET VMware=%%I
:START
IF "%1"=="" GOTO END
START "" /WAIT %VMware% -x -q %1
SHIFT
GOTO START
:END

コンテキストメニューの「送る」に登録するか、 runvmware.bat の上に *.vmx をドラッグ&ドロップして使います。

VMware Player の場合は -x と -q は不要ですので、 VMware Player しかインストールされていない環境ならば START "" /WAIT %1 のように省略できます。
VMware Player では右上のXボタンを押して閉じると自動的にサスペンドしてくれるので便利ですねぇ。

posted by 熊猫さくら at 05:47| Comment(0) | TrackBack(0) | Linux

2006年10月28日

余談:カーネルソースのパーミッション

http://www.atmarkit.co.jp/flinux/rensai/watch2006/watch10a.html によると David Wagner さんがカーネルのソースのパーミッションが 0666 なのは良くないのではないかと指摘したそうです。

実は、熊猫も http://lkml.org/lkml/2005/12/2/34 で質問したことがあります。

まぁ、 root で作業すべきではないのでしょうけど、 lxr をしようとしたらパーミッションの設定がおかしくて一般ユーザでは読めないファイルがあったという経験もあります。

なので、 TOMOYO Linux のカーネル構築手順書では、 root ユーザのまま tar で展開した直後に
find -print0 | xargs -0 chmod go-w --
するようにしています。

posted by 熊猫さくら at 12:12| Comment(0) | TrackBack(0) | Linux

2006年10月10日

個別環境に認証情報を残さないための Squid の設定について

インターネットへのアクセスにユーザ認証が必要なプロキシを必ず経由しなければいけない環境において、 http_proxy などの環境変数にユーザ認証のための情報を含めたくない場合への対処法です。
注意:私は Squid には詳しくないので、鵜呑みにするのではなく、他のサイトの情報も確認してください。

通常は http_proxy などの環境変数に認証情報と一緒にプロキシサーバを指定しますが、そのようにするとヒストリ機能や設定ファイルや /proc/PID/environ 等から認証情報が丸見えになりやすい状況になってしまいます。そこで、認証情報を環境変数に指定するのではなく、認証情報を追加して上流プロキシサーバへ転送してくれるプロキシサーバを用意して、環境変数にはそのプロキシサーバの情報だけを指定します。

まず、他人がHDD上のファイルを参照してしまう心配の無い環境(例えば Windows XP )に Squid をインストールします。そして、 squid.conf の

# TAG: cache_peer

というセクションの末尾に、以下のように cache_peer を指定します。

cache_peer 上流プロキシのIP parent 上流プロキシのポート番号 3130 no-query no-netdb-exchange login=上流プロキシの認証で使うユーザ名:上流プロキシの認証で使うパスワード

こうしておけば、 squid.conf にアクセスされるかパケットを盗聴されない限り、認証情報が他人に見られないようにできます。

次に、アクセス許可の指定ですが、例えば以下のように指定します。

# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
acl host1 arp アクセスを許可するホスト1のMACアドレス(例:00:0C:29:12:34:56)
acl host1 arp アクセスを許可するホスト2のMACアドレス
acl host1 arp アクセスを許可するホスト3のMACアドレス
acl local-servers dst 上流プロキシを経由しないネットワーク(例:192.168.0.0)/ネットマスク(例:255.255.255.0)
always_direct allow local-servers
never_direct allow all
http_access allow host1

誰でも自分のユーザ名とパスワードで上流プロキシにアクセスされては困るので、MACアドレスで制限を掛けます。なお、MACアドレスによる制限は同一ネットワークセグメント上でないと使えません。

「GET はできるのに POST ができない」場合は never_direct allow all を忘れているものと思われます。 POST の場合はデフォルトでは上流プロキシを経由しないで直接目的のサーバにアクセスしようとしてしまうようです。しかし、上流プロキシを経由しないとアクセスできない環境の場合は never_direct を指定する必要があります。

また、目的のサーバがローカルアドレスの場合、上流プロキシを経由しないで直接目的のサーバにアクセスしなければいけない場合もあります。そのような場合は、 acl dst で上流プロキシを経由しないサーバを定義し、 never_direct allow all よりも前に always_direct allow を指定する必要があります。

posted by 熊猫さくら at 20:27| Comment(0) | TrackBack(0) | Linux

2006年09月26日

FC6 でカーネル rpm を作成する際の注意点

Fedora Core 6 で kernel-2.6.18-1.2693.fc6.src.rpm から rpmbuild でバイナリパッケージを作ろうとした時に起こりそうなトラブルへの対処法です。

通常は、

rpmbuild -bb --target i586 /usr/src/redhat/SPECS/kernel-2.6.spec

と実行するだけでカーネル rpm を作成することができます。
しかし、 http://kumaneko-sakura.sblo.jp/article/696897.html で述べたように、デフォルトの .config ファイルでは CONFIG_DEBUG_INFO というオプションが有効になっているため、大量のディスク領域(約 2.5 GB?)が必要となります。

そこで、 /usr/src/redhat/SPECS/kernel-2.6.spec を開き、以下のように CONFIG_DEBUG_INFO= で始まる行を # CONFIG_DEBUG_INFO is not set に変更してやるための行を挿入することで、ディスク領域を節約することができます。

# now run oldconfig over all the config files
for i in *.config
do
  mv $i .config
  Arch=`head -1 .config | cut -b 3-`
  sed -i "s/CONFIG_DEBUG_INFO=.*/# CONFIG_DEBUG_INFO is not set/" .config
  make ARCH=$Arch nonint_oldconfig > /dev/null
  echo "# $Arch" > configs/$i
  cat .config >> configs/$i
done

しかし、 Fedora Core 6 ではこれだけではエラーになってしまいます。
FC6 では、以下のように %define _enable_debug_packages 0 という行も追加してやる必要があるようです。

%ifarch %nobuildarches
%define buildup 0
%define buildsmp 0
%define buildpae 0
%define buildxen 0
%define buildkdump 0
%define _enable_debug_packages 0
%endif

%define _enable_debug_packages 0

#
# Three sets of minimum package version requirements in the form of Conflicts:
# to versions below the minimum
#
posted by 熊猫さくら at 21:36| Comment(0) | TrackBack(0) | Linux

2006年09月18日

接続元ポート制限によるSSHサーバの保護について

別にSSHに限った話ではないのですが、多くのサーバはクライアントの使用するポート番号をチェックしません。
クライアントは未使用の非特権ポート(1024以上のポート)を見つけだしてそのポートを使用してサーバに接続するためです。
そのため、クライアントが使用するポート番号を制限することで、サーバが受け付けるべきポート番号を制限することも可能になり、ある程度サーバを攻撃対象になりにくくすることができます。

具体的には、クライアント側で

wget -O proxy.c http://lists.sourceforge.jp/mailman/archives/tomoyo-users/attachments/20060918/2b39ee3a/proxy.obj
gcc -Wall -O3 -o path_to_output proxy.c

でコンパイルします。 path_to_output は実行可能ファイルの出力先です。

次に、

ProxyCommand path_to_output %h %p min_port max_port

という内容のコンフィグファイルを作成し、適当な名前をつけて(例: useproxy )保存します。
min_port と max_port はそれぞれサーバが受け付けるクライアントの最小のポート番号と最大のポート番号です。

接続するときには、

ssh -F useproxy remote_host

のように -F オプションを指定してコンフィグファイルを指定します。
remote_host は接続先のサーバです。

デフォルトでこの設定を使いたい場合は ~/.ssh/config または /etc/ssh/ssh_config に記述しておきます。

min_port=1 max_port=10 としてクライアント側を設定した場合、サーバ側では

iptables -I INPUT 1 -p tcp --dport 22 --sport 11:65535 -j DROP

のようにファイアウォールを設定してサーバが受け付けるべきポート番号を制限することができます。
何も知らない攻撃者が 1024 以降のポート番号を利用して接続を試みても、ポートスキャンの時点で門前払いされるようになるわけです。

認証失敗ログと iptables を連動させて接続元 IP アドレスによる制限を行うSSHブルートフォース対策は有名ですが、 ちょっと工夫すれば、接続元ポート番号による対策も可能になります。

SSH クライアントが接続時に使用するローカルポートの範囲を制限する機能を備えていれば簡単なんだけどなぁ・・・。

posted by 熊猫さくら at 12:12| Comment(0) | TrackBack(0) | Linux

2006年09月16日

起動時に少しでも早くコンソールログインする方法について

通常、システム起動時には /etc/rc.d/rc による処理が完了してからコンソールログイン用のプロンプトが表示されます。
デフォルトの /etc/inittab の内容は以下のような内容になっているでしょう。

# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit

l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6

(中略)

# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6

しかし、ネットワークケーブルが繋がっていなかったり設定が不適切だったことが原因で、 /etc/rc.d/rc が数分間停止してしまう場合があります。
sshd が起動後であれば ssh でログインしてレスキューすることができますが、それ以前の段階で停止してしまうことが多く、不便です。
そこで、以下のように tty2 〜 tty6 用の /sbin/mingetty の行を /etc/rc.d/rc より前に移動させます。

# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit

2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6

l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6

(中略)

# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1

こうしておくと、 /etc/rc.d/rc.sysinit が終了して /etc/rc.d/rc が開始された時点からコンソールログインできるようになり、レスキュー時に威力を発揮するでしょう。
ログインするウィンドウの切り替えは Alt + F2 〜 Alt + F6 でできます。

posted by 熊猫さくら at 10:07| Comment(1) | TrackBack(0) | Linux

2006年09月13日

仮想ディスクファイルの圧縮時に圧縮率を高めるためのお掃除について

http://kumaneko-sakura.sblo.jp/article/475732.html の続きです。
ちゃんとしたプログラムにしてみたのでソースを載せておきます。

#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int fd;
    static char buffer[4096];
    memset(buffer, 0, sizeof(buffer));
    snprintf(buffer, sizeof(buffer) - 1, "%s/XXXXXX", argc > 1 ? argv[1] : "");
    if ((fd = mkstemp(buffer)) != EOF) {
        unlink(buffer);
        memset(buffer, 255, sizeof(buffer));
        while (write(fd, buffer, sizeof(buffer)) > 0);
        sync();
        close(fd);
    }
    return 0;
}

このソースを wiper.c という名前で保存し、 gcc -Wall -O3 -o wiper wiper.c のようにコンパイルします。その後、ランレベル1に移行して ./wiper を実行するとお掃除できます。
/ 以外にもハードディスク用のパーティションがマウントされている場合には、コマンドラインオプションでマウントポイントを指定して実行ください。例えば / と /boot 用のパーティションがある場合は ./wiper / と ./wiper /boot のように2回実行してください。

posted by 熊猫さくら at 21:58| Comment(0) | TrackBack(0) | Linux

2006年08月15日

OpenSUSE で Yast が動作しなくなるエラーについて

無事にソフトウェアのアップデートができるようになったと思ったら、今度は Yast が動作しないというトラブルに遭遇しました。 GUI 版ではアイコンをクリックしても新しいウィンドウが開かず、 CUI 版も以下のようなエラーメッセージが表示されます。

tomoyo:/root # yast
warning: the ncurses frontend is installed but does not work
You need to install yast2-ncurses to use the YaST2 text mode interface

いろいろ試した結果、 libzypp を再インストールする(強制的に古いバージョンに戻す)ことで動作するようになりました。

rpm -e --nodeps libzypp
rpm -ivh /media/SU1010_001/suse/i586/libzypp-0.0.8-154.i586.rpm

libzypp ってバージョンアップしてはいけないのかなぁ?まさかね?(^x^;

posted by 熊猫さくら at 20:03| Comment(0) | TrackBack(0) | Linux

OpenSUSE でソフトウェアアップデートを有効にするためのプロキシの設定について

Yast の設定でプロキシの設定をすることができますが、不思議なことに環境変数にはプロキシ認証部分が反映されないようです。
私の環境では http_proxy 環境変数の値は「http://プロキシ認証で使用するユーザ名:プロキシ認証で使用するパスワード@プロキシサーバのアドレス:プロキシサーバのポート」という形式で設定されていなければいけないのですが、何故か環境変数は「http://プロキシサーバのアドレス:プロキシサーバのポート」となってしまいます。

手動で環境変数を設定し直してアップデートの有無のチェックをしていたのですが、いつまで経っても1個もアップデートが無いという状態が続き、不思議に思っていました。いろいろ探してみた結果、ソフトウェアのアップデートを行うためには別途 rug コマンドを使ってプロキシの設定をする必要があるようです。

以下のように設定してください。

rug set proxy-url http://プロキシサーバのアドレス:プロキシサーバのポート
rug set proxy-username プロキシ認証で使用するユーザ名
rug set proxy-password プロキシ認証で使用するパスワード

rug get で現在の設定値を表示することができます。

しかし、いざダウンロードする段階で、ダウンロードをするプログラムが rug で設定した値ではなく http_proxy 環境変数を参照してしまったため、うまくダウンロードできませんでした。結局、 squid を用意して cache_peer 項目に「login=プロキシ認証で使用するユーザ名:プロキシ認証で使用するパスワード」というオプションを指定することで上位プロキシへリクエストを転送するときに挿入してもらうことにしました。(笑)

posted by 熊猫さくら at 20:00| Comment(0) | TrackBack(0) | Linux

2006年07月11日

SuSE カーネルのコンパイル方法について

openSuSE 10.1 のカーネルをコンパイルする際にはいくつか注意点があります。
ここで説明しているのは TOMOYO Linux カーネルをコンパイルする際に試行錯誤して見つけた手順です。正式なコンパイル手順については私は知りません。(^^;

カーネルをコンパイルしてインストールする場合は以下のようにします。
まず、カーネルソースの rpm をインストールします。

rpm -ivh kernel-source-2.6.16.13-4.i586.rpm

これにより、 /usr/src/linux-2.6.16.13-4 へのシンボリックリンクである /usr/src/linux と /usr/src/linux-2.6.16.13-4-obj へのシンボリックリンクである /usr/src/linux-obj が作成されます。
あとは、 kernel-default の場合、 /usr/src/linux-obj/i386/default/ ディレクトリへ移動して通常通りコンパイルします。

cd /usr/src/linux-obj/i386/default/
make -s menuconfig
make -s
make -s modules modules_install install

しかし、カーネルのバイナリ rpm を作成する場合は上記手順とは異なります。
まず、カーネルソースのソース rpm をインストールします。

rpm -ivh kernel-source-2.6.16.13-4.src.rpm

これにより、 /usr/src/packages/SOURCES/ ディレクトリにいくつかの .spec ファイルが作成されます。
そして、 kernel-default の場合、以下のようにコンパイルします。他のディストリビューションのように /usr/src/packages/SPECS/kernel*.spec を使うのではないことに注意してください。

rpmbuild -bb /usr/src/packages/SOURCES/kernel-default.spec

ディスク領域とコンパイル時間を節約するために私は kernel-default.spec を以下のように修正して使っています。

----- Start of patch -----
diff -u kernel-default.spec.org kernel-default.spec
--- kernel-default.spec.org 2006-05-03 18:31:20.000000000 +0900
+++ kernel-default.spec   2006-07-13 22:35:32.000000000 +0900
@@ -123,7 +123,7 @@
 # Will modules not listed in supported.conf abort the kernel build (0/1)?
 %define supported_modules_check 0
 # Are we building with debug symbols enabled?
-%define with_debug %(set -- " %optflags "; [ "$1" = "${1/ -g }" ]; echo $? )
+%define with_debug 0
 %define tolerate_unknown_new_config_options 0
 # kABI change tolerance (default in maintenance should be 4, 8 or 15;
 # see scripts/kabi-checks)
----- End of patch -----

また、 /usr/lib/rpm/find-requires.ksyms の実行中に "/usr/lib/rpm/find-requires.ksyms: line 12: /usr/bin/nm: Argument list too long" というエラーが出ると思われます。このエラーは以下のように修正することで回避できます。

----- Start of patch -----
# diff -u find-requires.ksyms.org find-requires.ksyms
--- find-requires.ksyms.org     2006-04-23 09:28:28.000000000 +0900
+++ find-requires.ksyms 2006-06-12 19:05:19.000000000 +0900
@@ -9,7 +9,7 @@
 esac

 all_provides() {
-    nm "$@" \
+    for module in "$@"; do nm -- $module; done \
     | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):\1\t\2:p' \
     | sort -k2 -u
 }
----- End of patch -----

ちなみに、 rpm パッケージを作成するために以下のようにするのはNGです。

rpm -ivh kernel-source-2.6.16.18-3.i586.rpm
cd /usr/src/linux/
cp -a /usr/src/linux-obj/i386/default/.* .
make -s rpm-pkg

この場合、以下のようなエラーメッセージが表示されます。

Finding Supplements: /usr/lib/rpm/find-supplements kernel
error: line 48: Dependency tokens must begin with alpha-numeric, '_' or '/':

error: Failed to find Supplements:

また、作成されたパッケージも rpm -ivh でインストールしようとすると "ksym(...) = ... is needed by kernel-..." というエラーが表示され、 --nodeps オプションを追加しないとインストールできないものになります。ただし、この問題は CONFIG_MODVERSIONS を使わない設定(# CONFIG_MODVERSIONS is not set)にすれば回避できるようです。

posted by 熊猫さくら at 20:14| Comment(0) | TrackBack(0) | Linux

2006年06月13日

http_proxy にパスワードを指定する場合の注意点(続)

http://kumaneko-sakura.sblo.jp/article/517004.html で DNS パケットによるパスワード誤流出の可能性について示しましたが、実際に環境を作って試してみました。

/etc/resolv.conf に自分自身を指定します。

[root@tomoyo ~]# cat /etc/resolv.conf
nameserver 127.0.0.1

即席のパケットダンプを行うプログラムを用意します。

[root@tomoyo ~]# cat dnsdump.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char *argv[]) {
  struct sockaddr_in addr;
  int fd = socket(AF_INET, SOCK_DGRAM, 0);
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
  addr.sin_port = htons(53);
  if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == 0) {
    int i, len;
    int size = sizeof(addr);
    static char buf[65536];
    while ((len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) &addr, &size)) != EOF) {
      for (i = 0; i < len; i++) {
        if (buf[i] >= 32 && buf[i] <= 126) putchar(buf[i]);
        else putchar('=');
      }
      putchar('\n');
    }
  }
  return 0;
}

コンパイルして実行します。

[root@tomoyo ~]# gcc -Wall -O3 dnsdump.c
[root@tomoyo ~]# ./a.out

別の画面で、以下のコマンドを実行します。

[root@tomoyo ~]# export http_proxy="http://USER:@PASS@WORD@127.0.0.1:8080"
[root@tomoyo ~]# wget http://localhost/
--16:33:02--  http://localhost/
           => `index.html'
Resolving pass@word@127.0.0.1... failed: Host not found.
[root@tomoyo ~]# yum update
Gathering header information file(s) from server(s)
Server: Red Hat Linux 9 (i386)
retrygrab() failed for:
  http://riksun.riken.go.jp/pub/Linux/fedoralegacy/redhat/9/os/i386/headers/header.info
  Executing failover method
retrygrab() failed for:
  http://download.fedoralegacy.org/redhat/9/os/i386/headers/header.info
  Executing failover method
failover: out of servers to try
Error getting file http://riksun.riken.go.jp/pub/Linux/fedoralegacy/redhat/9/os/i386/headers/header.info
[Errno 7] HTTP Error (CannotSendRequest):

./a.out を実行中の画面には、以下のような内容が表示されるはずです。

=============pass@word@127=0=0=1=====
=============pass@word@127=0=0=1=====
=============pass@word@127=0=0=1=====
=============pass@word@127=0=0=1=====
=u===========PASS@WORD@127=0=0=1=====
=u===========PASS@WORD@127=0=0=1=====
=v===========PASS@WORD@127=0=0=1=====
=v===========PASS@WORD@127=0=0=1=====
=w===========PASS@WORD@127=0=0=1=====
=w===========PASS@WORD@127=0=0=1=====
=x===========PASS@WORD@127=0=0=1=====
=x===========PASS@WORD@127=0=0=1=====

ちゃんとパスワードが流出していることを確認できました。

この原因は、 http_proxy の内容を最初に出現した @ の位置で分割してしまうためです。 @ が複数回出現したらエラーにしてくれると嬉しいんですがね。しかし、 RFC1738 によると、ユーザ名やパスワードの部分に @ を使ってはいけないということになっているので、アプリケーションの責任ではなく、ユーザの責任ということになるのでしょう。

話は違いますが、ユーザ名やパスワードをホスト名のように見せかけるといった攻撃手法もあるんですね。 http://itpro.nikkeibp.co.jp/free/ITPro/OPINION/20040306/141018/ 「URL ユーザ名 偽装」で検索するといろいろ出てきました。

posted by 熊猫さくら at 20:15| Comment(0) | TrackBack(0) | Linux

2006年05月18日

カーネルモジュールを小さくするためのコツについて

カーネル 2.6 には、 CONFIG_DEBUG_INFO という名前のコンパイルオプションが存在します。このオプションが有効である場合、コンパイルされたコードのサイズが約8倍〜10倍の大きさになります。
このオプションが有効になっている場合、(カーネルのコンフィグにもよりますが) /usr/src/ ディレクトリで約1GB、 /lib/modules/ ディレクトリで約300MBの余分なディスク領域を消費します。いくつかのディストリビューションではデフォルトで有効になっています。
ディスク領域を節約したい場合、以下のオプションが選択されていないことを確認してください。

Kernel hacking --->[ ]  Compile the kernel with debug info

VMware のようにディスク領域が貴重な場合は無効にすることを推奨します。私の場合、このオプションに気がつくまでは仮想ディスクを10GB割り当てていましたが、このオプションを無効にすることで4GBでやりくりできるようになりました。

posted by 熊猫さくら at 21:22| Comment(0) | TrackBack(0) | Linux

2006年03月31日

http_proxy にパスワードを指定する場合の注意点

認証が必要なプロキシ環境( http_proxy や ftp_proxy で「 http://プロキシユーザID:プロキシパスワード@プロキシホスト:プロキシポート」のような指定を行っている環境)で使用する場合には、以下の点に注意してください。

1つ目は、コマンドラインヒストリが有効になっているシェルから入力しないことです。私は、ヒストリが有効になっている bash から入力せずに、ヒストリが無効になっている tcsh を起動してから入力するようにしています。尤も、他のプロセスの環境変数(/proc/<PID>/environ)へのアクセスが可能であればどのみち盗まれてしまうわけですが。

2つ目は、パスワードに @ を使ってはいけないということです。これは、 http_proxy に @ が含まれている場合、最初の @ 以前を「プロキシユーザID:プロキシパスワード」、最初の @ 以降を「プロキシホスト:プロキシポート」として解釈するため、 「プロキシパスワード」に @ が含まれていると、「 @ 以降の部分」がプロキシホストのホスト名だと解釈されて、DNSの問い合わせパケット経由でプロキシサーバ以外のサーバにプロキシパスワードの一部を教えてしまうことになります。
これに気が付くまでは、どうしてホスト名が解決できないのか悩みました。そして、 http_proxy にパスワードを指定できるようにするために、わざわざパスワードを変更しました。もしも、「プロキシユーザID」に @ が含まれていたら「プロキシパスワード」全体をDNSサーバに教えてしまうことになるのでしょうね。怖くて試していませんけど。

posted by 熊猫さくら at 20:09| Comment(0) | TrackBack(0) | Linux

2006年03月23日

yum の罠

yum はコマンド1つでパッケージを最新版にアップデートしてくれる便利なプログラムですが、気をつけなければいけない点が2つあります。

1つは、設定ファイルに最新版を置いてあるサーバを指定しておくことです。全てのサーバが永遠に最新版を置き続けてくれる訳ではないため、時々確認してやらないと、最新版が存在しているのに当該サーバに置かれてないからダウンロードされないという状況が発生します。

もう1つは、キャッシュされたメタデータを時々削除することです。「yum update」を実行しても何もダウンロードされず、「最近、パッケージの更新が全然無いようだけどどうしたのかな?」と思ったら、「yum clean metadata」または「yum clean all」を実行してみてください。
その後、再度「yum update」を実行すると・・・「あら不思議。 yum clean metadata を実行前に yum update したときには表示されなかったパッケージが次々とダウンロードされてきた。」なんてことがあります。何かの拍子に、 yum が管理するメタデータが最新の情報を反映しなくなってしまうようです。

posted by 熊猫さくら at 21:49| Comment(0) | TrackBack(1) | Linux

2006年03月20日

簡単に作れる find もどき

Linux には ftw という関数があります。これは、 find コマンドのように指定されたディレクトリ以下をスキャンする関数です。以下、 RedHat Linux 9 で find もどきの関数を作る方法を紹介します。

プログラムの先頭で、ファイルサイズを64ビットで扱えるように以下の3行を記述します。これを指定しないと、32ビットでは扱えないファイルに遭遇した場合に ftw がエラーになってしまいます。

#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE

次に、以下の内容を記述します。(これらの内容は、 #include <ftw.h> で取り込まれるはずなのですが、何故かうまくいかないので直接記述します。)

#include <sys/types.h>
#include <sys/stat.h>
#define FTW_PHYS 1
struct FTW;
int nftw64(const char *dir, int (*fn)(const char *file, const struct stat64 *sb, int flag, struct FTW *s), int nopenfd, int flags);

コールバック関数 fn は、以下のような内容です。

#include <stdio.h>
int ftw_func(const char *file, const struct stat64 *sb, int flag, struct FTW *s) {
    printf("%s\n", file); // ここに処理内容を記述します。
    return 0;
}

呼び出し方は以下のようにします。

if (nftw64("/", ftw_func, 1000, FTW_PHYS)) {
    fprintf(stderr, "nftw64() returned %d\n", errno);
    exit(1);
}

これだけで、 find / 相当の機能が実現できます。詳細は man ftw を参照してください。

posted by 熊猫さくら at 22:04| Comment(0) | TrackBack(0) | Linux