Configure outgoing email from FreeBSD with sendmail

When you’re setting up a new host, sometimes it’s tricky to get outgoing email working right. I noticed that there isn’t a good guide for stock FreeBSD (except “install ssmtp instead“) so I wrote up some simple notes. I assume your system is connected to the Internet, including DNS, and your main goal is to get outgoing mail like cron job output sent offsite. You have your own domain name but use split DNS so internal hostnames are of the form “myserver.local”.

Assuming you’re on a private IP network (such as 10.* or 192.168.*), use a local hostname such as “myserver.local” in /etc/rc.conf or setup internal DNS. You can test it resolves via “nc myserver.local”. You’ll want to set an alias for root in /etc/mail/aliases. Let’s say you used “admin@example.org” here. The corresponding db file won’t be rebuilt unless you also type “make” in /etc/mail, but we’ll be doing that below.

Now copy the stock .mc files to your own local copies:

cp freebsd.mc ${HOST}.mc
cp freebsd.submit.mc ${HOST}.submit.mc

To rewrite the “From” domain to match your real domain, add the following to ${HOST}.mc:

MASQUERADE_AS(`example.org”)
FEATURE(`masquerade_envelope’)

This means mail from “user@myserver.local” will appear to come from “user@example.org” instead. The one exception is the root user, which is typically not rewritten. But if your goal is to capture cron output, root is the user you want to rewrite.

Unfortunately, the default for this is buried in a m4 file. You’ll have to edit /usr/share/sendmail/cf/domain/generic.m4. Make a backup if you’re concerned. Comment out the below line by adding “dnl” in front of it like this:

dnl # EXPOSED_USER(`root’)

Now “root@myserver.local” will become “root@example.org” as well. The final step to make this new configuration active is to run “make install” in /etc/mail. This will create your new /etc/mail/sendmail.cf from the appropriate files. You can restart sendmail with “make restart”.

The above approach is needed to avoid exposing the private domain “myserver.local” in the email headers since many remote servers will reject mail coming from a domain that doesn’t resolve. If you have a central host that does all this rewriting for you, you can just forward the mail to it for handling by the SMART_HOST directive in ${HOST}.mc.

All about ACPI

Up until recently, I was the maintainer for the FreeBSD ACPI implementation.  ACPI is a standard for making features like power management, which were originally in the BIOS, available to the OS to enumerate and control.  I implemented the FreeBSD CPU frequency control framework and drivers for individual CPUs, as well as numerous bugfixes and updates to support new BIOS versions.  I wanted to share my perspective on ACPI, as well as provide resources for other open source developers interested in getting involved in this obtuse area of PCs.

ACPI is a complex, 600-page standard.  It assumes the reader has a lot of low-level knowledge about PC hardware and the BIOS.  In the past, the BIOS would be the first thing that started on the PC.  First, it would configure peripherals like PCI slots and boards.  To retain control, it would hook the system management interrupt (SMI) before booting the OS.  The SMI was tied to the actual hardware by the OEM, say by linking a laptop’s lid switch to a microcontroller.  The BIOS had hard-coded event types and logic to process them (“if lid switch pressed, turn off backlight”).  The nice thing was that the OS was completely unaware of the BIOS since the SMI is mostly invisible to software, so it could run on all PCs without changes.  The downside was that the user had to go into the BIOS settings to change things and the BIOS had to be relatively complex in order to coexist with the OS.

In the ACPI model, the BIOS (or EFI now) still performs basic initialization.  After the hardware is setup, it hooks the SMI.  The difference is that it now provides a set of tables in RAM for the OS to consume.  While most of the static tables describe the hardware, the most important one (“DSDT”) provides bytecode called AML.  The OS sets up its interpreter very early in boot process and loads the BIOS’s AML.  The AML is composed of methods and data types and is arranged in a tree that matches the logical arrangement of devices.  For example, methods related to a video device would be located under the AML Device object for its parent PCI host interface.

The OS walks the AML tree, initializing the various devices and assigning resources to them using AML and device-specific methods.  Usually, the OS keeps a mapping between its internal device driver tree and the handle to the AML node that shadows it.  This allows it to later call methods under that node that change the power level or configure its wake capabilities.  For example, you want the OS to power down an internal modem if it’s not in use.  This is done by calling AML methods for the Device node that represents the modem.

The OS interoperates with ACPI this way constantly.  The OS calls into AML (or vice versa via an interrupt) to power up/down devices, change backlight settings, change CPU frequency/voltage, or suspend/resume the system.  While this level of control is nice to have as an OS developer, there have been a lot of bumps along the way.

ACPI could be seen as an attempt by Microsoft and Intel to take control over areas formerly owned by Phoenix/AMI and the numerous Taiwan integrators that actually build systems for companies like Dell.  They had arguably good reasons for doing so, including the support cost of working around so many BIOS bugs.  The conspiracy theorists may think that this was an attempt by Bill Gates to undermine Linux, but the pain that ACPI caused has been also borne by Microsoft.  Gates never really got his proprietary extensions to ACPI, but Windows did enjoy a privileged position of OEMs using it as the validation suite for their BIOS implementations.  Because there was no open interoperability testing, the spec was so complex, and information about the low-level BIOS and hardware were tied up in NDAs, open source kernels suffered many compatibility problems as new PCs appeared.  The process definitely should have been more open and seems to be getting better, largely due to the efforts of Intel with Linux.

If you’re interested in learning more about ACPI, I recommend the following resources.  The papers and talks are the best introduction, and I haven’t read the book yet.  I hope this helps the open-source community improve support for ACPI.

Papers and talks

Specs

Web

FreeBSD 7 upgrade experience

I recently upgrade my laptop to FreeBSD 7 in anticipation of the upcoming 7.0 release. This should be a major advance with new features such as ZFS and increased scalability due to improvements in the ULE scheduler. It went ok overall with a few important changes to note.

First, don’t use make delete-old-libs until you’ve updated all your ports. That article also includes a script for figuring out what’s no longer used. There was a bump in major version numbers for all libraries when symbol versioning was enabled, so you’ll get lots of “not found” errors for third-party applications if you run this before upgrading your ports. If this happens, all is not lost. You can continue running by symlinking most libraries to their new versions:

	ln -s /usr/lib/libc.so.7 /usr/lib/libc.so.6

Next, there are some changes to the Intel wireless drivers. The iwi-firmware-kmod port is no longer needed now that the firmware is included in the base kernel. You just have to set a tunable to agree to the license:

	legal.intel_iwi.license_ack=1

And load the various firmware files via /boot/loader.conf:

	iwi_bss_load="YES"
	iwi_ibss_load="YES"
	iwi_monitor_load="YES"

For more information, see the iwi man page. With these changes, my system again works fine. Now I need to look into fixing some acpi problems.

For those of you looking for more security and crypto posts, you won’t be disappointed with my next series.

FreeBSD ACPI on a Panasonic Y4

The Panasonic R/W/T/Y series is a set of ultralight notebooks, also available in a US model. I like the Y4-Y7 for their large screen, light weight, and long battery life.

There are a couple things needed to get suspend/resume working on these models in FreeBSD. To get the backlight on and video working again, we need to trigger the 0xc000 video BIOS reset. Set the following in /etc/sysctl.conf:

hw.acpi.reset_video=1

The built-in mouse is stuck once we resume. We need to reinitialize it by setting the following in /boot/loader.conf. This should really be done automatically since the reinitialization should work on most systems. But more testing will have to be done before that is enabled by default.

hint.psm.0.flags="0x2000"

With these changes, I can suspend/resume to RAM successfully. For more info, check the handbook.

GPG now requires pinentry package

As a FreeBSD committer, I also run FreeBSD on a lot of my machines. I recently upgraded my desktop with portupgrade and found that gnupg no longer worked. I got the error message:

gpg-agent[13068]: can’t connect server: `ERR 67109133 can’t exec `/usr/local/bin/pinentry’: No such file or directory’
gpg-agent[13068]: can’t connect to the PIN entry module: IPC connect call failed
gpg-agent[13068]: command get_passphrase failed: No pinentry
gpg: problem with the agent: No pinentry

I found these two articles and noticed that my gpg had been upgraded from the 1.x to 2.x series. The 1.x gpg had an integrated password entry prompt but 2.x requires an external package. This can be fixed by installing the security/pinentry port. I’m not sure why it wasn’t marked as a dependency for gpg2.

Reverse engineering with a VM

In a previous comment, Tim Newsham mentions reverse engineering an application by running it in a VM. As it so happened, I gave a talk on building and breaking systems using VMs a couple years ago. One very nice approach is ReVirt, which records the state of a VM, allowing debugging to go forwards or backwards. That is, you can actually rewind past interrupts, IO, and other system events to examine the state of the software at any arbitrary point. Obviously, this would be great for reverse engineering though, as Tim points out, there haven’t been many public instances of people doing this. (If there have, can you please point them out to me?)

An idea I had a few years back was to design a VM-based system to assist in developing Linux or FreeBSD drivers when only Windows drivers are available. The VM would be patched to record data associated with all IO instructions (inb, outb, etc.), PCI config space access, and memory-mapped IO (a “wedge” device.) It would pass through the data for a single real hardware device. To the guest OS, it would appear to be a normal VM with one non-virtual device.

vmreveng.png

To reverse engineer a device, you would configure the VM with the bus:slot:function of the device to pass through. Boot Windows in the VM with the vendor driver installed. Use the device normally, marking the log at various points (“boot probe”, “associating with an AP”). Pass that log on to the open source developer to assist in implementing or improving a driver.

A similar approach without involving a VM would be to make a Windows service that loads early and hooks HAL.DLL as well as sets protection on any memory mappings of the target device. Similar to copy-on-write, access to that memory would trigger an exception that the service could handle, recording the data and permitting access. This could be distributed to end users to help in remote debugging of proprietary hardware.