質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

FreeBSD

FreeBSDは、Unix系のオープンソースのOSです。PC/AT互換機用ですが、他のプラットフォームにも移植されています。優れたネットワーク・セキュリティ・ストレージ機能で人気のOSです。ソースコードと共に無償で公開されており、多くの コミュニティによって長年に渡って開発されています。

Q&A

解決済

1回答

1174閲覧

FreeBSD jailのC言語のシステムコールがEINVALになる

mask_mus

総合スコア37

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

FreeBSD

FreeBSDは、Unix系のオープンソースのOSです。PC/AT互換機用ですが、他のプラットフォームにも移植されています。優れたネットワーク・セキュリティ・ストレージ機能で人気のOSです。ソースコードと共に無償で公開されており、多くの コミュニティによって長年に渡って開発されています。

0グッド

0クリップ

投稿2021/02/22 08:32

編集2021/02/22 09:15

FreeBSD 12をHyper-V環境とVMWare環境に構築し、以下のような手順でディレクトリを作りました。
Hyper-VはFreeBSD 12.2-RELEASE-amd64.vhd.xz
VMwareはFreeBSD 12.1-RELEASE-amd64-dvd1.iso
から構築しました。

bash

1mkdir /jail 2mkdir /jail/sample-jail01 3 4fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/12.1-RELEASE/base.txz 5tar -xzpf base.txz -C /jail/sample-jail01

次のようなC言語のコードを実行しました。

c

1#include <stdio.h> 2#include <errno.h> 3#include <sys/param.h> 4#include <sys/jail.h> 5#include <sys/types.h> 6#include <unistd.h> 7#include <netinet/in.h> 8 9int main(void) 10{ 11 struct jail jail_01; 12 jail_01.version = 0; 13 jail_01.path = "/jail/sample-jail01"; 14 jail_01.hostname = "sample-jail01.com"; 15 16 // to be Jail Proccess 17 int jid = jail(&jail_01); 18 19 if (jid < 0) 20 { 21 printf("errno=%d\n", errno); 22 return -1; 23 } 24 25 printf("jid=%d\n", jid); 26 27 int ret = execl("/bin/sh", "/etc/rc", NULL); 28 29 return 0; 30} 31

VMWareではjail関数が成功してjailが起動するのですが、Hyper-Vではerrno=22と出力されてしまいます。
jail関数がEINVALの時は引数のバージョン番号が正しくないらしいのですが、引数のバージョン番号とはstruct jailのversionメンバのことなのかどうかがわかりません。jail_01.versionを03まで変えてみましたが13に設定したとき、Hyper-VでもVMwareでもerrno=22になりました。

引数のバージョン番号とはなんなのか、なぜerrno=22が出続けるのかを教えていただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

バージジョンについては以下のようにすると確認できます。

$ man -S 2 jail

私の環境(12.2-RELEASE-p3)で表示された内容から一部を抜粋します。

The jail() system call sets up a jail and locks the current process in it. The argument is a pointer to a structure describing the prison: struct jail { uint32_t version; char *path; char *hostname; char *jailname; unsigned int ip4s; unsigned int ip6s; struct in_addr *ip4; struct in6_addr *ip6; }; “version” defines the version of the API in use. JAIL_API_VERSION is defined for the current version.

最後の文に書かれているとおりversionにはJAIL_API_VERSIONを設定すればいいと思います。一応、値を確認したところ2でした。

$ grep JAIL_API /usr/include/sys/jail.h #define JAIL_API_VERSION 2

ところで、エラーになる原因ですが、構造体を初期化してないからかもしれません。こちらのページの4.1.1.1の項を見たとこら、構造体を以下のようにmemsetで初期化していました。

c

1/usr/src/usr.sbin/jail/jail.c 2... 3memset(&j, 0, sizeof(j)); 4j.version = 0; 5j.path = path; 6j.hostname = argv[1];

(かなり古い内容なのでversion = 0のところなどは参考にならないと思います)

試しにmemsetを追加してみてください。先ほどのJAIL_API_VERSIONと合わせて以下のようになると思います。

c

1// この行を追加 2#include <string.h> 3 4// ...(中略)... 5 6 struct jail jail_01; 7 memset(&jail_01, 0, sizeof(jail_01)); // この行を追加 8 jail_01.version = JAIL_API_VERSION; // JAIL_API_VERSIONを使用 9 jail_01.path = "/jail/sample-jail01"; 10 jail_01.hostname = "sample-jail01.com";

投稿2021/02/22 12:09

tatsuya6502

総合スコア2035

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mask_mus

2021/02/22 13:39 編集

無事に解決することができました、ありがとうございます。 メンバに値をセットすれば初期化は不要だと思っていたのですが、初期化が必要な理由を教えていただけないでしょうか?
tatsuya6502

2021/02/22 14:02 編集

今回のプログラムではversion, path, hostnameに値をセットしていますが、manで表示された説明を読むと、現在の(バージョン2の)jail構造体にはさらに次のメンバがあることがわかります。jailname, ip4s, ip6s, ip4, ip6 ですから、これらのメンバにも値をセットしないといけないです。 manの説明を読むと、これらのメンバの値は省略可能で、省略するときは0やNULLをセットすることになっているとわかります。FreeBSDではNULLは0なので、memsetを使ってjail構造体の全体を0で埋めることでjailname, ip4sなどのメンバをセットしています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問