3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NetBSDAdvent Calendar 2023

Day 24

NetBSDのカーネルモジュールからホスト名を設定してみる

Posted at

NetBSD Advent Calendar 2023 24日目の記事です。今日はカーネルモジュールからNetBSDカーネル空間内のデータを操作してみます。

カーネル空間内のデータ

カーネルモジュールはその名前の通り、カーネル空間に組み込んで使用します。言い換えると、カーネル空間内のデータに自由にアクセスできるということになります。今日の記事では、作成したカーネルモジュールからカーネル空間内の既存のデータを操作してみます。

ホスト名書き換えカーネルモジュール

NetBSD(に限らずUNIX系OS)では、hostname(1)でホスト名を設定できます。カーネルの実装という観点からすると、カーネル内にホスト名の情報を保持する変数を用意する形で実装されています。具体的には/usr/src/sys/kern/kern_sysctl.cの以下の個所で宣言されている変数でホスト名が保持されています。

 152 char hostname[MAXHOSTNAMELEN];
 153 int hostnamelen;

MAXHOSTNAMELEN/usr/src/sys/sys/param.hで以下のように定義されています。

124 #define MAXHOSTNAMELEN  256     /* max hostname size */

char hostname[] はカーネル空間内であればどこからでも参照・変更可能です。今回はデバイスファイルへのwrite(2)経由でホスト名を設定し、カーネルモジュール側で write() されたデータを受け取り、新しいホスト名として設定するサンプルを作成してみます。

カーネルモジュールのサンプルコード

カーネル空間側(カーネルモジュール)のコードは以下になります。

使用するデバイス /dec/hostname_sample への write(2)hostname_sample_write() 関数に紐づけられており、ユーザ空間から書き込まれたデータ(ホスト名文字列)をカーネル空間にコピーしたのち、変数 hostname に設定することでホスト名を設定しています。

カーネルモジュールビルド用の Makefile を作成します。この Makefile とCソースファイルは /usr/src/sys/modules/example/hostname_sample のようなディレクトリに配置します。

.include "../Makefile.inc"

#S?=    /usr/src/sys
KMOD=   hostname_sample
SRCS=   hostname_sample.c

.include <bsd.kmodule.mk>

make コマンドでビルドします。

# make
...
/usr/src/tooldir.NetBSD-9.3-amd64/bin/x86_64--netbsd-gcc -O2 -g   -std=gnu99    -Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wno-sign-compare  -Wsystem-headers   -Wno-traditional   -Wa,--fatal-warnings  -Wreturn-type -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -Wextra -Wno-unused-parameter -Wno-sign-compare -Wold-style-definition -Wsign-compare -Wformat=2  -Wno-format-zero-length  -Werror   -ffreestanding  -fno-strict-aliasing -Wno-pointer-sign -mno-red-zone -mno-mmx -mno-sse -mno-avx -msoft-float -mcmodel=kernel -fno-omit-frame-pointer   -I/usr/src/common/include --sysroot=/ -I/usr/src/common/include  -nostdinc -I. -I/usr/src/sys/modules/examples/hostname_sample -isystem /usr/src/sys -isystem /usr/src/sys/arch -isystem /usr/src/sys/../common/include -D_KERNEL -D_LKM -D_MODULE -DSYSCTL_INCLUDE_DESCR -c    hostname_sample.c
/usr/src/tooldir.NetBSD-9.3-amd64/bin/nbctfconvert -L VERSION hostname_sample.o
#      link  hostname_sample/hostname_sample.kmod
/usr/src/tooldir.NetBSD-9.3-amd64/bin/x86_64--netbsd-gcc  --sysroot=/ -Wl,--warn-shared-textrel -Wl,-z,relro -nostdlib -r -Wl,-T,/usr/src/sys/../sys/modules/xldscripts/kmodule,-d  -Wl,-Map=hostname_sample.kmod.map  -o hostname_sample.kmod hostname_sample.o
/usr/src/tooldir.NetBSD-9.3-amd64/bin/nbctfmerge -t -L VERSION -o hostname_sample.kmod hostname_sample.o

デバイスノードを作成します。データを書き込む想定であるため、 chmod 666 でデバイスファイルに書き込み権限を付与しておきます。これでカーネル側での準備は完了です。

# mknod /dev/hostname_sample c 210 0
# chmod 666 /dev/hostname_sample

ユーザ空間側のサンプルコード

ユーザ空間側のコードは以下になります。write(2) でホスト名を設定し、read(2) で現在のホスト名を取得しています。

コンパイルして実行してみます。無事にホスト名の設定と取得が行えていることが確認できます。

# gcc -Wall -g -o hostname_sample hostname_sample.c
#
# # 現在のホスト名を取得する。
# ./hostname_sample
mbsd93test
#
# # カーネルモジュール経由でホスト名を設定する。
# ./hostname_sample newname
newname
#
# # 設定されたホスト名を確認する。
# ./hostname_sample
newname

まとめ

カーネルモジュールからカーネル空間内の既存のカーネルデータを操作してみました。今回のサンプルはカーネル内のデータだけでなく、カーネルが提供する機能を試してみるケースにも応用できそうです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?