An mdo(1) introduction

This post takes a quick look at a recent addition to FreeBSD: mdo(1). The mdo(1) utility allows one user to execute a command as another user. In that sense it is similar to the doas(1) program from OpenBSD and at the same time mdo(1) has noticeable differences when compared with doas(1).

kldload

The mdo(1) utility depends on the mdo policy – and the policy must be loaded into the kernel before we can use mdo(1) from the command line. The mac(4) man page provides some larger context about the Mandatory Access Control (mac) framework:

##
# Enable mac_do(4) policy
root@freebsd# kldload mac_do

The policy can be loaded into kernel at boot time by updating /etc/rc.conf through the sysrc(8) utility. This change will make the policy persistent across reboots:

##
# Enable mac_do(4) policy at boot
root@freebsd# sysrc kld_list+=mac_do

sysctl

A rule defines which user or group members can execute a command as another user. Rules are stored as a comma-separated list and can be retrieved or modified via sysctl(8) under the security.mac.do.rules node.

If we were to draw a comparison with doas(1) then security.mac.do.rules would be roughly equivalent to the doas.conf configuration file but it is neither a direct equivalent nor as feature-rich as doas.conf.

A rule has a left-hand side and a right-hand side, separated by the : character. The left-hand side describes the user id or group id that is allowed to run commands as another user, and the right-hand side describes the target user id. Let's look at some examples:

##
# Permit alice to run commands as bob
root@freebsd# sysctl security.mac.do.rules=uid=$(id -u alice):$(id -u bob)

##
# Permit members of the beatles to run commands as bob
root@freebsd# gid=$(getent group beatles | awk -F: '{print $3}')
root@freebsd# sysctl security.mac.do.rules=gid=${gid}:$(id -u bob)

##
# Permit alice to run commands as anyone
root@freebsd# sysctl security.mac.do.rules=uid=$(id -u alice):any

mdo

With rules and everything else in place, the user alice can run commands as bob through the mdo(1) utility:

##
# Launch firefox as 'bob'
alice@freebsd$ mdo -u bob /usr/local/bin/firefox