How to update Perl on your box with setuid

We need to understand how perl works with setuid. I have copied the sections from this page to help you understand it better:

Perl is designed to make it easy to write secure setuid and setgid scripts. Unlike shells, which are based on multiple substitution passes on each line of the script, perl uses a more conventional evaluation scheme with fewer hidden "gotchas". Additionally, since the language has more built-in functionality, it has to rely less upon external (and possibly untrustworthy) programs to accomplish its purposes.

In an unpatched 4.2 or 4.3bsd kernel, setuid scripts are intrinsically insecure, but this kernel feature can be disabled. If it is, perl can emulate the setuid and setgid mechanism when it notices the otherwise useless setuid/gid bits on perl scripts. If the kernel feature isn't disabled, perl will complain loudly that your setuid script is insecure. You'll need to either disable the kernel setuid script feature, or put a C wrapper around the script.

When perl is executing a setuid script, it takes special precautions to prevent you from falling into any obvious traps. (In some ways, a perl script is more secure than the corresponding C program.) Any command line argument, environment variable, or input is marked as "tainted", and may not be used, directly or indirectly, in any command that invokes a subshell, or in any command that modifies files, directories or processes. Any variable that is set within an expression that has previously referenced a tainted value also becomes tainted (even if it is logically impossible for the tainted value to influence the variable). For example:

	$foo = shift;			# $foo is tainted
	$bar = $foo,'bar';		# $bar is also tainted
	$xxx = <>;			# Tainted
	$path = $ENV{'PATH'};		# Tainted, but see below
	$abc = 'abc';			# Not tainted

	system "echo $foo";		# Insecure
	system "/bin/echo", $foo;	# Secure (doesn't use sh)
	system "echo $bar";		# Insecure
	system "echo $abc";		# Insecure until PATH set

	$ENV{'PATH'} = '/bin:/usr/bin';
	$ENV{'IFS'} = '' if $ENV{'IFS'} ne '';

	$path = $ENV{'PATH'};		# Not tainted
	system "echo $abc";		# Is secure now!

	open(FOO,"$foo");		# OK
	open(FOO,">$foo"); 		# Not OK

	open(FOO,"echo $foo|");		# Not OK, but...
	open(FOO,"-|") || exec 'echo', $foo;	# OK

	$zzz = `echo $foo`;		# Insecure, zzz tainted

	unlink $abc,$foo;		# Insecure
	umask $foo;			# Insecure

	exec "echo $foo";		# Insecure
	exec "echo", $foo;		# Secure (doesn't use sh)
	exec "sh", '-c', $foo;		# Considered secure, alas
Uninstalling the current version of Perl

We will want to update perl using the FreeBSD Ports System. Lets check and see if Perl is already enabled with setuid. run the following command:

# cat /etc/make.conf

If you see:


If you see that line in the file output above, then perl is installed with setuid. You can now skip to Installing Qmail if you're comfortable with continuing on. If you would like to reinstall perl anyways, you can continue with the steps below. Just make sure NOT to run the echo "ENABLE_SUIDPERL=true" line below.

Run the following command to change to the Perl 5.8.8 port and then deinstall it:

# cd /usr/ports/lang/perl5.8
# make deinstall

If you get a message that says

===> Deinstalling for lang/perl5.8
===> perl not installed, skipping

If you see a section of the output that says perl is required by the following programs and give you a list. If it does, don't worry. We'll be reinstalling perl again below.

Otherwise the current version of perl thats installed will be uninstalled, if any.

Installing perl with setuid

Now we need to enable suidperl with perl:

# cd /usr/ports/lang/perl5.8
# make config

Now in the screen you see, hit the spacebar on the following line:

[X] SUIDPERL Build set-user-id suidperl binary

Hit the tab key to Ok and then hit Enter on your keyboard to continue.

Now we need to fix perl so it works correctly with suid. Basically what we are going to do here is extract the perl 5.8 port and then cd to the perl5.8 work folder and copy over the new perl.c file. The perl.c file has a missing suid section and breaks suid if this is not corrected. Run the following commands:

# cd /usr/ports/lang/perl5.8
# make extract
# cd work/perl-5.8.9
# cp perl.c perl_bak.c
# cp /downloads/qmailrocks/fixes/perl.c perl.c

Now that we have told /etc/make.conf to enable setuid perl and uninstalled it, we can now go ahead and install perl 5.8.8 which is current as of Feb 2007 Now run the following.

# cd /usr/ports/lang/perl5.8
# make install clean

We are now done with installing Perl with setuid! We can now continue on!

Installing Qmail