In addition to the xterm consoles that made themselves visible, some others have attached themselves less visibly to other host resources. You can attach UML consoles to almost any host device that can be used for that purpose. For example, they can be (and some, by default, are) attached to host pseudo-terminals. They announce themselves in the kernel log, which we can see by running dmesg: UML% dmesg | grep "Serial line" Serial line 0 assigned device '/dev/pts/13' This tells us that one UML serial line has been configured in /etc/inittab to have a login prompt on it. The serial line has been configured at the "hardware" level to be attached to a host pseudo-terminal, and it has allocated the host's /dev/pts/13. Now we can run a terminal program, such as screen or minicom, on the host, attach it to /dev/pts/13, and log in to UML on its one serial line. After running host% screen /dev/pts/13 we see a blank screen session. Hitting return gives us another UML login prompt, as advertised: Debian GNU/Linux 2.2 usermode ttyS0 usermode login: Notice the ttyS0 in the banner, in comparison to the tty0 we saw while logging in as root in the previous chapter and the tty1 we just saw while logging in as user. The tty0 and tty1 devices are UML consoles, while ttyS0 is the first serial line. On a physical machine, the consoles are devices that are displayed on the screen, and the serial lines are ports coming out of the back of the box. There's a clear difference between them. In contrast, there is almost no difference between the consoles and serial lines in UML. They plug themselves into the console and serial line infrastructures, respectively, in the UML kernel. This is the cause of the different device names. However, in all other ways, they are identical in UML. They share essentially all their code, they can be configured to attach to exactly the same host devices, and they behave in the same ways. In fact, the serial line driver in UML owes its existence to a historical quirk. Because of a limitation in the first implementation of UML, it was impossible to log in on a console in the window in which you ran it. To allow logging in to UML at all, I implemented the serial line driver to connect itself to a host device, and you would attach to this using something like screen. As time went on and limitations disappeared, I implemented a real console driver. After a while, it dawned on me that there was no real difference between it and the serial line driver, so I started merging the two drivers, making them share more and more code. Now almost the only differences between them are that they plug themselves into different parts of the kernel. UML consoles and serial lines can be attached to the same devices on the host, and we've seen a console attached to stdin and stdout of the linux process, consoles appearing in xterms, and a serial line attached to a host pseudo-terminal. They can also be attached to host ports, allowing you to telnet to the specified port on the host and log in to the UML from there. This is a convenient way to make a UML accessible from the network without enabling the network within UML. Finally, UML consoles and serial lines can be attached to host terminals, which can be host consoles, such as /dev/tty*, or the slave side of pseudo-terminals. Attaching a UML console to a host virtual console has the interesting effect of putting the UML login prompt on the host console, making it appear (to someone not paying sufficient attention) to be the host login. Let's look at some examples. First, let's attach a console to a host port. We need to find an unused console to work with, so let's use the UML management console tool to query the UML configuration: host% uml_mconsole debian config con0 OK fd:0,fd:1 host% uml_mconsole debian config con1 OK none host% uml_mconsole debian config con2 OK pts:/dev/pts/10 host% uml_mconsole debian config con3 OK pts We will cover the full capabilities of uml_mconsole in Chapter 8, but this gives us an initial look at it. The first argument, debian, specifies which UML we wish to talk to. A UML can be named and given a unique machine ID, or umid. When I ran this UML, I added umid=debian to the command line, giving this instance the name debian. uml_mconsole knows how to use this name to communicate with the debian UML. If you didn't specify the umid on the command line, UML gives itself a random umid. There are a couple of ways to tell what it chose. First, look through the boot output or output from dmesg for a line that looks like this: mconsole (version 2) initialized on /home/jdike/.uml/3m3vDd/mconsole In this case, the umid is 3m3vDd. You can communicate with this instance by using that umid on the uml_mconsole command line. Second, UML puts a directory with the same name as the umid in a special parent directory, by default, ~/.uml. So, you could also look at the subdirectory [1] of your ~/.uml directory for the umid to use.
The rest of the uml_mconsole command line is the command to send to the specified UML. In this case, we are asking for the configurations of the first few consoles. Console names start with con; serial line names begin with ssl. I will describe as much of the output format as needed here; Figure 3.1 contains a more complete and careful description.
Looking at the output about the UML configuration, we see an OK on each response, which means that the command succeeded in communicating with the UML and getting a response. The con0 response says that console 0 is attached to stdin and stdout. This bears some explaining, so let's pull apart that response. There are two pieces to it, fd:0 and fd:1, separated by a comma. In a comma-separated configuration like this, the first part refers to input to the console (or serial line), and the second part refers to output from it. The fd:0 part also has two pieces, fd and 0, separated by a colon. fd says that the console input is to be attached to a file descriptor of the linux process, and 0 says that file descriptor will be stdin, file descriptor zero. Similarly, the output is specified to be file descriptor one, stdout. When the console input and output go to the same device, as we can see with con2 being attached to pts:/dev/pts/10, input and output are not specified separately. There is only a single colon-separated device description. As you might have guessed, pts refers to a devpts pseudo-terminal, and /dev/pts/10 tells you specifically which pseudo-terminal the console is attached to. The con1 configuration is one we haven't seen before. It simply says that the console doesn't existthere is no such device. The configuration for con3 is the one we are looking for. pts says that this is a pts console, and there's no specific pts device listed, so it has not yet been activated by having a UML getty running on it. We will reconfigure this one to be attached to a host port: host% uml_mconsole debian config con3=port:9000 OK port:9000 says that the console should be attached to the host's port 9000, which we will access by telnetting to that port. We can double-check that the change actually happened: host% uml_mconsole debian config con3 OK port:9000 So far, so good. Let's try telnetting there now: host% telnet localhost 9000 Trying 127.0.0.1... telnet: connect to address 127.0.0.1: Connection refused This failed because UML hasn't run a getty on its console 3. We can fix this by editing its /etc/inittab. Looking there on my machine, I see: #3:2345:respawn:/sbin/getty 38400 tty3 I had enabled this one in the past but since disabled it. You may not have a tty3 entry at all. You want to end up with a line that looks like this: 3:2345:respawn:/sbin/getty 38400 tty3 I'll just uncomment mine; you may have to add the line in its entirety, so fire up your favorite editor on /etc/inittab and fix it. Now, tell init it needs to reread the inittab file: UML# kill -HUP 1 Let's go back to the host and try the telnet again: host% telnet localhost 9000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Fedora Core release 1 (Yarrow) Kernel 2.4.27 on an i686 Debian GNU/Linux 2.2 usermode tty3 usermode login: Here we have the UML's console, as advertised. Notice the discrepancy between the telnet banner and the login banner. Telnet is telling us that we are attaching to a Fedora Core 1 (FC1) system running a 2.4.27 kernel, while login is saying that we are attaching to a Debian system. This is because the host is the FC1 system, and telnetd running on the host and attaching us to the host's port 9000 is telling us about the host. There is some abuse of telnetd's capabilities going on in order to allow the redirection of traffic between the host port and UML, and this is responsible for the confusion. Now, let's stick a UML console on a host console. First, we need to make sure there's no host getty or login running on the chosen console. Looking at my host's /etc/inittab, I see: 6:2345:respawn:/sbin/mingetty tty6 for the last console, and hitting Ctrl-Alt-F6 to switch to that virtual console confirms that a getty is running on it. I'll comment it out, so it looks like this: #6:2345:respawn:/sbin/mingetty tty6 I tell init to reread inittab: host# kill -HUP 1 and switch back to that console to make sure it is not being used by the host any more. I now need to make sure that UML can open it: host% ls -l /dev/tty6 crw------ 1 root root 4, 6 Feb 17 16:26 /dev/tty6 This not being the case, I'll change the permissions so that UML has both read and write access to it: host# chmod 666 /dev/tty6 After you make any similar changes needed on your own machine, we can tell UML to take over the console. We used the UML tty3 for the host port console, so let's look at tty4: host% uml_mconsole debian config con4 OK pts So, let's assign con4 to the host's /dev/tty6 in the usual way: host% uml_mconsole debian config con4=tty:/dev/tty6 OK After enabling tty4 in the UML /etc/inittab and telling init to reread the file, we should be able to switch to the host's virtual console 6 and see the UML login prompt. Taken to extremes, this can be somewhat mind bending. Applying this technique to the other virtual con soles results in them all displaying UML, not host, login prompts. For the security conscious, this sort of redirection and fakery can be valuable. It allows potential attacks on the host to be redirected to a jail, where they can be contained, logged, and analyzed. For the rest of us, it serves as an example of the flexibility of the UML consoles. Now that we've seen all the ways to access our UML console, it's time to stay logged in on the console and see what we can do inside the UML. |