Drop Process Privileges

sudo tcpdump -Z uses initgroups(3), setgid(2) and setuid(2) to drop the root privileges of its own process.

# code taken from: 
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c

/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
            if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
               setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
                    fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
                        username, 
                        (unsigned long)pw->pw_uid,
                        (unsigned long)pw->pw_gid,
                        pcap_strerror(errno));
                    exit(1);
            }
...
}

The process itself has to call setuid(2). You should also investigate running it inside chroot(8) if you aren't already. As far as I know, there is no way for root to change the uid of another process.

If the reason you are running it as root is to bind ports, I'd suggest running it as a normal user on a higher port and using ipfw(8) on OS X to forward port 80/443/etc to the higher port:

http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx


You can run commands as other users using su:

 su USERNAME -c COMMAND

Will run COMMAND with privileges dropped to USER.


Note that, by default, su will use the target user's shell interpreter to run the command. By contrast, the default behaviour of sudo is to treat the COMMAND as a standalone program, that is run the current environment. Of course these default behaviours can be changed with various switches and environment variables.