The UTS namespace is used to isolate two specific elements of the system that relate to the uname
system call. UTS is an abbreviation of UNIX Time Sharing, a term that dates back to the fledgling days of UNIX, when multi-user, multi-tasking operating systems were a novelty.
The UTS namespace is named after the data structure used to store information returned by the uname
system call. Specifically, the UTS namespace isolates the hostname and the NIS domain name. NIS, an abbreviation of Network Information Service, is an outdated directory service created by Sun Microsystems for the Solaris operating system, which was discontinued by Oracle after its acquisition of Sun Microsystems. In short, the UTS namespace is about isolating hostnames.
To demonstrate its use, the program we used in the last article about the mount namespace, has been further adapted as invoke_ns3.c
, and is available here. Unsurprisingly, we’ve added a new command line option to our program, -u
, which must be accompanied with a string that will be used to set the hostname in our newly created UTS namespace:
$ ./invoke_ns -h
Usage: ./invoke_ns [options] [cmd [arg...]]
Options can be:
-h display this help message
-v display verbose messages
-p new PID namespace
-m new MNT namespace
-u hostname new UTS namespace with associated hostname
We’ve added some code to parse the command line when -u
is specified, which adds the CLONE_NEWUTS
constant to the clone flags, and stores the hostname in some dynamically allocated memory. The pointer to the memory is passed as part of the args
structure to the clone
system call, which provides the arguments to childFunction
:
// Parse command line options and construct arguments
// to be passed to childFunction
while ((option = getopt(argc, argv, "+hvpmu:")) != -1) {
switch (option) {
case 'u':
flags |= CLONE_NEWUTS;
args.hostname = malloc(sizeof(char) * (strlen(optarg) + 1));
strcpy(args.hostname, optarg);
break;
case 'm':
flags |= CLONE_NEWNS;
break;
case 'p':
flags |= CLONE_NEWPID;
break;
case 'v':
args.verbose = 1;
break;
case 'h':
usage(argv[0]);
exit(EXIT_SUCCESS);
default:
usage(argv[0]);
exit(EXIT_FAILURE);
}
}
In order to set the hostname inside the new UTS namespace, we need to add some code to childFunction
using the sethostname
system call:
// Set new hostname in UTS namespace if applicable
if (args->flags & CLONE_NEWUTS)
if (sethostname(args->hostname, strlen(args->hostname)) == -1)
perror(" Child: childFunction: sethostname");
Having compiled invoke_ns3.c
, we can run the program with sudo ./invoke_ns -vpmu calculus env PS1='\h\[\] [\[\]\w\[\]] ' bash
, which will set the hostname inside the new UTS namespace as ‘calculus’. As part of the command that’s specified for the cloned process to run, we’ve set the bash
shell prompt (using the environment variable PS1
) to include the hostname, which is, of course, ‘calculus’. We can also use the hostname
command to echo the hostname set for the UTS namespace:
$ sudo ./invoke_ns -vpmu calculus env PS1='\h\[\] [\[\]\w\[\]] ' bash --norc
Parent: PID of parent is 16375
Parent: PID of child is 16376
Child: PID of child is 1
Child: executing command env ...
calculus [/home/wolf] hostname
calculus
Hence, it’s possible to provide processes running on a given host system, an entirely different identity in terms of hostname, provided they exist in their own unique UTS namespace.
The next article will cover the NET namespace.