仙石浩明の日記

2007年1月9日

La Fonera 用の ipkg feed を始めました hatena_b

ネットワーク経由で La Fonera にパッケージをインストール

La Fonera (FON ソーシャル ルータ) のベースとなっている OpenWrt は、 パッケージ管理システムとして ipkg を利用している。 La Fonera 用の ipkg feed を 作ってみた。 この feed を使うには、 以下のように /etc/ipkg.conf に 「src gcd http://www.gcd.org/fonera」 を追加し、 「ipkg update」 を実行する。

root@OpenWrt:/# echo "src gcd http://www.gcd.org/fonera" >> /etc/ipkg.conf
root@OpenWrt:/# ipkg update
Downloading http://www.gcd.org/fonera/Packages
Updated list of available packages in /usr/lib/ipkg/lists/gcd
Done.

すると、feed のリスト (パッケージ名の一覧) が /usr/lib/ipkg/lists/gcd に保存される。 あとは、「ipkg install パッケージ名」などと実行するだけで、 パッケージをネットワーク経由で La Fonera にインストールできる。

例えば stone をインストールするには、 次のように「ipkg install stone」と実行するだけでよい。

root@OpenWrt:~# ipkg install stone
Installing stone (2.3c-2.2.4.12) to root...
Downloading http://www.gcd.org/fonera/stone_2.3c-2.2.4.12_mips.ipk
Installing libopenssl (0.9.8d-1) to root...
Downloading http://www.gcd.org/fonera/libopenssl_0.9.8d-1_mips.ipk
Installing zlib (1.2.3-3) to root...
Downloading http://www.gcd.org/fonera/zlib_1.2.3-3_mips.ipk
Installing libpthread (0.9.28-8) to root...
Downloading http://www.gcd.org/fonera/libpthread_0.9.28-8_mips.ipk
Configuring libopenssl
Configuring libpthread
Configuring stone
Configuring zlib
Done.

stone の実行に必要な、libopenssl, zlib, libpthread パッケージの インストールも自動的に行なわれている。 このようにパッケージの依存関係も管理してくれるので便利なのであるが、 残念ながら現行の La Fonera 上の ipkg にはバグがある。 インストールしたパッケージをアンインストールしようとして、

ipkg remove stone

などと実行してはいけない。 /usr/bin/stone だけでなく、 /usr/bin ディレクトリまでもが削除されてしまう。 なぜこんなバグがあるかというと、 mini_fo の rmdir の実装にバグがあるからだ。 すなわち、空でないディレクトリに対して rmdir を行なっても、 ディレクトリが削除されてしまうことがある。 試しに、あまり重要そうでないディレクトリに対して rmdir してみる:

root@OpenWrt:/www/images# ls -a table
.                 bottom-right.gif  logo.gif          top-left.gif
..                bottom.gif        right.gif         top-right.gif
bottom-left.gif   left.gif          sidebar.gif       top.gif
root@OpenWrt:/www/images# rmdir table
root@OpenWrt:/www/images# ls table
ls: table: No such file or directory

La Fonera のファイルシステムは mini_fo (mini fan-out) を使っている。 つまり squashfs を read only でマウントした「上」に、 jffs を重ねてマウントしている。 前述の例で言えば、 /www/images/table ディレクトリは squashfs 上にあり、 jffs 上には /www/images/table ディレクトリは存在しない。 「rmdir table」などファイルシステムに対する変更は、 「上」に重ねられた jffs に対して行なわれるが、 ディレクトリが空か否かの判断まで、 「上」のファイルシステムに対してのみ行なっているのだろう、 jffs 上では /www/images/table ディレクトリの中にはファイルが存在しない (ディレクトリが存在しないので当然だが) ため、 rmdir がエラーにならずにディレクトリの削除が行なわれてしまう。

La Fonera の ipkg (busybox に含まれている) のソース ipkg_remove.c を 確認してみると、

    for (iter = installed_dirs.head; iter; iter = iter->next) {
            file_name = iter->data;
 
            if (rmdir(file_name) == 0) {
                 ipkg_message(conf, IPKG_INFO, "  deleting %s\n", file_name);
                 removed_a_dir = 1;
                 str_list_remove(&installed_dirs, &iter);
            }
    }

などとなっている。 つまりディレクトリが空かどうかは判断せず、 いきなり rmdir してみて成功すればヨシとしている。 このため、「ipkg remove パッケージ名」を実行すると、 空でないディレクトリまで削除してしまうのだろう。

空でないディレクトリに対して rmdir を実行したら ENOTEMPTY を返すのがスジであるので、 mini_fo 側を修正すべきだとは思うのだが、 とりあえず sh スクリプト版の ipkg を拾ってきて、 rmdir するまえに中身の確認をするように変更し、 /usr/bin/ipkg を この修正済み sh スクリプトで置き換えてみた。

root@OpenWrt:~# wget http://www.gcd.org/fonera/ipkg-0.9-1.32.sh
Connecting to www.gcd.org[60.32.85.216]:80
ipkg-0.9-1.32.sh     100% |*****************************| 27925       00:00 ETA
root@OpenWrt:~# chmod 755 ipkg-0.9-1.32.sh
root@OpenWrt:~# mv ipkg-0.9-1.32.sh /usr/bin/ipkg

などと置き換えるとよいだろう。 これで安全にパッケージをアンインストールできるようになる。

root@OpenWrt:~# ipkg remove stone
ipkg_remove: Removing stone...
ipkg_remove: Warning: Not removing the following directories since they are not
empty:
 /usr /usr/bin
Done.

/usr および /usr/bin ディレクトリが空でなかったので削除できなかった旨が、 表示されている。

La Fonera の自動アップデートのまとめ

La Fonera の自動アップデートは、 cron から呼び出される /bin/thinclient プログラムによって行なわれている。 このアップデートは ipkg とは独立した形で行なわれているので、 ipkg でパッケージのインストールを行なう場合は、 この自動アップデートで何が行なわれているか把握しておく必要がある。 確認できたアップデートについてまとめてみた。

0.7.0 rev 2 -> 0.7.0 rev 3 (upgrade.fon)
修正: /usr/lib/webif/validate.awk
0.7.0 rev 3 -> 0.7.0 rev 4 (upgrade.fon)
[WiFi] 暗号方式のデフォルトを WPA+TKIP に変更
修正: /etc/init.d/rcS /sbin/ifup /www/cgi-bin/webif/*.sh
変更: /lib/modules/2.4.32/wlan.o /lib/modules/2.4.32/ath_ahb.o
追加: /etc/hotplug.d/iface/10-ppp_hack
0.7.0 rev 4 -> 0.7.1 rev 1 (upgrade.fon) 2006-11-21 0.7.1 rev 1
[Web interface] 多言語サポート
[Web interface] ポートフォワード機能
[NTP] ntpclient による時刻同期
修正: /bin/thinclient /etc/functions.sh /usr/lib/webif/*
変更: /usr/bin/webif-page
追加: /etc/config/ntpservers /etc/config/openports /etc/config/webif /etc/init.d/N45ntpclient /usr/lib/webif/lang /usr/sbin/adjtimex /usr/sbin/ntpclient /www/cgi-bin/webif/adv_pf.sh /www/cgi-bin/webif/language.sh
0.7.1 rev 1 -> 0.7.1 rev 2 (upgrade.fon) 2007-01-04 01:00 JST
[Web interface] 任意のコマンドを実行させられてしまう脆弱性を修正
[NTP] crontab に複数の ntpclient 呼び出しが登録されてしまうバグを修正
修正: /etc/init.d/N45ntpclient /usr/lib/webif/validate.awk /www/cgi-bin/webif/*.sh
変更: /usr/bin/haserl

特に重要なのが、0.7.1 rev 2 で行なわれた、 Web インタフェースにおける脆弱性の修正だろう。 POST した入力データのチェックが厳密になった。 La Fonera に ssh でログインする最も手軽な方法が、 この脆弱性を利用する方法だっただけに、 0.7.1 rev 2 にアップデートする際は注意が必要である。

Filed under: La Fonera — hiroaki_sengoku @ 06:51

1 Comment »

  1. どうも。初めてコメントさせていただきます。いつもstoneを有り難く使わせていただいております。(ウチでは支社とのfilemakerをSSLでラップするのに欠かせません)
    さて、Fonera用のipkg feedを有り難く使わせていただきました。厚かましい御願いで恐縮なのですが、仙石様が公開されているWake-On-Lan(wol.c)も一緒にFeedしていただけませんでしょうか。
    これができれば、自宅の計算機の電源をすべて落とす事ができ、細君に怒られずに済みます。(^^;

    Comment by kiro — 2007年3月22日 @ 17:35

RSS feed for comments on this post.

Leave a comment