Linuxulator ist kaputt

Since a few weeks I’m running RELEASE on a custom kernel to use a patch that I made for a missing feature in the IPv6 stack (namely icmp_may_rst).

But a few minutes ago I had the surprise to find that the Linuxulator was no longer working. Trying to run a Linux binary failed with the following error:

ELF binary type "0" not known.
exec: test: Exec format error

Actually looking at kldstat, the Linux kernel module wasn’t even loaded. Trying to load it manually gave me the following error:

link_elf_obj: symbol kern_sched_setscheduler undefined
linker_load_file: Unsupported file type

OK so what is this sched_setscheduler you are talking about? Well there you go!
Now the Linuxulator depends on that syscall, but for some reason the necessary option disappeared from my custom kernel configuration. All I had to do was to add it again and recompile:

options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions

And now I can run Linux binaries again!

Display WiFi RSSI on FreeBSD

On FreeBSD we also use the ifconfig command to configure wireless interfaces. The command ifconfig wlan0 list scan lists available AP along with their SNR. However the ifconfig command does not display the RSSI/SNR on the current link. To do so we need another command, wlanstats. It is not included in base system but you can find it in the source tree under /usr/src/tools/tools/net80211/wlanstats. This command also shows you the signal level (in dBm) and current transmit rate among other things.

I wonder why the RSSI is not visible with the ifconfig command. I suppose they wanted to regroup all those stats with another command. But again I wonder why this command is not part of the base system.

Dedibox serial shell access

If you cannot access the shell on a FreeBSD dedibox from the online.net console, here is a quick tip. Create an alternate root account with csh or tcsh and access ttyu1 on this account instead. That’s almost precisely what the toor account is made for, except that we generally leave the default shell on root.

No idea why sh, bash and zsh are not working through the serial connection, more doesn’t work either, but vi does. Probably a termcap thingy ? If anyone has a clue…

Install FreeBSD 11 with ZFS on Dedibox XC 2016

Online.net’s Dedibox XC 2016 comes with 16 GB DDR3 and 1 To SATA or 250 GB SSD on a 8 cores Atom CPU. This is a very nice entry-level dedicated box for anyone who want to upgrade from a small VPS (yes, there is some upgrade in the air). There is only one HDD and no RAID though. But they offer (for free) a 100 GB FTP storage space which is more than enough to backup the base system and bootstrap it again in case of disk failure.

An advantage of dedicated over VPS is that you can install almost any OS you want. The management console comes with an easy install for FreeBSD 11 on UFS. But I thought it would be nice to use ZFS instead. Yeah, I hear you, why using ZFS with only one HDD and non-ECC memory? But with 16 GB it still comes as a viable alternative.

The method I used was adapted from a post on Online.net’s forum. So here we go. First, reboot in rescue mode from the console. Choose FreeBSD 10.2 (or higher) as the rescue OS. Once you are logged on the rescue, switch to root and bootstrap FreeBSD:


SWAP_SIZE=4g
TEMP_ROOT_PASSWORD="1337rul35"

# Create partitions table
gpart destroy -F ada0
gpart create -s gpt ada0
gpart add -t freebsd-boot -l boot -s 512K ada0
gpart add -t freebsd-swap -l swap -s $SWAP_SIZE -a 1m ada0
gpart add -t freebsd-zfs -l zfs0 ada0

# Install MBR
dd if=/dev/zero of=ada0p3 count=560 bs=512
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0

# Create ZFS pool and FS
zpool create -f -m none -o altroot=/mnt -o cachefile=/tmp/zpool.cache -O compress=lz4 -O atime=off zroot gpt/zfs0
zfs create -o mountpoint=/ zroot/ROOT
zfs create -o mountpoint=/usr zroot/usr
zfs create -o mountpoint=/var zroot/var
zfs create -o mountpoint=/tmp zroot/tmp
zfs create -o mountpoint=/www zroot/www
zfs create -o mountpoint=/usr/home zroot/usr/home
zpool set bootfs=zroot/ROOT zroot

# Bootstrap
cd /mnt
fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/amd64/11.0-RELEASE/base.txz
fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/amd64/11.0-RELEASE/kernel.txz
tar --unlink -Jxpf base.txz -C /mnt
tar --unlink -Jxpf kernel.txz -C /mnt
rm base.txz kernel.txz

# Configuration
# 1) fstab and swap
cat << EOF > /mnt/etc/fstab
ada0p2 none swap sw 0 0
EOF

# 2) rc.conf
cat << EOF > /mnt/etc/rc.conf
keymap="fr.acc"
ifconfig_igb0="DHCP"
ifconfig_igb1="DHCP"
fsck_y_enable="YES"
background_fsck="YES"
zfs_enable="YES"
sshd_enable="YES"
EOF

# 3) loader.conf
cat << EOF > /mnt/boot/loader.conf
zfs_load="YES"
vfs.root.mountfrom="zfs:zroot/ROOT"
boot_multicons="YES"
boot_serial="YES"
comconsole_speed="9600"
console="comconsole"
comconsole_port="0x2F8"
EOF

# 4) TTY for serial console
cat << EOF >> /mnt/etc/ttys
ttyu1 "/usr/libexec/getty std.9600" vt100 on secure
EOF

# 5) Temporary root password
echo "$TEMP_ROOT_PASSWORD" | pw -R /mnt user mod -n root -h 0

# Last step
cd ~
zpool export zroot
zpool import -o altroot=/mnt -o cachefile=/tmp/zpool.cache zroot
cp /tmp/zpool.cache /mnt/boot/zfs

# Terminated!
halt

Now from the management console, reboot in normal mode and connect to your box using serial connection. You should be able to login with root and continue the configuration from there.

FreeBSD 10 on ThinkPad X250

UPDATE:


I’m now using FreeBSD 10-RELEASE on a ThinkPad X250. It’s been quite a while now, and I should have written this long ago. Well… Here we go! Everything works fine except for:

  • Intel Broadwell integrated graphics
  • Intel Wireless 7265
  • Resume/Suspend

For the integrated graphics, the Broadwell architecture is not yet supported [1, 2]. But it works well using VESA at native resolution (1920×1080). I had to tweak the MTTR a little to get reasonable performance. Of course you cannot use your VGA and miniDP anymore. That’s a bummer for giving presentations. To this regard, I still rely on Linux. Also you cannot adjust screen luminosity, it’s always at full power. So if you are in a dark room or a car at night, you will transform yourself into a lamppost.

Here is what I have in my /etc/rc.local for the MTTRs:

memcontrol clear -b 0xc0000000 -l 0x20000000
memcontrol set -b 0xc0000000 -l 0x20000000 -o BIOS write-combine

I also had to force the DPI in /usr/local/etc/X11/xorg.conf.d/dpi.conf

Section "Monitor"
  Identifier "Monitor0"
  Option     "DPI" "96x96"
EndSection

For the WiFi, there is an iwm driver coming in FreeBSD 11 that was ported from OpenBSD. Until recently I used a Ralink RT2500USB card to get it working. But last week, I did a quick and dirty backport for FreeBSD 10, it is available here. This is a fork of the iwm driver before its inclusion in HEAD. It works somewhat. But please keep in mind that I have no clue here. I still have to read more and get into the FreeBSD kernel. And this is a temporary solution while we are waiting for the release of FreeBSD 11.

The driver still crashes when loaded with virtual box modules. Also the channel is currently locked. So if you want to use it, you need to find the correct channel first, select it manually, and then try to associate. There is a small script on the repo to do so.

Use notify-send as root

The automount script is a neat devd based automounter for FreeBSD. Just pkg install automount and all your removable media will mount themselves automatically in /media when you plug them in. It’s very clean. You may also check vumount, a short script that I made to list all removable media and remove the mount point when you unmount them.

It’s possible to configure automount to send a notification to your desktop using notify-send from libnotify. What it does exactly is (as root):

env DISPLAY=:0 notify-send automount "Device '${1}' mounted on '${3}' directory."

Except that it doesn’t work… I started dbus-monitor and tried notify-send as root (from ttyv2) but didn’t receive anything and notify-send did not complain. So I tried to start dbus-monitor from root instead, in the hope that it would be a bit more verbose than notify-send. I got this error message:

Failed to open connection to session message bus: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.

By default DBus sessions are private and don’t accept connections from other users than the one that own the bus, even root. The solution is to configure DBus to allow root on the session bus. Edit /usr/local/etc/dbus-1/session.conf and add this line to the default policy:

<allow user="root"/>

But you still need tell DBus how to connect to the session bus. To do so you have to specify the session bus address in DBUS_SESSION_BUS_ADDRESS. Fortunately automount is a shell script, so you can fetch and export the bus address from its configuration file. Just add this to /usr/local/etc/automount.conf:

# Load DBus session bus address
DBUS_USER=your-user
if [ -d /home/$DBUS_USER/.dbus/session-bus ]
then
  dbus_file=$(ls -t1 /home/$DBUS_USER/.dbus/session-bus | head -n1)
  export DBUS_SESSION_BUS_ADDRESS=$(cat /home/$DBUS_USER/.dbus/session-bus/$dbus_file | \
                                    grep "DBUS_SESSION_BUS_ADDRESS=" | \
                                    sed 's/[A-Z_]*=//')
fi

Data signing failed

I got the following error while trying to send a signed (GPG) e-mail using claws-mail:

Signature failed: Data signing failed, General error

Turns out it was a path problem. The GPG agent uses pinentry to ask for your private key password. The agent was configured with the absolute path to pinentry-gtk-2 on Linux. But this happened on FreeBSD and executables are located in /usr/local, not /usr.

So I changed in ~/.gnupg/gpg-agent.conf:

- pinentry-program /usr/bin/pinentry-gtk-2
+ pinentry-program /usr/local/bin/pinentry-gtk-2

Switch MTA on FreeBSD

As you probably know FreeBSD comes with Sendmail installed as the default MTA. However this may be a bit overkill on a desktop installation where the most you might want is to relay mails to an external address. Luckily it is quite easy to change the default MTA as described in the handbook, see 28.4. Changing the Mail Transfer Agent.

On my Desktop I prefer to install nullmailer. This is a simple MTA replacement for hosts which only relay mails through a smart relay. GNUTLS (SSL) is not enabled by default in the nullmailer package on FreeBSD. So if you want SSL you have to compile the port. This is my case. Let’s install it:

cd /usr/ports/mail/nullmailer
make install clean
(...)
pkg lock nullmailer

The configuration happens in /usr/local/etc/nullmailer. This directory contains multiple files and each one of them focuses on a specific aspect of the configuration.

First we specify the remote SMTP through which our mail shall be relayed, this is the remotes file. This file contains a list of remote servers, the module used to send the message and command-line arguments for that module. Modules are located in /usr/local/libexec/nullmailer. The man page states that you can list available options using --help on each protocol module.

In most cases you want to use the smtp module which takes the following arguments (with SSL enabled):

  • port: SMTP port (25, 465, 587, …)
  • user: SMTP user
  • pass: SMTP password
  • auth-login: LOGIN authentication method (default to PLAIN)
  • ssl: Use SSL/TLS encryption
  • starttls: Use STARTTLS command to initiate encrypted connection
  • insecure: Accept invalid certificates (which I do not recommend)
  • x509certfile: Client certificate file
  • x509cafile: Certificate Authority trust file (default to /etc/ssl/cert.pem on FreeBSD)
  • x509crlfile: Certificate revocation list
  • x509fmtder: Switch from PEM to DER format for the certificates

Here is an example that would relay through relay.example.com:465 using SSL and LOGIN authentication:

relay.example.com smtp --port=465 --ssl --auth-login --user=some-user --pass=some-password

Since this file contains your SMTP password in cleartext, I advise you to:

chown nullmail:nullmail remotes
chmod 600 remotes

Next we edit the name that will be used to construct email addresses on this host. You configure this in the me file. Normally this should be the fully-qualified host name of the computer running nullmailer. This is really useful to distinguish, say root at machine-a from root at machine-b. However some mail providers refuse to relay mails from a different domain name than their own so it might be useful to change this in those cases (I am my own mail provider, so personally I don’t care and do what I want). You also need to configure defaultdomain to your domain name. That is your FQHN minus the hostname. If a mail is sent to an address that is not localhost and does not contain a domain name (no period in the hostname), this domainname will be appended to it.

After that we configure the mail to which all local mails are forwarded. You configure this address in the adminaddr file. And we also configure the file pausetime. This is the interval of time between two queue runs with a default value of 60 seconds. I prefer to set this to a higher value, like 15 minutes.

For more information about the configuration of nullmailer, see this article. Although related to Raspbian on a RPi, it remains mostly the same.

Now we need to replace the MTA on FreeBSD. First we configure the mailwrapper (see man mailwrapper) in /etc/mail/mailer.conf. Replace each line with their nullmailer equivalent, that is:

sendmail  /usr/local/libexec/nullmailer/sendmail
send-mail /usr/local/libexec/nullmailer/sendmail
mailq     /usr/local/libexec/nullmailer/mailq

Time to test. Disable sendmail, enable nullmailer and send a mail. Oh and by the way, tail -f /var/log/maillog in any case:

service sendmail stop
service nullmailer onestart
echo Hello from FreeBSD\! | mailx -s "test" root

If it works, you can now disable sendmail and enable nullmailer in /etc/rc.conf:

sendmail_enable="NONE"
nullmailer_enable="YES"

Where did my PGP keys go?

Today I noticed that one of my PGP private key just disappeared of GPG. The key did not appear when I did gpg --list-secret-keys. After a bit of investigation I discovered that the problem did not affect Linux hosts but only FreeBSD hosts. Weird…

The source of the problem was a migration from GnuPG v2.0 to v2.1. According to this page, GPG does not handle the private keys anymore and delegates all private keys operations to the gpg-agent. Therefore GPG v2.1 migrates the legacy secret keyring, secring.gpg, to the gpg-agent key store, private-keys-v1.d and then forgets about it.

Though, you see, my GPG keyrings were synchronized across all hosts. But the GnuPG package on Debian is still v2.0, while FreeBSD is v2.1. Get the picture?

I synced my keyring on FreeBSD hosts where GPG migrated my private keys to the gpg-agent key store. Then I generated a new key pair on a Debian host, which was added to the legacy keyring. Resynced, but the newer version of GPG didn’t care, they already migrated to the new key store.

Fortunately it was easy to fix, all you have to do is re-import your legacy keyring with one of the newer versions of GPG. The private keys are now also present in the new key store so you can sync to all other hosts.

gpg --import $HOME/.gnupg/secring.gpg
gpg --list-secret-keys