カテゴリ: linux

昔、kernel watch で真のO_SYNCサポートについての記事(※下記参照)を書いたことがあるんだけど、RHELではちょっと事情が違うことがわかった。

http://www.atmarkit.co.jp/flinux/rensai/watch2009/watch12b.html

時系列でいうと、まずkernel 2.6.33でO_SYNCサポートが入り(上記記事)、glibc 2.12 でそれに対応するためのヘッダファイル修正が入ったんだけど、RHEL6は kernel 2.6.32 + glibc 2.12 なんだな。

だからRHEL6でコンパイルしたアプリをRHEL6で実行するケース
→ O_SYNCはの実体は (__O_SYNC|O_DSYNC) なんだけど、カーネルのほうに、_O_SYNCの定義がないので、その部分は無視されて、O_DSYNCとして動作

RHEL6でコンパイルしたアプリをRHEL7で実行するケース
→ カーネルに_O_SYNCの実体があるので、O_SYNCが正しくO_SYNCとして動く

つまり、OSをバージョンアップするとアプリの挙動が変わってしまう。コミュニティ開発者がとんでもなく苦労して後方互換性を維持してもディストリのうっかりで台無しになることもあるよという例でした。

まあ、O_SYNCを使ってるのに、O_DSYNCセマンティクスを仮定してるアプリがいたら、そいつがアホという意見には同意する。同意するが、後方互換性とはそういうものじゃないんだよ。バグ互換も含めて考えるのが互換性。

今日知ったこと。
gtagsのupdate は global --single-update で1ファイルだけのアップデートが出来る。
よって、



みたいなスクリプトで、gitのコミットIDから変更ファイルだけアップデートが出来る。わたしはこれをcherry-pickの処理に仕込んだ

いままで、rpmbuildするときに

mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}


して、

echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros



とかやってたんだけど、それはもう古いらしい。

% yum install rpmdevtools
% rpmdev-setuptree



すると、上記の両方をやってくれるのに加えて .rpmmacrosに並列処理設定を追加してくれる。
こんな感じ

%_topdir %(echo $HOME)/rpmbuild

%_smp_mflags %( \
[ -z "$RPM_BUILD_NCPUS" ] \\\
&& RPM_BUILD_NCPUS="`/usr/bin/nproc 2>/dev/null || \\\
/usr/bin/getconf _NPROCESSORS_ONLN`"; \\\
if [ "$RPM_BUILD_NCPUS" -gt 16 ]; then \\\
echo "-j16"; \\\
elif [ "$RPM_BUILD_NCPUS" -gt 3 ]; then \\\
echo "-j$RPM_BUILD_NCPUS"; \\\
else \\\
echo "-j3"; \\\
fi )

%__arch_install_post \
[ "%{buildarch}" = "noarch" ] || QA_CHECK_RPATHS=1 ; \
case "${QA_CHECK_RPATHS:-}" in [1yY]*) /usr/lib/rpm/check-rpaths ;; esac \
/usr/lib/rpm/check-buildroot



rpmbuildがかなり高速化されるし、間違いも起きにくいので、手で .rpmmacrosを書く必然性は
まったくなくなったと言っていい。

知らんかったなあ

RHEL7でしばらくキーを操作しないでおくと、以下の様なカーテンが降りてくるけど、非常に鬱陶しい。

gnome3-curtain

今回はこれのdisableの仕方。

% sudo yum install -y gnome-shell-browser-plugin



で、firefoxにgnome-shell extensionを入れる。これで、ブラウザで、https://extensions.gnome.org を
閲覧すると、インストールしまっかと聞いてくるようになる。

https://extensions.gnome.org/extension/730/curtains-up/

に curtainを disable するプラグインがあるので、これをインストール。

なお、パスワード入力はGnome標準の機能でdisableできるが、これがとんでもなく分かりにくいので
ついでに紹介。

メニューバー右端の、自分の名前をクリック、Settingsを選択
setting1.png

Privacyを選択
010acd2d.png


Screen LockをOFFに変更
d6fa38f7.png


昔ながらのようにスクリーンセーバーというアイコンがコントロールパネルにあるかと思い込んでるとハマる。

もう何百回もやってるはずなのに定期的にハマるのでメモ

kernelのspec ファイル書き換えてオレオレカーネルを作るには以下の三箇所を変更する

まず、rpm名を書き換えるために6行目ぐらいのbuildidのところ、コメントアウトされてるのを元に戻す

変更元)

# % define buildid .local



変更後)

%define buildid .mytest



ここで罠なのは % と define の後に、スペースを入れるのは許されていないのだが、なぜか
変更元はスペースが入っているのでまんまと騙されることである。
あと、名前は "." で初めておかないと、いろいろと後悔する。

kernel-3.10.0-1.el7.mytest.src.rpm

みたいなファイル名になるんだが、ここで "." がないと、前の el7 とくっついてしまう。

次に

# empty final patch to facilitate testing of kernel patches
Patch999999: linux-kernel-test.patch



となっているところに、適用するパッチを足す

変更後)

# empty final patch to facilitate testing of kernel patches
Patch999999: linux-kernel-test.patch

Patch10001: hoge1.patch



とかみたいにする。番号は適当でいいが、ユニークな番号にすること。
なお、ここでファイル名を書くときに余分なスペースは絶対に入れてはいけない。

パッチ適用をするApplyPatchという関数の中で


ApplyPatch()
{
(略)
if ! grep -E "^Patch[0-9]+: $patch\$" %{_specdir}/${RPM_PACKAGE_NAME%%%%%{?variant}}.spec ; then



というクソコードが有るため、スペースが1つでも余分にあるとパッチ適用に失敗する。
わたしは、dired から矩形選択でファイル名持ってきて、これでハマったよ。

さて、rpm specfileはクソフォーマットなので、これで話が終わりじゃなくて、別の場所にもう一度
パッチ一覧を列挙しないといけない。

変更元)

ApplyOptionalPatch linux-kernel-test.patch



変更先)

ApplyOptionalPatch linux-kernel-test.patch

ApplyPatch hoge1.patch



のように、ApplyOptionalPatchがあるあたりに、ApplyPatchを書いていく。ここで間違ってもApplyOptionalPatchを
使ってはいけない。
ApplyOptionalPatchはパッチがなきゃあスキップする関数なので、間違った時に気づくのが遅れてしまう。


で、こんなん憶えていられるはずなのでスクリプト書いた

rpmpatch kernel.spec --localname .mytest ../SOURCES/00*.patch



のように名前をファイル名を引数に取ってパッチしてくれる。

以下に置いとく。
https://gist.github.com/kosaki/de41d67a899b0d839599

そういえば、Red Hat Enterprise Linux Developer Suite 持ってたら RHELのSubscriptionついてくるんだったよなあと
思い出してRHEL7をインスコ。これは年間たったの$99なのでお得だと思う。

普通に入ったけど、カットアンドペーストをサポートするための guest addition CD が
インストール不可

このへんに有志パッチがあるので、それを使った。
RHEL 7 VirtualBox Guest Additions Patched http://matthewcasperson.blogspot.com/2014/06/rhel-7-virtualbox-guest-additions.html

man pages 3.69 がリリースされたようです。
毎回関係者に連絡くれるMichaelえらいなー

今回のハイライトは execveのEAGAINエラーについての追記。

http://man7.org/linux/man-pages/man2/execve.2.html

で、EAGAINで検索するといいと思う。これは何をいっているかというと、典型的には以下のセキュリティーホールに
対処するための修正が kernel 3.1 で入ったということ。

・Linuxにおいてユーザーごとのプロセス数制限はRLIMIT_NPROCで表現される
・UIDはsetuidと(SUIDされた実行ファイルへの)execveによって変更されうる
・権限分離のため 1)SUIIDされた実行ファイルをexec、 2)特権を必要とする処理が終わったらすぐさまsetuidにて権限放棄 というプログラムが広く使われている
・3.0以前はexecveはRLIMIT_NPROC未チェック、setuidではチェックしてた
・ところが、世の中にはsetuidの返り値をチェックしてないあほなプログラムがたくさんある。そういうプログラムがRLIMIT_NPROC踏むように誘導すると、権限放棄が失敗したまま移行のすべての処理がrootで走り続けてしまうので、攻撃の起点につかうことが出来た
・たとえば sendmail は以前はsetuidのチェックがなくてセキュリティーホールを出している
https://sites.google.com/site/fullycapable/Home/thesendmailcapabilitiesissue (ただしこれはRLIMIT_NPROCではなく、capabilityの考慮不足)
・そもそも論に戻ると、権限が上がる方向のexecveが未チェックで、権限を捨てる方向のsetuidがチェックあり(失敗しうる)というの論理的におかしい。(Unix的にはrootはすべてOKなのは正しいが、ここでいってるのはセキュリティ的な筋論)
・なので、setuidでのチェックを削除して、execveでのチェックを追加する変更を3.1で加えた

そのとき、そのパッチ作成にかかわったKOSAKIという人が man も変えろとBugzilla起票してたのが、最近関係者レビューが終わってやっとこさ反映されたということです。
https://bugzilla.kernel.org/show_bug.cgi?id=42704

ちなみに、この挙動はNetBSDとも一致してるので、世の中のOSSでは問題ないことが確認済みだったりします。

ChangeLogの全文はこちら。
http://man7.org/linux/man-pages/changelog.html#release_3.69


PS さいきんSYSV IPCのデフォルトを無制限に変えたんだけど(従来はリミットが小さすぎて実用になってなかった)、まだmanには反映されてないみたいだ

ところで、memstompのライセンスは結構ひどい

$ rpm -qi memstomp
Name : memstomp
Version : 0.1.4
Release : 11.el7
Architecture: x86_64
Install Date: Fri 14 Mar 2014 07:18:53 PM EDT
Group : Development/Debuggers
Size : 1157987
License : LGPLv3+ and GPLv2+
Signature : RSA/SHA256, Mon 03 Feb 2014 09:37:00 AM EST, Key ID 938a80caf21541eb
Source RPM : memstomp-0.1.4-11.el7.src.rpm
Build Date : Sun 26 Jan 2014 10:27:02 AM EST
Build Host : x86-017.build.eng.bos.redhat.com
Relocations : (not relocatable)
Packager : Red Hat, Inc.
Vendor : Red Hat, Inc.
URL : git://fedorapeople.org/home/fedora/wcohen/public_git/memstomp
Summary : Warns of memory argument overlaps to various functions
Description :
memstomp is a simple program that can be used to identify
places in code which trigger undefined behavior due to
overlapping memory arguments to certain library calls.



License : LGPLv3+ and GPLv2+

というのがよく分からなくてデュアルライセンスかなあと思っていたのだが、README
読むと

LICENSE:
LGPLv3+

Exception:

backtrace-symbols.c is GPLv2+. Which probably means that using
the --debug-info switch for memstomp might not be legally safe
for non-GPL-compatible applications. However, since that
module is independantly built into a seperate .so it should
still be safe using the profilers without this switch on such
software.



と書いてある。
ライセンスは著作権者の解釈が重要な意味を持つことが少なくないので、Author が LD_PREALOD だろうがライセンス的には non-GPL-compatible application では使えないかもーとか書いちゃうと、使っちゃダメな事で確定しちゃうだろ。そうしたいのならパッケージを別にして明確に注意喚起すべきで、誰も読まないような場所にインストールされたREADMEにこっそり書くんじゃない。

一番いいのはbinutilsコミュニティいって、明示的に許可をもらってライセンス変更の許可をもらってくることだが、次善の策は別のところからもってくることかなあ。Rubyのaddr2lineとか。

↑このページのトップヘ