ホスト名とsetns
本内容は、SETNSについてです。
newuts.cは、CLONE_NEWUTSで、親プロセスと異なるネームスペースの子プロセスを作成し、この子プロセスにsethostname()でホスト名(コマンド引数)を設定する事で、デフォルトの親プロセスのホスト名(localhost.localdomain)と子プロセスのホスト名(babakaka)のホスト名を有する環境となります。
シェルから起動されたプロセスは、ネームスペースの変更がない限り、親シェルのネームスペースのlocalhost.localdomainを継承しますが、このシェル下でbabakakaのプロセスのネームスペースをsetns()で更新後、execしたbashは、localhost.localdomaiでなくbabakakaとなります。
newuts.c
setns.c
newuts.cは、CLONE_NEWUTSで、親プロセスと異なるネームスペースの子プロセスを作成し、この子プロセスにsethostname()でホスト名(コマンド引数)を設定する事で、デフォルトの親プロセスのホスト名(localhost.localdomain)と子プロセスのホスト名(babakaka)のホスト名を有する環境となります。
シェルから起動されたプロセスは、ネームスペースの変更がない限り、親シェルのネームスペースのlocalhost.localdomainを継承しますが、このシェル下でbabakakaのプロセスのネームスペースをsetns()で更新後、execしたbashは、localhost.localdomaiでなくbabakakaとなります。
newuts.c
#define _GNU_SOURCE
#include <sys/wait.h>
#include <sys/utsname.h>
#include <sched.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
static int childFunc(void *arg)
{
struct utsname uts;
if (sethostname(arg, strlen(arg)) == -1)
errExit("sethostname");
if (uname(&uts) == -1)
errExit("uname");
printf("uts.nodename in child: %s\n", uts.nodename);
sleep(200);
return 0;
}
#define STACK_SIZE (1024 * 1024) /* clone される子プロセスのスタックサイズ */
int main(int argc, char *argv[])
{
char *stack;
char *stackTop;
pid_t pid;
struct utsname uts;
if (argc < 2) {
fprintf(stderr, "Usage: %s <child-hostname>\n", argv[0]);
exit(EXIT_SUCCESS);
}
stack = malloc(STACK_SIZE);
if (stack == NULL)
errExit("malloc");
stackTop = stack + STACK_SIZE;
pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]);
if (pid == -1)
errExit("clone");
printf("clone() returned %ld\n", (long) pid);
sleep(1);
if (uname(&uts) == -1)
errExit("uname");
printf("uts.nodename in parent: %s\n", uts.nodename);
if (waitpid(pid, NULL, 0) == -1)
errExit("waitpid");
printf("child has terminated\n");
exit(EXIT_SUCCESS);
}
setns.c
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
int
main(int argc, char *argv[])
{
int fd;
if (argc < 3) {
fprintf(stderr, "%s /proc/PID/ns/FILE cmd args...\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY); /* 名前空間のディスクリプターを取得 */
if (fd == -1)
errExit("open");
if (setns(fd, 0) == -1) /* 名前空間に参加 */
errExit("setns");
execvp(argv[2], &argv[2]); /* 名前空間内でコマンドを実行 */
errExit("execvp");
}
実効結果
子プロセスIDは2270でホスト名はbabakakaで、シェルとする親プロセスIDは2269でホスト名はlocalhost.localdomainです。[root@localhost test]# ./newuts babakaka & [1] 2269 [root@localhost test]# clone() returned 2270 uts.nodename in child: babakaka uts.nodename in parent: localhost.localdomain [root@localhost test]# uname -n localhost.localdomain [root@localhost test]# ./setns /proc/2270/ns/uts /bin/bash [root@babakaka test]# uname -n babakaka [root@localhost test]# ./setns /proc/2269/ns/uts /bin/bash [root@babakaka test]# uname -n localhost.localdomain [root@localhost test]# exit exit [root@babakaka test]# uname -n babakaka [root@babakaka test]# exit exit [root@localhost test]# uname -n localhost.localdomain






