NetBSD Advent Calendar 2024 11日目の記事です。
今日は8日目の記事で紹介した、所有者とグループを考慮したハードリンク作成制限機能について、ソースコードレベルでの処理がどうなっているかを見てみようと思います。
ハードリンク作成時のuid,gidチェック
ハードリンク作成制限は、sysctl(8)の security.models.extensions.hardlink_check_*
というMIB(Management Information Base)エントリの値を設定することで実現できます。
hardlink_check_
というキーワードで grep
してみます。どうやら /usr/src/sys/secmodel/extensions/secmodel_extensions.c
というファイルでMIB用の変数定義と値の参照が行われているようです。
$ find /usr/src/sys -type f | xargs grep hardlink_check
/usr/src/sys/secmodel/extensions/secmodel_extensions.c:static int hardlink_check_uid;
/usr/src/sys/secmodel/extensions/secmodel_extensions.c:static int hardlink_check_gid;
/usr/src/sys/secmodel/extensions/secmodel_extensions.c: CTLTYPE_INT, "hardlink_check_uid",
/usr/src/sys/secmodel/extensions/secmodel_extensions.c: &hardlink_check_uid, 0,
/usr/src/sys/secmodel/extensions/secmodel_extensions.c: CTLTYPE_INT, "hardlink_check_gid",
/usr/src/sys/secmodel/extensions/secmodel_extensions.c: &hardlink_check_gid, 0,
/usr/src/sys/secmodel/extensions/secmodel_extensions.c: if (hardlink_check_uid && kauth_cred_geteuid(cred) != va.va_uid)
/usr/src/sys/secmodel/extensions/secmodel_extensions.c: if (hardlink_check_gid && kauth_cred_groupmember(cred, va.va_gid) != 0)
ファイル所有者以外のハードリンク作成を制限する機能について見てみます。
52行目で hardlink_check_uid
というMIBエントリの値を保持する変数が宣言され( static
宣言されているのでデフォルト値は 0
)、157~164行目で sysctl
にMIBエントリが追加されています。
52 static int hardlink_check_uid;
...
157 sysctl_createv(clog, 0, &rnode, NULL,
158 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
159 CTLTYPE_INT, "hardlink_check_uid",
160 SYSCTL_DESCR("Whether unprivileged users can hardlink "\
161 "to files they don't own"),
162 sysctl_extensions_user_handler, 0,
163 &hardlink_check_uid, 0,
164 CTL_CREATE, CTL_EOL);
hardlink_check_uid
の値がどのように参照されているか見てみます。548行目で hardlink_check_uid
が真、かつ取得したuidが自分( kauth_cred_t
で渡したクレデンシャル経由で取得しているっぽい)と異なる場合に checkroot:
ラベルにジャンプし、 root
ユーザでない場合はuidが異なる場合のハードリンク作成制限に該当するため、 KAUTH_RESULT_DENY
を返すという挙動になっています。
gidをチェックする場合もほぼ同じ処理になっており、 root
ユーザかどうかのチェックは共通化できるため、 checkroot:
ラベルにジャンプするという実装になっているようです。
533 static int
534 secmodel_extensions_vnode_cb(kauth_cred_t cred, kauth_action_t action,
535 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
536 {
537 int error;
538 bool isroot;
539 struct vattr va;
...
544 error = VOP_GETATTR((vnode_t *)arg0, &va, cred);
...
548 if (hardlink_check_uid && kauth_cred_geteuid(cred) != va.va_uid)
549 goto checkroot;
...
554 return KAUTH_RESULT_DEFER;
555 checkroot:
556 error = secmodel_eval("org.netbsd.secmodel.suser", "is-root",
557 cred, &isroot);
558 if (error || !isroot)
559 return KAUTH_RESULT_DENY;
560
561 return KAUTH_RESULT_DEFER;
562 }
まとめ
所有者とグループを考慮したハードリンク作成制限機能について、ソースコードレベルでの処理を見てみました。基本的には sysctl
で機能が有効・無効であるかを判定し、有効な場合は然るべき判定処理(uidが違う場合は root
ユーザかどうかをチェック)するという、シンプルな実装になっていました。ただ、これらの処理はsecmodel(9)というフレームワークを使用しており、secmodel(9)の利用により実装しやすくなっているという側面もあるようです。