サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
コーヒー沼
kernhack.hatenablog.com
たまにやる必要があったりするのでメモです。 まずは。。。 pagerを1に設定することで、出力内容が多い時に(catとかで)moreとlessみたいに1ページ毎にページ送り出来ます。これないと辛い。。 setコマンドで引数渡さなければ現在の設定が見れます。これで今の設定を確認。 ここで知りたいのはrootがどこかというとこです。このPCだと(hd1,gpt1)。 このrootは/bootではなくて/boo/efiです。 /dev/sda1 on /boot/efi type vfat (rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=winnt,errors=remount-ro) よって、ls (hd1,gpt1)/をするとこうなります。efiディレクトリとかがあります。 Linux上で見る
前書き 2018 Linux Storage, Filesystem, and Memory-Management Summit関連の記事でlwn.netに面白そうな記事が増えてる今日この頃ですヽ(=´▽`=)ノ 今週のpatch メモリを確保してデータを書き込んだあとはR/Oにするpmalloc() 前にlwn.netでも紹介されてたかも。24日の時点で[RFC PATCH v23 0/6] mm: security: write protection for dynamic dataのpatchが流れてました。メモリは専用のpoolを作って管理して、alloc時はそのpoolからメモリを取得します。このpoolはスラブアロケータみたいに特定のサイズ毎にチャンクを作るのではなくて、pmalloc()でサイズを指定して確保するようになっています。 一番メインであろうpmalloc()とかの
前書き 今週も細かいネタを拾っていきます。重要そうなpatchはLWN.netをチェックしましょう。lwnはSubscriberになると最新の記事がすぐに読めて快適ですΣ(゚∀゚ノ)ノキャー 今週のpatch cpuタイマーのバグフィックス LKML: Laura Abbott: [PATCH] posix-cpu-timers: Ensure set_process_cpu_timer is always evaluatedというpatchです。fedoraのbugzillaでBug 1568337 – kernel: prlimit64 with RLIMIT_CPU ignored]と報告されたものの修正ですね。バグの内容はsetrlimit(2)でRLIMIT_CPUを使ってcpu時間の上限をセットしてもプロセスが終了しないということでした。 vm_fault_t patchはmm
まえがき 週刊Railsウォッチというrailsを中心とした記事がとても良い感じで、これのカーネル版あったら嬉しなということで自分でやってみました(*´Д`) どれくらいのボリュームでとか、毎週ちゃんと書くのかは全く不明でございます。 我々にはWelcome to LWN.net [LWN.net]やLinux Hardware Reviews, Open-Source Benchmarks & Linux Performance - Phoronixがあるし、基本的にこれらを読めば事足りる気はしますが。まあ、小ネタを拾っていこう的な感じです。 読むpatchについてはマージされるかどうかは別として、気になったものとかを取り上げようと思います。 今週のpatch sl*bでコンストラクタ使う場合にスラブオブジェクトの取得時に__GFP_ZEROフラグ使わない [PATCH v2 2/2]
最近のgccはインラインアセンブラ内からcのgotoラベルに飛べる仕組みがあるのでそれのメモです。 ドキュメントはUsing the GNU Compiler Collection (GCC): Extended AsmとUsing the GNU Compiler Collection (GCC): Extended Asmです。たしかLKMLに送られてたpatchにもこれを使ったコードがあった気がします。 それはさておき、gotoを使う場合の書式は以下のようになっていて、asm gotoという形式です。 asm [volatile] goto ( AssemblerTemplate : : InputOperands : Clobbers : GotoLabels) ドキュメントには-ansiオプションを付けてコンパイルする場合はasmではなくてasmを使うようにと書かれています。また
xv6のページング周りをちょっと見てたので記録をφ(..)メモメモ 参照したドキュメントはbook-rev10.pdfです。 book-rev10.pdfのP21、 Figure 1-2にxv6のメモリレイアウトがあります。 仮想アドレスの0から0x80000000がユーザー空間で、0x80000000〜0xFFFFFFFFがカーネル空間ですね。カーネル空間のうち先頭の0x100000バイトはBIOSの領域となってます。 カーネルのアドレス空間はvm.cにあるkmap構造体で管理してます。 static struct kmap { void *virt; uint phys_start; uint phys_end; int perm; } kmap[] = { { (void*)KERNBASE, 0, EXTMEM, PTE_W}, // I/O space { (void*)KERN
Linuxのしくみの5章でページングの説明がありますね。なんとなく、この辺の挙動をエミュレートする感じのものでも作ってみようかなと思ったりしたので。 リポジトリはこちらです。 github.com ページングのコードを実際に書くなら自作OSを書くのが良いと思いますが、ページの割り当てくらいならユーザーランドのプログラムでもそれっぽい感じにはなるかなということで^^; 動かし方はこんな感じで、4MiBのメモリがあって、4プロセスが5回ずつページの割り当てを行った感じが下のコマンドです。 masami@saga:~/codes/how_paging_works (master=)$ ./pg -p 4 -l 5 -m 4 | jq . 出力はjson形式になるようにしたので、pipeでjqコマンドに渡せば綺麗に見れます。 { "physical memory": { "size": "4MiB
著者の武内さんより「[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識」を献本いただきました。ありがとうございますm( )m 武内さんはQiitaなどでもわかりやすいカーネルの解説記事を書かれているので、記事を読んだことが有る方も多いかと思います。そして、今回「試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識」というOS・ハードウェアのしくみを手を動かして学ぶコンセプトの本を書かれました。 gihyo.jp 本書の「実験と図解で学ぶOSとハードウェアの基礎知識」というコンセプトはOSの解説本にしては珍しいと思います。しかし、何かを学ぶ上で実際に手を動かしたほうが勉強になるということを考えるとこのコンセプトは良いですよね。 また、図解の部分も丁寧に解説されています。第5章の仮想記憶、ページングの図解などはここまで細く説明されている文
カーネルをgdbでリモートデバッグできるようにするかーとか思ってやってたわけです。 しかし、下記のような感じでちょっとハマってました。 ブレークポイントが効かなかったり vmlinuxとvmlinuzの組が合ってるのにシンボル名が出なかったり Cannot access memory at address 0xffffffff8124d730とかで落ちたり 原因はKASLRが有効だったため、実行時にアドレスがランダマイズされていたのが原因ですね\(^o^)/ 解決策はKASLRをoffにすれば良いだけです。そのためにカーネルの再ビルドは不要で、カーネルのコマンドラインでnokaslrを渡せばOKです。 そうすればこのようにいい感じに 以下はめも remote接続にシリアルコンソールを使う場合 qemuはこんな感じになる。 $ qemu-system-x86_64 -kernel vmlin
/proc/cpuinfoでcpuの機能を表示するflagsのところってどうやって名称設定してんだろ?と思ったので調べてみたメモです。調べたカーネルのバージョンはv4.14.12です。 ↓これですね /proc/cpuinfoのopen処理 これはfs/proc/cpuinfo.cにあるcpuinfo_open()が担当します。と言っても、実際の処理はseq_operations構造体のcpuinfo_opに関数がセットされていて、それらが実行されます。 extern const struct seq_operations cpuinfo_op; static int cpuinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &cpuinfo_op); } ここからはアーキテクチャ固有になります
Linux 4.14でプロセスをforkした時のPage Global Directoryの設定を見てみます。読むカーネルはv4.14.12です。 前にLinux x86_64のPaging:Page Global Directory辺りの扱いを見てみる - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモ書いてたけど、最新のカーネルで調べてみたので。 プロセス生成時のPage Global Directoryの設定の流れ Page Global Directory(pgd)の設定はpgd_alloc()で行います。fork()からの流れはこのような形。 _do_fork() -> copy_process() -> copy_mm() -> dup_mm() -> mm_init() -> mm_alloc_pgd() -> pgd_alloc() pgd_alloc() pgd_al
この記事はLinux Advent Calendar 2017の9日目の記事です。 なんとなくlib/を見ていたらonce.cなんてファイルを見つけて、一度だけ実行したいという時に使う関数を見つけたのでその機能についてのきじになります。 使い方 まず使い方をザクっと見てみましょう。使用するのはDO_ONCEマクロです。 実装はこんな感じです。 サンプルコード #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> #include <linux/kernel.h> #include <linux/debugfs.h> #include <asm/uaccess.h> #include <linux/err.h> #include <linux/once.h> MODULE_DESCRIPTION("once
この記事はLinux Advent Calendar 2017の22日目の記事です。 カーネルのコードを書いていてサイズを表示したい時にstring_get_size()を使うとお手軽に2進接頭辞(KiBとか)とSI接頭辞(KBとか)を使ったサイズの文字列を作ることができます。 関数のプロトタイプはこうです。 void string_get_size(u64 size, u64 blk_size, enum string_size_units units, char *buf, int len); sizeとblk_sizeは使い分けが有ります。バイト数を扱いたい場合はsizeにバイト数、blk_sizeには1を指定します。ブロックデバイスやページなどを扱う場合などはそのサイズをblk_sizeに指定して、それがいくつあるかをsizeで指定します。 たとえば、1024という数字を2進接頭辞
この記事はIT勉強会/コミュニティ運営 Advent Calendar 2017の3日目の記事です。2日目はikkouさんのIT勉強会/コミュニティ運営 Advent Calendar 2017 をやるよ、あるいは今からでも書いてくれる人を募集しているよ、という話でした。 Linuxカーネルもくもく会 開催場所 もくもく会の方針 ネットワーク 絶対のルール 募集人数 参加者の傾向 まとめ 今後 Linuxカーネルもくもく会 linmoku.connpass.com いうのを不定期に開催してます。去年までは大体月一ペースでてきてたんだけど、最近は不定期気味に(´・ω・`) 今のところ28回やりました。Linuxカーネルもくもく会とは別の番外編的なものも実はやっていて、自作エミュレータで学ぶx86アーキテクチャのもくもく会なんかもやったりしました。 linmoku.connpass.com 開
この記事はLinux Advent Calendar 2017の1日目の記事です。Linuxのスラブアロケーター仕組みを多少弄りながら学んでみます。 スラブアロケーターとはなんぞやというところはSlab allocation - Wikipediaを参照してください。スラブアロケーターはSolaris5.4で最初に実装されたようです。 Linuxカーネルプログラミングで動的にメモリを確保するのに使用するkmalloc()もスラブアロケーターを使用しています。 目次 Linuxのスラブアロケーター SLAB SLUB SLOB 各スラブアロケーターのまとめ 実装 スラブ用のページ 弄ってみる 最低限必要な準備 実装開始 データ構造 ロック 初期化 kmem_cache_create() スラブオブジェクトのアロケート スラブオブジェクトのfree 実験 ボトルネック この後 Linuxのスラ
pythonでなんとなく。 show memory usage in memcg. memoryサブシステムにtest1を作ってメモリの上限を100Mで設定。 root@saga:/sys/fs/cgroup/memory/test1# cat memory.limit_in_bytes 104857600 root@saga:/sys/fs/cgroup/memory/test1# cat memory.memsw.limit_in_bytes 104857600 root@saga:/sys/fs/cgroup/memory/test1# pid 4473はtest1に所属するbashのプロセス。このシェルから1MiBのmalloc()を繰り返すプロセスを実行する。 ツールはpid 4473を指定して実行 masami@saga:~/codes/memcgstat$ ./memcgst
Linuxのシステムコールのファジングツールとしてsyzkallerというのがあって、これはコードカバレッジを見つつ入力を変えていってくれるというファジングするツールです。 試してみたのでどんな感じなのかを簡単にめも。 まず、ツール自体はgolangで書かれているのでgoの実行環境が必要です。あとテスト対象のカーネル側でコードカバレッジを利用可能になっている必要があります。この辺はsyzkallerのドキュメントに書かれています。 ツールはビルドして行います。make一発で良いのですが、デフォルトだとstatic linkなバイナリを作ります。うちだと-lpthreadと-lcのところでそんなライブラリはないとか怒られてしまったので、動的リンクにしました。ホストとゲストのディストリビューションが同じならライブラリのABIの違いとかないですし、これで良いでしょう。 ファジングはVMを使って行
前も調べたことあった気がするけど忘れても良いようにメモを。 まずディレクトリを作成するのはdebugfs_create_dir()で1番目の引数はディレクトリ名、2番目はディレクトリを作りたい場所のdentryでNULLを渡せばdebugfsをマウントしている場所になる。例えばdebugfs_create_dir("foobar", NULL)を実行した時に/sys/kernel/debugがdebugfsのマウント先なら/sys/kernel/debug/foobarとなる。ディレクトリを作ったら読み書きしたい変数にアクセスするためのファイルを作成。この場合、方法は大雑把に2種類あって1つ目はdebugfs_create_file()を使う、もう1つはdebugfs_create_XXXのシリーズを使う(debugfs_create_u32とか)。前者はデータの読み書きをするためにfil
/proc/<pid>/ にファイルを作ってデータを読めると便利なときがあったりするのでめも。 今回はcgroup.cで処理を実装して、その関数をcgroup.hにて宣言。fs/proc/base.cでcgroupのほうに追加した関数を登録する形です。/proc/<pid> にあるファイルに対する関数はここで登録されてます。 差分はこのような感じです。 git masami@kerntest:~/linux-kernel (ktest *=)$ git diff --stat fs/proc/base.c | 2 ++ include/linux/cgroup.h | 2 ++ kernel/cgroup/cgroup.c | 7 +++++++ 3 files changed, 11 insertions(+) 最小限のコードはこのようになります。 masami@kerntest:~/l
カーネルは4.1.15。mem_cgroup_commit_charge()はchargeの処理で呼ばれる関数。 今回はここで使われる関数の詳細は調べないで、大まかな流れを把握するのが目標。 LXRで検索するとmm/filemap.cとかmm/swapfile.c、mm/memory.cなんかから呼ばれてます。 mem_cgroup_commit_charge()自体は40行ほどの関数。引数はcharge対象のpage構造体、所属するmemcgの構造体、最後のlrucareはpageがすでにLRUで管理されているかを示すbool値です。 5522 void mem_cgroup_commit_charge(struct page *page, struct mem_cgroup *memcg, 5523 bool lrucare) 5524 { 5525 unsigned int nr_p
誰得なめも。バージョンは4.1.15。 __initがついているのは以下の3関数。 mem_cgroup_init() enable_swap_account() mem_cgroup_swap_init() 当たり前だけど、__initがあるのでカーネル起動時の初期化で呼ばれる。 mem_cgroup_init()はこのような関数。 5774 static int __init mem_cgroup_init(void) 5775 { 5776 int cpu, node; 5777 5778 hotcpu_notifier(memcg_cpu_hotplug_callback, 0); 5779 5780 for_each_possible_cpu(cpu) 5781 INIT_WORK(&per_cpu_ptr(&memcg_stock, cpu)->work, 5782 drain
cgroupはv1とv2という2つの実装(と言っていいのか?)があってそれらはkernel/cgroup.cで一つのコードベースにまとまっているのでコード読んでで混乱するなーというところで、誰得なめもを。 特に、4.1とかのカーネルだとv2のコードはまだ正式版となってないけどマージはされていて、DEVELsane_behaviorというオプションを使うことでv2の機能が使えるようになってます(参考: Linux 3.16 から試せる cgroup の単一階層構造 (1) - TenForward)。今はv2がちゃんと入っているのでこのオプションは不要で、cgroupのマウント時にcgroup v2としてマウントするかどうかで切り分けできます。cgroup_mount()のis_v2がそれです。 2083 static struct dentry *cgroup_mount(struct f
pid numberからtask_structの取得のめも pid番号から直接task_structは取得できないので、pid構造体の取得 -> task_struct構造体の取得という流れになる。 pid名前空間を気しなくて良い場合は、find_get_pid()でpid構造体を取得し、pid_task()でtask_structを取得できる。pid名前空間が重要になる場合は、find_get_pid()ではなくてfind_ge_pid()を使ってpid構造体を取得する。 static struct task_struct *find_task_by_pid(int nr) { struct pid *pid = find_get_pid(nr); if (!pid) { pr_warn("couldn't find pid %d's task\n", nr); return NULL;
たぶん、この辺の会話から Linuxカーネルのコードネームって気にした事無いな— int $0x03@SNS部 (@masami256) 2017年1月30日 この記事に繋がってたりするのかな?なんて思ったりということで、 さらに話を続けてみてですね、こんなpatchを書きました。4.10.0-rc6がベースのカーネルです。 diff --git a/Makefile b/Makefile index 96b27a8..6c3f392 100644 --- a/Makefile +++ b/Makefile @@ -1024,6 +1024,7 @@ endif prepare2: prepare3 prepare-compiler-check outputmakefile asm-generic prepare1: prepare2 $(version_h) include/genera
systemd 228にlocal exploitがあったようなのでどんなバグだったのかをメモします。脆弱性の説明は、Headsup: systemd v228 local root exploit (CVE-2016-10156)に書かれてました。CVEはCVE-2016-10156です。 ちなみに、fedora 25のsystemdは201701/24時点で231です。 修正patchはbasic: fix touch() creating files with 07777 mode · systemd/systemd@06eeacb · GitHubです。 修正は以下のようになってます。 - fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644); + fd = open(path, O
gdbであるアドレスがアドレスを指している場合のdereferenceを簡単にやりたかったのでpythonでコマンド作ってみました。 これは例えばcのコードがこうで、 void func(char *p) { printf("[*] %s\n", p); } func()のディスアセンブル結果にこのような処理があるとします。 0x000000000040066e <+8>: mov %rdi,-0x8(%rbp) このとき、rbp - 8のアドレスは0x7fffffffdc68で、ここはアドレス0x0000000000602010を指しています。 (gdb) x/gx $rbp - 8 0x7fffffffdc68: 0x0000000000602010 このアドレスが指す内容は以下のようにしてdereferenceできますが、ちょっと面倒ですよね。 (gdb) x/s *(char **
Kia Ora! この記事はプロ生ちゃん Advent Calendar 2016の16日目の記事です。 2015年はbash-completionでコマンド補完するときにプロ生ちゃんに何か言ってもらう - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモなんて記事を書きました。2014年はプロ生ちゃん Advent Calenderではないけど、 systemdでshutdown時にプロ生ちゃんに挨拶してもらう - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモなんてネタを書いたりしました。 今年はすぱこー焼きそばソースを頂きました(∩´∀`)∩ワーイ 某氏よりプロ生ちゃんのソースを頂いたので今度焼きそばでも作ろう( ´ ▽ ` ) pic.twitter.com/etNhHQdTdj— int $0x03@SNS部 (@masami256) October 31, 2016 今年
この記事はLinux Advent Calendar 2016の1日目の記事です。 テストする時にstubって便利ですよね。最近はnodejsで仕事のコードを書いているのでsinon便利だなとか思ってます。じゃあ、Linuxカーネルでもstub作れたら便利だよねという思うわけです。そうすると、我々にはlivepatchという機能があります。 というわけで、Linuxカーネルのlivepatchを使ってstubを作れるようにしてみようと思ったのが今回の記事のネタです。 今回のコードはLinux 4.9.0-rc4で動かしています。 stub機能の前提としてlivepacthを使うのでstubのコードはlivepatch方式でカーネルモジュールとして作成します。どんな関数をどのようにstubするかはカーネルモジュールで決めるので、ここは使う人の自由となります。カーネル側はstubをするための機
たとえば、debugfsのディレクトリとファイルをプロセス毎に作って、ファイルの中身はプロセスごとに変えたいってことをしたい場合にどうするかというメモです。 foobarという機能がdebugfsのルートディレクトリにディレクトリを作成して、piyoというプロセスはfoobar/piyo、poyoならfoobar/poyoとディレクトリができます。で、ファイルはfileという名前で固定されているけど、内容は個々に違う感じです。 /sys/kernel/debugfs/foobar --- /piyo/file |-- /poyo/file piyo/、poyo/は任意のタイミングで作成できて、foobarはstart_main()の時に初期化の関数を呼んで作るものとします。 foobar用に1つだけファイルを作成するならバッファは一つで良いのでファイルのdentryはこんな感じで作れます。
次のページ
このページを最初にブックマークしてみませんか?
『φ(・・*)ゞ ウーン カーネルとか弄ったりのメモ』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く