Sunday, March 25, 2012

How to Lock Down and Clean up GRUB 2

In Ubuntu 9.10 and later

Introduction
Ubuntu boots using the GRUB boot loader. GRUB has all sorts of fun powers including the ability to pull up a root shell without any authentication. Sometimes, though, you don't want root to be so trivially accessible to your drunk frenemies and script kiddie siblings. This is a perfectly normal sentiment.

In this post, I will explain how to lock down the GRUB 2 boot menu used in Ubuntu. This will not protect your data if your computer is stolen, if the CIA is out to get you, or in the face of another persistent attack. It will, however, make it a lot harder for passersby to ruin your digital life.

GRUB 2 on Ubuntu is a bit of a mess at the moment, and locking down GRUB is a good time to also do some cleaning up. The second part of the post is about just that.

Disclaimer
The procedure I describe worked for me, but it might not work for you. I am not your sysadmin, and I am not responsible for what you do with the computers to which you have access. I cannot be responsible for any data loss resulting from following these instructions. ALWAYS MAKE A BACKUP! I used Ubuntu 11.10 (Oneiric Ocelot); other versions may differ.

Background

This section explains why configuring GRUB 2 on Ubuntu is such a pain. If you're just skimming through, the interesting info starts in the next section.

Since Ubuntu 9.10 (Karmic Koala), Ubuntu has used GRUB 2 as the bootloader rather than classic GRUB. The difference in configuring the two is illustrated in the following diagram:
In words: In classic GRUB, the user wrote a menu.lst file that controlled GRUB. In GRUB 2, the user modifies a series of configuration files and scripts, the update-grub script takes these files and some hard-coded magic, and spits out a grub.cfg configuration file.

Using eight (or more) configuration files has some advantages over using just one. For example, 8 is clearly a bigger and better number than 1. On the downside, the number of files involved makes it difficult to find the setting you want, and sometimes the setting you want is controlled by hard-coded scripting magic instead of a line in a configuration file. Password-protecting GRUB is an example of just such functionality.

The amusingly unhelpful “Security” section of Ubuntu's GRUB 2 documentation says that there's no way to lock down GRUB. This is actually not true; it's possible to have coarse-grained control over what is locked in GRUB through the standard configuration files. Fine-grained control currently requires a slightly more unorthodox approach. I will cover both options.

Files

First, a list of all the useful files:

/etc/default/grub
The main, user-facing configuration file. All the options you would ever want to change as an end user should be in this file. In fact, they are not.

/etc/grub.d/##_<description>
These scripts generate the entries that show up in the GRUB 2 boot menu. You're really only meant to edit the one called 40_custom.

/boot/grub/grub.cfg
This is the autogenerated GRUB 2 configuration. You should never touch this file, but editing it is the only way to get GRUB to really do what you want.

/usr/sbin/update-grub
This is a very thin wrapper around grub-mkconfig. It is called to regenerate grub.cfg.

Locking down GRUB
This section is based on some Googling, the GRUB info pages, and trial and error. Before you change anything, it's a good idea to create copies of the files so that it's easy to revert back. You will need root access to complete these steps.

1. Disable generation of recovery mode menu entries (optional)
In /etc/default/grub, uncomment the GRUB_DISABLE_RECOVERY=”true” line. Recovery mode entries in the GRUB menu allow access to a root shell. Uncommenting this line will make the recovery mode entries go away. Of course, you might want a recovery mode entry in case you need it, so you can skip this step. However, if you do skip this step, you will need to resort to the unorthodox methods in step 4 to lock GRUB.

2. Set superuser name and password
In /etc/grub.d/40_custom, add these two lines at the end:
set superusers="root"
password_pbkdf2 root grub.pbkdf2.sha512.10000.<biglongstring>
As with all shell scripts, make sure the file ends with a blank line.

The first line sets the name of the superuser to “root”. The second line contains the hash of the root user's password. To obtain this, run $> grub-mkpasswd-pbkdf2 on the command line, and type the desired password. Then paste the output of the command into 40_custom.

This change, once passed to grub.cfg, will password-protect command-line access and the ability to edit menu items from within GRUB itself. If you skipped step 1, recovery mode entries will still allow unfettered access to a root shell.

3. Run update-grub 
$> sudo update-grub
This will generate a new grub.cfg file, taking into account the changes in the previous two steps.

If you completed step 1, you now have coarse-grained password-protection: GRUB will allow you to boot all installed Linux kernels as well as any other OS you have on your hard drive without a password. There are no recovery mode menu items, and you need a password to get into a shell from GRUB. You can finish here or go on to the next step.

4. Hack grub.cfg (optional)
If you want fine-grained control over what is password-protected in GRUB or you skipped step 1, you will need to hack grub.cfg. Some system updates will regenerate grub.cfg for you, so you will need to repeat this step after every update.

The first thing to do is find the recovery mode entry and other entires you want to password-protect in grub.cfg, and add the --user "" option:
menuentry 'Ubuntu, with Linux <some version> (recovery mode)' --users "" --class ubuntu ...
This tells GRUB that by default, no users are allowed to access this entry; the root password will be required to run it.

If you have more than one Linux kernels installed and you skipped step 1, update-grub will create recovery mode entries for each kernel. These show up in a GRUB sub-menu called “Previous Linux versions.” You will see
submenu "Previous Linux versions" {...}
in grub.cfg. For some reason, adding the --user "" option does not actually password-protect the recovery modes of previous Linux kernels. The solution is to either uninstall all but one kernel, or just comment out the entries in grub.cfg. When commenting out, make sure to comment out the right number of closing curly braces. You can also comment out the entire “Previous Linux versions” submenu. Unfortunately there is no obvious way to keep this submenu from being created in the first place.

Now just save grub.cfg, and reboot into GRUB to check that it all worked. I have no idea on how GRUB will respond to a malformed grub.cfg file, so be very careful when editing it.

Cleaning up GRUB
Since you're already messing around with all the configuration files, now is a good time to clean up the GRUB menu. Here are three ideas.

Remove old kernel versions
Unless you're a developer, there's really no reason to have the ability to boot previous Linux kernels. In grub.cfg, comment out the bit that starts with
submenu "Previous Linux versions" {
Again, make sure to comment out the right number of closing curly braces.

Remove other operating systems
You might have other operating systems on your computer that you don't plan to boot using GRUB. For example, you might have followed this guide to triple-boot a Mac. You could comment these out in grub.cfg, but the better option is to use /etc/grub.d/30_os-prober. You could rename the file to something like no_touchy_30_os-prober, take away the execute privileges with chmod, or move it somewhere else. All three options will keep other operating systems from showing up in the GRUB menu. Note that this is an all-or-nothing step; there's no way to choose which other OSes to list and which ones to ignore.

Decrease GRUB timeout
When you're booting up, there's no reason to sit at the GRUB menu for half a minute. In /etc/default/grub, change the GRUB_TIMEOUT value to something like 5 or 1 or however many seconds you like. If you need to, you can always stop the timer in the GRUB menu by hitting an arrow key.

Conclusion
Out of the box, GRUB 2 on Ubuntu can be unwieldy and a bit messy. There are many configuration files in various places that control GRUB, and it can be difficult to keep track of them. It's possible to lock down GRUB and clean up the GRUB menu just by using the configuration files, but to really control GRUB, you need to break the configuration interface.

I'm not sure how much of the configuration process is designed by the Ubuntu developers, and how much is designed by the GRUB developers. I can see that the developers are trying to organize the configuration process to make it more user-friendly, but I don't think it's working as well as it could. Admittedly, GRUB 2 is still in active development, but I'm not convinced that it's even possible to extend the current configuration infrastructure to provide both simplicity for normal users and flexibility for power users.

Sunday, January 29, 2012

Bash One-Liner and Function to grep PDFs


Sometimes you need to find some text in PDF files. The problem is that PDFs are often compressed, making standard grep useless. Spotlight in OS X keeps PDFs indexed, and there might be something similar in Windows. There is no obvious way of doing a simple search of PDFs in Linux, however.

My solution is the following bash one-liner that lists all PDFs in a directory and subdirectories that contain a search term. It uses the pdftotext utility from Xpdf (here, no compilation needed). Both search terms and PDF file names can include spaces.

$> find . -iname "*.pdf" -print0 | xargs -n1 -i -0 bash -ci 'if [ `pdftotext "{}" - | grep -ci "<search term>"` != 0 ] ; then echo "\"{}\"" ; fi ; '

Just replace <search term> with what you're looking for (and make sure you don't miss any of the spaces—they're important).

An even better option is to add this function to your .bashrc file:

function fpdf ()
{
acroread &
find . -iname "*.pdf" -print0 | xargs -n1 -i -0 bash -ci 'if [ `pdftotext "{}" - | grep -ci "$0"` != 0 ] ; then echo "\"{}\"" ; fi ; ' "$1" | xargs -n1 acroread
}

Now running $> fpdf "search term" in a directory will use acroread to open all PDFs in the directory and subdirectories that contain the search term. You can, of course, replace acroread with any PDF reader of your choice.

How does it work?

First, acroread is started as a background process. This keeps every subsequent invocation of acroread from blocking the search.

Next, bash replaces $1 with the search term.

Then, find . -iname "*.pdf" -print0 does a case-insensitive search for all files in the current directory that end with .pdf and prints them out as a NUL-separated list. This list is piped to xargs. The NUL-separated list is better at keeping file names from interfering with xargs than a new-line separated list.

Next, xargs runs bash once for each of the PDF files:
bash -ci 'if [ `pdftotext "{}" - | grep -ci "$0"` != 0 ] ; then echo "\"{}\"" ; fi ; ' "$1"
xargs replaces both instances of {} with the name of the PDF file; bash replaces $0 with the contents of $1. The command executed by the inner bash instance, then, is:
if [ `pdftotext "<a doc.pdf>" - | grep -ci "<search term>"` != 0 ] ; then echo "a doc.pdf" ;fi ;

The section in backticks (``) is executed first. pdftotext dumps the contents of the PDF in plain text. The text is piped into grep, which counts how many times the search term shows up. If the result is not zero, the name of the PDF, surrounded by quotation marks, is echoed to standard out. The result is a new-line separated list of double-quoted PDF file names.

Finally, this list is piped to the second xargs, which calls acroread for each file. The result is one instance of acroread that has open all files that match the search term.

Sunday, December 25, 2011

Triple-Booting OS X Lion, Ubuntu, and Windows 7 on a Late 2011 MacBook Pro

Introduction

I recently needed to triple-boot a late 2011 MacBook Pro (MacBookPro8,2) with Lion, Windows, and Ubuntu. I wasn't able to find a good guide on how to do this, so this post will try to be that guide. If you are trying to triple-boot a different combination of OSes, there might still be something useful here.

There is a whole lot of advice out there on how to triple-boot, and when you follow it, you find that much of it is incomplete. The main problem is that triple-booting requires what's called a hybrid MBR partition table, and most OS installers and disk tools (as well as people who write tutorials on the Internet) get confused by this. A great place to learn about hybrid MBRs and partition tables in general is Rod Smith's GPT fdisk tutorial. If you get stuck anywhere in this guide, I highly recommend going there. It's long, but it will help you understand what is going on better than I can explain it.

I want to thank joevt (Joe van Tunen) for providing feedback, factual corrections, and additional tips to this guide.

Overview 

In this guide I will walk you through triple-booting one of the new MacBook Pros. Briefly, the steps are:
  • Install Windows using Boot Camp
  • Set up your partitions for Linux and rEFIt
  • Install rEFIt 
  • Install Linux
  • Make it all work
  • Snazz it all up (or not)
There's also a section at the end for when things go wrong.

I am assuming that you have only one physical hard drive in your Mac, the hard drive has only one partition (not counting the hidden Lion recovery and EFI partitions), and the one partition has OS X Lion installed.

I have arranged the steps in this guide into short instructions followed by longer explanations of what is going on and why. Hopefully this makes it more readable.

Warnings

Before I get to the guide, some warnings are in store:

Warning 1: This is not for the faint of heart. You will have to use the command line. You will probably have to improvise somewhere along the line if your configuration isn't exactly like mine. There's a good chance that something will fail, you will have to reformat your drive, and start from scratch.

Warning 2: This is not something you want to do after a long day at work. This is something you might do on Saturday if the workweek hasn't been grueling enough for your taste.

Disclaimer: This procedure worked for me, but I cannot guarantee that it will work for you. This procedure is not supported by Apple. I am not a lawyer or an IT professional, and I cannot advise you on what the legal or technical ramifications of this procedure might be. You undertake this procedure completely at your own risk. I will not be held liable for any broken hardware, or any other loss on your part. Keep in mind that you are reading this on the internet, and act accordingly.

Hope: With all that said, triple-booting happens in software and should not affect your warranty or break your hardware (see #19 below for one possible exception). If something goes wrong, you can reformat and start over. I'm confident that most people who are interested in triple-booting can pull it off, though it will take some elbow grease. Now to the guide itself.

What you will need

At least two USB memory sticks of at least 1 GB each
A blank CD or DVD (rewritable is fine)
Windows 7 install DVD (I used Windows 7 Professional)
An Internet connection
An Ubuntu 10.10 or earlier install CD (you can upgrade after installing; more on this later)
A USB stick with the same version of Ubuntu on it (more on this later)

Before you begin

1. Back up all your stuff onto an external hard drive
Strictly speaking, this is optional, but there is a good chance you will lose the contents of your hard drive.

2. Create a system restore point
Again, this is optional, but very useful if things go bad. This step partially overlaps with #1. The idea is that when things go south, you can restore your OS from a local backup rather than downloading it again from Apple.

You could use Apple's Time Machine running on an external hard drive for this. A more portable option is to use Disk Utility to back up to a disk image. Apple has good instructions here. Note that even though only Leopard and Snow Leopard are listed, the procedure is the same for Lion. The one difference is that Lion will use the recovery partition or a recovery USB stick rather than an install CD.

3. Create a Lion recovery USB stick
Download Apple's Lion Recovery Disk Assistant from here and use it to make a recovery USB stick.

If you don't do this, and something happens to the hidden recovery partition on your hard drive, you will have to boot your Mac over the Internet from Apple's servers. I haven't tried it myself, but it sounds painfully slow.

4. Download and install GPT fdisk from here
This is one utility I've found that handles hybrid MBR partition tables well. This tool provides the special sauce to make the triple-boot work.

5. Download but do not install rEFIt (here)
rEFIt is the most common boot loader used on Macs. It lets you choose into which OS you want to boot. The problem is that currently, rEFIt is one of the tools that seems to get confused by the hybrid MBR, so you need to be careful with what you let it do. I recommend downloading the Mac disk image.

6. Download Ubuntu 10.10 or earlier (from here for example)
You probably want the 64-bit version of Ubuntu. It's called AMD64 because AMD developed the 64-bit extension to x86. It will run just fine on Intel.

You need an Ubuntu 10.10 (Maverick Meerkat) or earlier .iso file. As of this writing, there is a bug in newer versions of Ubuntu (11.04, 11.10) that causes the installer to overwrite your partition table whether you want it to or not, even when you install using the advanced options (see this). Once you've installed 10.10, you can upgrade to the latest and greatest with no problems. Another way to get around the bug might be to fix your partition table manually, but I haven't tried this.

7. Create an Ubuntu install CD
For some reason, Macs don't really like booting from USBs, so burn your Ubuntu .iso file to a CD using Disk Utility.

Edit: joevt elaborates: "Some Macs don't boot legacy OS's (OS's that boot using BIOS such as Windows and Linux) from USB because their EFI doesn't have a BIOS that supports booting from USB or FireWire. Even on Macs that do support it (such as the MacBook Air which doesn't have a built in CD drive) it may not work if the startup disk already has a legacy OS installed (Boot Camp). I haven't experimented with those computers so I'm not 100% sure about that. Note that all Macs can boot EFI OS's (Mac OS X) from USB or FireWire without problem."

8. Create an Ubuntu install USB stick
Yes, you read that correctly. Ubuntu gets confused when loaded from a CD, and needs to also have a USB stick present. Ben Stones describes this bug and how to make an Ubuntu USB stick here. 

Now on to the good stuff.

Setting Up Triple-Booting 

9. Install Windows using Boot Camp
Use the Boot Camp Assistant that comes with OS X (it's in /Applications/Utilities) to install Windows. The wizard makes this a cinch. If you've got a spare USB stick lying around, you can download the Apple drivers now, but you can also skip this and do it later. When you choose how big to make your Windows partition, leave enough space on the Macintosh HD partition for Linux. After this point, the Windows partition size will be set in stone, but you will need to take chunks out of the Macintosh HD partition. Keep in mind that OS X now reports disk sizes in GB (1 GB = 1000^3 bytes), but Windows reports disk size in GiB (1 GiB = 1024^3 bytes), so the Boot Camp partition will look a little bigger in OS X than in Windows.

Then just follow Boot Camp's instructions for installing Windows. After Boot Camp restarts the computer and the Windows installer loads, make sure you tell Windows to install on the right partition. In the advanced settings, format the partition to NTFS.

Once Windows is installed, reboot a couple of times to make sure both OS X and Windows work (hold down option (aka alt) during startup to choose the OS). Don't worry about installing Apple's Windows drivers or authenticating Windows now; if something goes wrong down the line, you might have to reinstall Windows.

I recommend using Boot Camp because it's a painless way of letting Apple set up a hybrid MBR for you. There is probably a way to do the same thing with GPT fdisk, but I haven't tried it.

Edit: A tool such as iPartition could replace Disk Utility and GPT fdisk, and allow you to resize your partitions after they're created. I haven't used iPartition myself.

This is a good time to give a quick overview of some acronyms and explain what a hybrid MBR does. I've listed the confusing acronyms in the table below. Older computers use BIOS to interface with the hardware. Intel-based Macs use a newer standard called EFI, and the latest PCs use a successor to that called UEFI. Older computers split their hard drives into partitions using MBR, and newer computers sometimes use GPT. The problem created by booting OS X and Windows on the same machine is that OS X only (officially) supports running on an EFI machine on a GPT hard drive. Windows, on the other hand, traditionally works on a BIOS machine with an MBR hard drive, and can only run on a GPT drive when running on a UEFI machine. In other words, OS X wants to see GPT, and Windows wants to see MBR. A hybrid MBR is a way of making both happy. I'll come back to this in step #12.


Old New Newer
Firmware Interface BIOS EFI UEFI
Partition Table Master Boot Record (MBR) GUID Partition Table (GPT)

10. Create a backup of your partition table using GPT fdisk
If something goes screwy with the partitions in the next few steps, this is a good place to come back to. Open Terminal and run GPT fdisk with $> sudo gdisk /dev/disk0. If, for some reason, your hard drive is not disk0, replace 0 with the right number. I can't imagine why it would not be 0; you can check by running Disk Utility, selecting your internal hard drive, hitting <command>+i, and checking the disk identifier field.

In GPT fdisk, choose option b, and type the full path to where you want the backup. If you're really paranoid, you can put this on an external drive, but I don't think it's worth the trouble. Then exit with option q.

Edit: joevt suggests the following sanity check between changes to the partition table to make sure it has actually changed. I didn't do this myself, and interpreting the output is a little beyond me.
$> diskutil list
$> sudo fdisk /dev/rdisk0
$> sudo gpt -r show -l disk0
$> sudo gpt -r show disk0
$> sudo dd if=/dev/rdisk0 skip=0 count=1 | xxd
$> sudo dd if=/dev/rdisk0 skip=# count=1 | xxd
# = first block of a partition

11. Create partitions for Linux and rEFIt
In Disk Utility, create three new partitions from Macintosh HD and call them whatever you like (select your hard drive -> click the partition tab -> select Macintosh HD -> click the + button, and use the fields on the right to define settings). Do not touch the BOOTCAMP partition. The first new partition is for rEFIt. It needs to be formatted to "Mac OS Extended (Journaled)". Make this at least 12MB (Disk Utility doesn't seem to allow anything less than 1.07GB; a third-party tool might give more flexibility). The next two partitions are for the Linux swap drive and the main Linux drive. There are various opinions on the Internet on how big your Linux swap space should be. I made mine a bit bigger than the amount of RAM I have installed; you can make up your own mind. Make the Linux partition as big as you want it. Both of the Linux partitions should be formatted to FAT32 (aka “MS-DOS (FAT)” in OS X parlance).

The order of your partitions should be as follows:
  1. Macintosh HD
  2. rEFIt
  3. Linux swap
  4. Linux
  5. BOOTCAMP
The relative order of the Linux partitions shouldn't be important, but the rEFIt partition must come right after Macintosh HD. It doesn't really matter what you name the partitions, as long as you can remember what's what. When you are happy with the sizes of the partitions, click “Apply.” Disk Utility will warn you that it's dangerous to modify a drive with Boot Camp on it. We know this, so just go ahead and apply the changes.

Do not stop here. Do not restart your computer. Go straight to # 12.

12. Fix the partition table
The hybrid MBR partition table needs to be recreated after repartitioning in #11. The following is based on the hybrid MBR section of the GPT fdisk tutorial, so take a look at that if something doesn't quite make sense.

As in #10, run GPT fdisk with $> sudo gdisk /dev/disk0. Then enter the “recovery and transformations” section with r. Display your current partition table with p. If you've followed everything up to now, you should see seven partitions:
  1. EFI System Partition
  2. Customer (the main OS X partition)
  3. Recovery HD (the OS X system recovery tools)
  4. The rEFIt partition
  5. The Linux swap partition
  6. The Linux partition
  7. The Boot Camp partition.
Type h to create a hybrid MBR. GPT fdisk warns you that hybrid MBRs aren't the best of technologies, but that's just something you have to live with if you want to dual- or triple-boot. Follow GPT fdisk's simple prompts to create the hybrid MBR: Choose the final three partitions (5, 6, 7) to place in the MBR. Say yes (Y) to placing the EFI GPT partition first in the MBR. Make the Linux partitions (5, 6) hex codes 0c, and set the boot flag on the main Linux partition. Make the Windows partition hex code 07. When you've gone through the prompts, you can hit o to see the MBR you just created. Then use w to write out the results and quit.

As in #10, create another backup of your partition table, just in case. Don't restart, here but continue on to the next step.

This is a good time to explain briefly what a hybrid MBR actually is. As stated in #9, OS X wants a GPT (new style partition table), and Windows wants an MBR (old style partition table). A hybrid MBR is just a hack that makes a GPT (new) look like an MBR (old) to something that isn't aware of GPT (new). One of the limits of MBR is that it only supports four partitions, so a hybrid MBR hides everything that we don't want the MBR to see under a single protected region. In other words, GPT sees this:
  1. EFI System Partition
  2. Customer
  3. Recovery HD
  4. rEFIt
  5. Swap
  6. Linux
  7. Windows
But MBR sees this:
  1. Don't touch
  2. Swap
  3. Linux
  4. Windows
This is why it is so important to cluster all the GPT-related partitions together—that way they can be considered to be one protected partition by the MBR. You can see this information using the p and o options in the GPT fdisk r menu.

It should theoretically not be necessary to place the two Linux partitions in the MBR, and instead they could be put under the protective partition. I could not get this to work, however.
It should theoretically not be necessary to place the swap partition in the MBR; the main Linux partition needs to be there as Linux is booted through BIOS. With some juggling, this could make it possible to place the Macintosh HD into the MBR and allow you to access it from Windows using Apple's HFS+ drivers. I have not tested this, however.

13. Install rEFIt onto the rEFIt partitions
This is based on the instructions here. Copy the “efi” directory from the rEFIt disk image to your rEFIt partition. Then run
$> cd /Volumes/<your_rEFIt_partition/efi/refit
$> ./enable 

Do not use the rEFIt installer. This seems to break the partition table.
Do not use any of the other rEFIt utilities. rEFIt comes with gptsync, which, as of this writing, doesn't handle hybrid MBRs well. Other bundled utilities might also break things.

You should now be able to boot into both OS X and Windows through rEFIt. Try it. Restart while holding down option (aka alt), and when your boot disks come up, choose your rEFIt partition. The rEFIt menu should load and let you choose between OS X and Windows. If something doesn't work at first, try rebooting once or twice. If it still doesn't work, then something is wrong.

By default, the rEFIt menu will give you access to gptsync. Do not use this tool.

Edit: The downside of this approach is that it bypasses the rEFItBlesser script, which is used to make sure the computer always boots into rEFIt and not straight into OS X. As a result, an OS X update could make the computer automatically boot OS X rather than rEFIt. In this case, you will need to repeat #21 below or set up rEFItBlesser manually. In some older Macs when not using rEFItBlesser, waking from safe sleep (aka hibernation) apparently caused the rEFIt menu to appear. I have verified that this is not the case for the MBP 8,2 hardware.

14. Install Linux (part 1: loading)
Reboot, holding down the option key. Then pop in your Ubuntu CD and USB stick and wait for the CD to show up in the list of boot devices. Once it shows, select the rEFIt partition. rEFIt should now show a CD menu item (or several). Pick one of the CD items, and hopefully the Ubuntu installer will load after some time.

There shouldn't be a difference between booting directly from the Ubuntu CD and booting from the Ubuntu CD by first going through rEFIt, but I haven't actually tested this. (joevt confirms)

For whatever historical and technological reason, the Ubuntu CD can be recognized as two or three boot devices. I wasn't able to figure out just what the difference among them is. When booting, pick the first one, and if something doesn't work, try again with the second, and so on.

If you get an error message saying that Ubuntu cannot find a medium containing a live file system, then you've run into the problem that the Ubuntu USB stick is meant to solve.

15. Install Linux (part 2: installing)
Follow the Linux install wizard to install Linux. This step is roughly based on the instructions here.

Choose the option to set up your partitions manually. In the list of partitions, choose your Linux and swap partitions in turn, and set their options respectively. For the main partition, set the mount point to / and format it to Ext3. You could try Ext4. When I tried, Ext4 didn't work, but that was likely a result of something else I did wrong.

Make sure you set the location of the boot loader to your Linux partition (/dev/sda#) and not the root of the drive. We don't want Ubuntu to control the entire boot process.

16. Fix the partition table (again)
Once you've installed Linux, you might need to fix the hybrid MBR again as in #12.

17. Test that it works
You should now be able to do the following:
  • Boot while holding the option key to get a choice among booting into OS X, the system recovery partition, rEFIt, or "Windows." The "Windows" option will boot the most recently used BIOS-based OS (either Windows or Linux).
  • If you choose rEFIt, there should be options for booting OS X, Linux, and Windows.
  • If you boot Linux, you'll get a GRUB menu allowing you to boot Linux, Linux recovery, Windows, OS X, and a memory test. I do not know whether booting OS X from GRUB works. After getting everything to work, I didn't really want to try just to find out that it broke everything. GRUB will happily boot Linux or Windows. It sees 32-bit and 64-bit versions of OS X, but it is not able to boot these.
18. Run updates
Run the built in updaters on Windows and Ubuntu. In Ubuntu, you can upgrade to the latest release if you so desire. This should not have any negative impact on the triple-boot setup.

19. Install drivers
If you haven't done so already, use the Boot Camp Assistant (in OS X) to download Windows drivers onto a USB stick, boot into Windows, and install them.

Linux drivers are a bit more complicated, but a good place to start is here. You will probably need to look at support pages for older hardware and older releases. This is the only place where you could potentially do some permanent damage if you accidentally put a bad driver on the wrong hardware. I'm not an expert on this, though.

Adding some polish 

20. Configure rEFIt
Open the efi/refit/refit.conf file on the rEFIt partition with your text editor of choice and look through the options. They're quite well documented in the comments. I recommend changing the timeout value to something small so the computer doesn't sit in rEFIt for too long. I strongly recommend removing the tools from the menu so you don't accidentally run gptsync and break your partition table.

21. Decide how you will normally boot
In the Startup Disk section of OS X preferences or in the Boot Camp application on Windows, you can choose the default startup disk (OS X, Windows, rEFIt). Note that for me, rEFIt only shows up on the Windows side. If you choose the rEFIt partition as the startup disk, you'll get an OS choice every time. Otherwise, you can boot into OS X or Windows by default. Also note that the Windows option will actually boot Windows or Linux, depending on which was booted most recently.

If you manage to get rEFItBlesser working (beyond the scope of this guide), it will make sure you're always booting into rEFIt.

Edit: There is an open bug with booting into Windows 7 that causes the display brightness controls to not work in some circumstances. See here for details.

22. Clean up your OS X desktop
By default, OS X will mount the Macintosh HD, as well as the rEFIt and Boot Camp partitions. It doesn't mount the two Linux partitions because it doesn't understand them. You can follow the steps here to stop OS X from mounting these two partitions. You can still mount them through Disk Utility. I recommend against touching the rEFIt partition just in case, and the Windows partition is of minimal use in OS X because OS X can only read from NTFS.

Note: If you are using rEFItBlesser, then you will need allow the rEFIt partition to mount automatically.

Note: There are third-party drivers for getting read-write access to NTFS and ext* filesystems, but I haven't used these.

23. Clean up the GRUB menu
I've posted tips here for cleaning up the GRUB 2 boot menu.


If something goes wrong 

If you're reading this section, then something bad probably happened that you weren't expecting. Here are a couple of ideas on what to do, but if you can think of something better, go ahead and try that as well:

1. Revert to your previous working partition table
If you made a backup of your partition table before things broke, use GPT fdisk to revert to it. Run GPT fdisk, enter the recovery menu with r, and load the previous table with l. This can help if something like the Ubuntu installer or something in rEFIt broke something. Then continue from the step right after the one where you made the backup.

2. Delete all extra partitions and try again
In OS X, open Disk Utility and delete all the partitions you've created, leaving just Macintosh HD. Resize Macintosh HD to take up the full disk. Then start over. If you've just got a Boot Camp partition, you can use the Boot Camp Assistant to remove it.

The first time I tried to triple-boot, I managed to break things so badly that Disk Utility wasn't able to put the partitions right. Steps #3 and #4 below can help in this situation.

3. Use the recovery partition
If using Disk Utility inside OS X isn't working, you can boot from the recovery partition or your recovery USB stick and open Disk Utility from there. Then, you can format the Macintosh HD partition and restore from the image you created in step #2 of the guide.

4. Do a clean reinstall
If things are still broken, you can use the recovery partition or USB stick to download and completely reinstall OS X. The download might take a while.

5. Last resort
On booting up, it's possible to start your computer up from Apple's servers over the Internet and do a reinstall that way. I haven't tried this, though.

Concluding remarks
 
In the guide above, I've tried to explain in detail how to triple-boot a late 2011 MacBook Pro. I haven't written about security considerations, GRUB configuration, Ubuntu drivers, etc. I'm hoping to post about these as I have time.

There are some obvious limitations to triple-booting. By running three operating systems, you're opening up your computer to many more attack vectors. Full disk encryption should be possible for some or all operating systems, but it adds another level of complexity. In the setup I've described, there's no partition that's visible to all OSes, so sharing data becomes difficult. Ubuntu can access both OS X and Windows, and OS X can read from the Windows partition, but Windows is completely clueless. Beyond these limitations, I've been triple-booting for some time now, and haven't had any other problems.



Have you followed this guide? Did it work for you? Is something not clear or do you have something to add? Leave some comments below.