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.

Ken Thompson & Dennis Ritchie

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 MNT 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: sethostname");

Having compiled invoke_ns3.c, we can run the program with sudo ./invoke_ns -vpmu calculus bash, which will set the hostname inside the new UTS namespace as 'calculus'. If the PS1 prompt string is set appropriately, the bash command shell prompt running in the new PID, MNT and UTS namespaces will include the string 'calculus', but if not, simply typing the command hostname will yield 'calculus':

$ sudo ./invoke_ns -vpmu calculus bash
[sudo] password for wolf:
Parent: PID of parent is 12771  
Parent: PID of child is 12772  
 Child: PID of child is 1
 Child: Executing command bash ...
calculus [~] hostname  
calculus  
calculus [~]  

Hence, it's possible to provide processes running on a given host system, an entirely different identity to the host in terms of hostname, provided they exist in their own unique UTS namespace.

The next article will cover the NET namespace.