I Am Joe’s Blog:

August 7, 2007 • 2:14 PM

Safe Sleep addendum

My article in last week’s issue of TidBITS, Stewing Over Safe Sleep, generated an awful lot of feedback. Most of it was of the “Yeah, that was really stupid of Apple” or “Thanks; now I know how to solve an annoying problem” varieties. Some of it was along the lines of “How could anyone not love safe sleep?” or “I’m not seeing 49-second delays on MY machine” or “It probably doesn’t really matter if you move your computer while the RAM is being cached to disk” or the simple and elegant “You’re an idiot.” Well, thanks one and all for sharing your thoughts, constructive and otherwise.

Two particular threads of discussion, though, are worth a more detailed look.

Hibernating Only When Necessary First, Greg Nicholson sent me a clever script he wrote (to replace the one I showed in TidBITS) that’s significantly smarter. Greg pointed out that there are certain situations, such as a long flight to China, in which one might be much more likely to want the default Safe Sleep behavior. So his script, which he runs every 10 minutes with cron, checks the battery life. If it’s over 50%, it turns off hibernatemode (as my script does). But if the charge is less than 30%, it turns hibernatemode back on. Very spiffy, and I wish Apple would have built something like this right into Mac OS X. You can, of course, tweak the percentages and so on to your liking. Here’s (my slightly modified version of) Greg’s script:

MODE=`/usr/bin/pmset -g | grep hibernatemode | awk '{ print $2 }'`
LEFT=`/usr/bin/pmset -g batt | grep Internal | awk '{ print $2 }' | awk -F % '{ print $1 }'`

if [ $LEFT -lt 30 ] && [ $MODE != 3 ] ; then
     echo "Less than 30% remains" >> /var/log/system.log
     echo "setting Hibernate mode 3" >> /var/log/system.log
     `/usr/bin/pmset -a hibernatemode 3`
elif  [ $LEFT -gt 50 ] && [ $MODE != 0 ]; then
     echo "Greater than 50% remains" >> /var/log/system.log
     echo "Setting Hibernate mode 0" >> /var/log/system.log
     `/usr/bin/pmset -a hibernatemode 0`
     `rm /var/vm/sleepimage`

Greg noted that since the script requires root privileges, you need to add the following to your sudoers file:

ALL ALL=(ALL) NOPASSWD: /usr/bin/pmset -a hibernatemode 3
ALL ALL=(ALL) NOPASSWD: /usr/bin/pmset -a hibernatemode 0

An easier way to achieve that effect would be to put the cron job in your system crontab, if you feel comfortable doing that.

Dealing with an Unencrypted “sleepimage” file Correction (08-Aug-2007): I see I munged some of my facts here earlier, so I’ve rewritten this paragraph to reflect what I currently believe to be the truth.

Second, the issue of encryption came up. It turns out that using hibernatemode values of 5 or 7 (the prescribed values for those using Secure Virtual Memory) don’t actually result in your sleepimage file being encrypted—in fact, it’s just the opposite. If you have Secure VM turned on and use 5 or 7, your encrypted RAM is apparently decrypted while being written to the sleepimage file. So if you’re using Secure VM and want your sleepimage file, too, to be encrypted (which you should), stick with values of 1 or 3 (3 being the default).

Now, in the real world, this fact probably makes little practical difference for most people, most of the time. Even if you don’t encrypt your VM, it’s not a given that any particular password (or other sensitive data) will actually be in RAM when it comes time for your computer to sleep—it might be, or it might not, depending on a long list of details about how particular programs do things, how recently you logged in, what applications you have running, and so on. And also, the risk is certainly greater for power users who enter an administrative password multiple times per hour than people for whom that is a rare occurrence. Even then, the contents of your RAM is cached to that unencrypted disk image only when your computer goes to sleep and only when the hibernatemode setting is at its default (3) or “always hibernate” (1). And even then, the fact that potentially sensitive stuff is sitting on your hard disk in a readily readable format only causes problems if someone gets access to your computer and knows how to find this data. So, like I say, not a problem for most people, most of the time.

If you’re concerned about this, though, DO follow my advice to turn of Safe Sleep. But go a step further. Instead of using

sudo rm /var/vm/sleepimage

to delete the RAM cache, use the secure version of rm, srm, and use the -m flag for a 7x overwrite rather than the default 35x overwrite:

sudo srm -m /var/vm/sleepimage

The command will take a long time to run, but the disk image holding your RAM contents will be safely overwritten. Note that you only have to do this the first time. If you’ve set up a script (as discussed previously) to check regularly to see that hibernatemode hasn’t turned itself back on, having a simple rm in that script will do the trick. The reason? When hibernatemode turns back on, Mac OS X recreates the sleepimage file immediately. But initially, it’s blank. It doesn’t fill up with the contents of your RAM until your machine tries to go to sleep. If your script runs and deletes the (blank) image before then, nothing incriminating will have been in that file.

I truly hope this all gets sorted out in Leopard.