Subject: Feature patch for chroot, adding --hostname parameter

From: [email-masked]
Date: Wed, 13 Jul 2011 12:46:10 +0200

Hello,

Here is a small patch to chroot that adds the ability to run the chroot
environment with a different namespace for the hostname.

I am hoping that other people (besides myself) will find this feature
useful, and that it will be considered for inclusion in the excellent
coreutils suite.

The additional code is plainly stolen from Michael Marineau's chname tool,
so I reckon most of the credit should go to him. (see
http://mike.marineau.org/blog/code/2007-07-23-giving-chroot-its-own-hostname-chname
)

With kind regards,
Zaerc Rene.
diff -ur coreutils-8.5.orig/src/chroot.c coreutils-8.5/src/chroot.c
--- coreutils-8.5.orig/src/chroot.c	2010-04-20 21:52:04.000000000 +0200
+++ coreutils-8.5/src/chroot.c	2011-07-07 15:29:47.000000000 +0200
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <grp.h>
+#include <sys/syscall.h>
 
 #include "system.h"
 #include "error.h"
@@ -37,16 +38,22 @@
 # define MAXGID GID_T_MAX
 #endif
 
+#ifndef CLONE_NEWUTS
+# define CLONE_NEWUTS	0x04000000
+#endif
+
 enum
 {
   GROUPS = UCHAR_MAX + 1,
-  USERSPEC
+  USERSPEC,
+  HOSTNAME
 };
 
 static struct option const long_opts[] =
 {
   {"groups", required_argument, NULL, GROUPS},
   {"userspec", required_argument, NULL, USERSPEC},
+  {"hostname", required_argument, NULL, HOSTNAME},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -132,6 +139,7 @@
       fputs (_("\
   --userspec=USER:GROUP  specify user and group (ID or name) to use\n\
   --groups=G_LIST        specify supplementary groups as g1,g2,..,gN\n\
+  --hostname=HOSTNAME    specify a different hostname\n\
 "), stdout);
 
       fputs (HELP_OPTION_DESCRIPTION, stdout);
@@ -151,6 +159,7 @@
   int c;
   char const *userspec = NULL;
   char const *groups = NULL;
+  char const *hostname = NULL;
 
   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
@@ -173,6 +182,10 @@
           groups = optarg;
           break;
 
+        case HOSTNAME:
+          hostname = optarg;
+          break;
+
         case_GETOPT_HELP_CHAR;
 
         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -188,6 +201,18 @@
       usage (EXIT_CANCELED);
     }
 
+  if (hostname)
+    {
+      // Use 'syscall' instead of unshare incase glibc doesn't have it.
+      // unshare(CLONE_NEWUTS);
+      if (syscall(__NR_unshare, CLONE_NEWUTS))
+        error (EXIT_CANCELED, errno, _("new utsname namespace failed"));
+
+      if (sethostname(hostname, strlen(hostname)+1))
+        error (EXIT_CANCELED, errno, _("set hostname failed"));
+    }
+
+
   if (chroot (argv[optind]) != 0)
     error (EXIT_CANCELED, errno, _("cannot change root directory to %s"),
            argv[optind]);