Setuid is a property of a process, not a module. It's an OS
level thing, not a perl level thing. If an executable is
marked as setuid, the process' effective uid will be that of
the owner of the file (not necessarily root, just whomever
owns it). It's an all or nothing proposition that you can't
really enable for just some code.
If you can't use something like syslog, you could write your
own logging process which listens on a UNIX domain socket (or
a TCP socket if you want to work from multiple hosts) and let
your module send messages to that (of course then you have to
worry about authentication et al yourself).
Another posibility would be to use a wrapper which opens
a write only filehandle to the logfile in question as a
priveledged user, changes uid to the target user's, and then
execs the end script. Set something in the environment to
the filedescriptor they should use and then dup it into a
handle in your module.
# in wrapper . . .
use Fcntl qw( F_GETFD F_SETFD FD_CLOEXEC );
open( LOG, "/path/to/log" ) or die "open log: $!\n";
$ENV{LOG_FD} = fileno( LOG );
my $flags = fcntl( LOG, F_GETFD ) or warn "getfd: $!\n";
fcntl( LOG, F_SETFD, $flags & ~FD_CLOEXEC ) or warn "setfd: $!\n";
$< = $> = uid_to_run_as( ... );
exec "/path/to/real/program", @prog_args
or die "Can't exec real program: $!\n";
# in your module
sub log_it {
local( *LOG );
open( LOG, "<&=" . $ENV{LOG_FD} ) or die "Can't dup log fd: $!\n";
print LOG, "Ack: ", @_, "\n";
}
Update: Added in code to clear close-on-exec flag
so that the descriptor will survive the exec.
|