#!/usr/bin/perl # # runForward # # This is no longer vulnerable to a race condition. # Uses sysopen to avoid symlink open attack, # and fchown system call to avoid symlink race # between create and chown. # # No chmod needed (handled in the open call.) # POSIX needed for fchown call. use POSIX; require "syscall.ph"; # Get username and id info. ($username,$email) = @ARGV; ($uid,$gid,$home) = (getpwnam($username))[2,3,7] || die $FILE = "$home/.forward"; # No need to check unlink's exit status. If it fails # then sysopen will complain and we'll bail out. # Besides, relying on the exit status would lead to a # a new race condition. unlink $FILE; # Open the file securely - O_EXCL makes sure that # it can't be a symlink, dangling or no. sysopen( FORWARD, $FILE, O_RDWR|O_CREAT|O_EXCL, 0600) || die; # Note we're using fchown, which operates on the open # file descriptor, thus no chown race condition. syscall(&SYS_fchown, fileno(FORWARD), $uid, $gid)==0 || die; print FORWARD "$email\n"; close FORWARD;