| FuguLib::Privdrop(3p) | Perl Library Manual | FuguLib::Privdrop(3p) |
NAME
FuguLib::Privdrop —
drop root privileges permanently
SYNOPSIS
use FuguLib::Privdrop; FuguLib::Privdrop->drop_privileges(user => '_openhap');
DESCRIPTION
FuguLib::Privdrop implements the privilege
drop an OpenBSD daemon performs once its privileged
work is done: bind the reserved port, fork the helper that needs root, then
give up root for good and run the event loop as an unprivileged user.
The module keeps no state and has a single class method.
drop_privileges
drop_privileges(%args)
switches the process to the given user and group and verifies that root
cannot be regained.
The arguments are as follows:
- user
- Name of the user to become. Required.
- group
- Name of the group to become. Optional; the user's primary group is used if it is omitted.
The method returns immediately if the effective user ID is not 0, so a program that is already unprivileged may call it unconditionally. Otherwise it resolves the user and group, calls setgid(2) before setuid(2), assigns the real and effective IDs, and then confirms both that neither ID is 0 any more and that calling setuid(2) with 0 does not bring root back.
RETURN VALUES
drop_privileges() returns 1 on success,
including the case where the process was already unprivileged. It never
returns on failure.
EXAMPLES
Bind a reserved port as root, then run as _myapp:
my $socket = IO::Socket::INET->new(
LocalPort => 80,
ReuseAddr => 1,
Listen => SOMAXCONN,
) or die "Cannot bind port 80: $!";
FuguLib::Privdrop->drop_privileges(user => '_myapp');
while (my $client = $socket->accept) {
handle_client($client);
}
ERRORS
drop_privileges() dies, rather than
returning a failure indication, when user is missing,
when the user or group cannot be resolved, when
setgid(2) or
setuid(2) fails,
or when the process still holds root afterwards. A privilege drop that half
succeeded is not something a caller can be allowed to continue past.
SEE ALSO
setgid(2), setuid(2), FuguLib::Daemon(3p), FuguLib::Process(3p)
AUTHORS
Dick Olsson <hi@senzilla.io>
CAVEATS
Supplementary groups are not changed. A process that was started as root keeps whatever supplementary groups it inherited, which on OpenBSD is how a daemon retains access to the mdnsd(8) socket after dropping to its own user. Callers that need the groups cleared must call setgroups(2) themselves before dropping.
| July 27, 2026 | OpenBSD |