Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Oct 2002 16:57:57 +1000
From:      Edwin Groothuis <edwin@mavetju.org>
To:        freebsd-ports@freebsd.org
Subject:   A less exploit vulnerable ports building environment
Message-ID:  <20021009065757.GA7253@k7.mavetju>

next in thread | raw e-mail | index | archive | help
Greetings,

About two months ago it was the OpenSSH distribution which was
trojaned, today it is the Sendmail distribution. Hopefully the 4.7
CD will have the right source-tarball. Anyway, my story.

What can been done to the FreeBSD port-system to prevent malicious[sp]
code to be run as root? Right now, everything without the ports-system
is running as root. Is this required? yes and no. Is it safe? yes
and no. Can it be reduced? yes.

Is it required to run make as root? For certain parts it is, specially
the (un)install-part. For the rest it is not needed.

Is it safe to run make as root? It is a matter of trust. For certain
parts it is, specially the stuff coming with the ports-framework
the level of trust is high: it's coming from a controlled environment.
For other parts, like running configure, automake, build and install,
it's always "keep fingers crossed and pray". In 99% of the times
it will act like it did with the submittor/commitor of the port,
for 1% it will not and complain. Worst case scenario it will touch
files which it wasn't supposed to touch.

Can it be reduced? Yes. There are three moments why you need
root-privileges: "make install", "make deinstall" and a less often
occuring "make clean". For the rest it's not needed. There are three
moments where you don't want root-privileges: "make configure",
"make build" and "make install".  Why not? Because you're running
code not submitted by the ports-system but coming from untrusted
sources.

In the previous paragraph, you see a clash: you need root-privileges
to run "make install" and you don't want root-privileges there
because you're running untrusted code. This is not a thing which
can be solved.


What can be solved is changing everything (except for the three
mentions moments) to be non-root. Run everything which is writing
in the WRKDIR as an unprivileged user (for example, portbuild).
Instead of running things as root, run them as portbuild:

    .if !target(do-extract)
    do-extract:
	@${RM} -rf ${WRKDIR}
	@${MKDIR} ${WRKDIR}
+	/usr/bin/su -m portbuild -c "\
	for file in ${EXTRACT_ONLY}; do \
	    echo \$$file; \
	    if ! (cd ${WRKDIR} && ${EXTRACT_CMD} ${EXTRACT_BEFORE_ARGS} ${_DISTDIR}/\$$file ${EXTRACT_AFTER_ARGS});\
	    then \
		exit 1; \
	    fi \
	done \
+	"
    .endif

This approach (i.e. su when going into the WRKDIR) looks good, but
it won't work because the user can override the targets and play
around as root again.

The right approach would be to put a wrapper around the targets
which shouldn't be ran as root.

(See Skeleton targets in bsd.port.mk):
    _FETCH_SEQ=     pre-everything fetch-depends pre-fetch pre-fetch-script \
		    do-fetch post-fetch post-fetch-script
+   _FETCH_WRAP=
    _EXTRACT_DEP=   fetch 
    _EXTRACT_SEQ=   extract-message checksum build-depends lib-depends \
		    misc-depends pre-extract pre-extract-script do-extract \
		    post-extract post-extract-script
+   _EXTRACT_WRAP=  pre-extract pre-extract-script do-extract post-extract \
+		    post-extract-script
    _PATCH_DEP=     extract  
    _PATCH_SEQ=     patch-message pre-patch pre-patch-script do-patch \
		    post-patch post-patch-script
+   _PATCH_WRAP=    pre-patch pre-patch-script do-patch post-patch \
+		    post-patch-script
    _CONFIGURE_DEP= patch
    _CONFIGURE_SEQ= configure-message patch-libtool pre-configure \
		    pre-configure-script do-configure post-configure \
		    post-configure-script
+   _CONFIGURE_WRAP=pre-configure pre-configure-script do-configure \
+		    post-configure post-configure-script
    _BUILD_DEP=     configure
    _BUILD_SEQ=     build-message pre-build pre-build-script do-build \
		    post-build post-build-script
+   _BUILD_WRAP=    pre-build pre-build-script do-build post-build \
+		    post-build-script
    _INSTALL_DEP=   build
    _INSTALL_SEQ=   install-message check-categories check-already-installed \
		    check-umask run-depends lib-depends install-mtree pre-install \
		    pre-install-script do-install generate-plist post-install \
		    post-install-script compress-man run-ldconfig fake-pkg \
		    security-check
+   _INSTALL_WRAP= 
    _PACKAGE_DEP=   install
    _PACKAGE_SEQ=   package-message pre-package pre-package-script \
		    do-package post-package-script
    _PACKAGE_WRAP=

replace all the ones in _SEQ which are in _WRAP so that they can be wrapped:
    .for target in extract patch configure build install package
    . for wrap in ${_${target:U}_WRAP}
    _${target:U}_SEQ:=  ${_${target:U}_SEQ:S/^${wrap}$/wrap-&/}
    . endfor
    .endfor

And create wrappers for them:
    .for target in extract patch configure build install package
    . if ${_${target:U}_WRAP:Mdo-${target}}!=""
    wrap-do-${target}:
	@echo Wrapping do-${target}
	@${SU} portbuild -c "${MAKE} do-${target}"
    . endif
    .endfor

    .for stage in pre post
    . for name in fetch extract patch configure build install package
    .  if ${_${name:U}_WRAP:M${stage}-${name}}!=""
    wrap-${stage}-${name}:
	@echo Wrapping ${stage}-${name}
	@${SU} portbuild -c "${MAKE} ${stage}-${name}"
    .  endif
    .  if ${_${name:U}_WRAP:M${stage}-${name}-script}!=""
    wrap-${stage}-${name}-script:
	@echo Wrapping ${stage}-${name}-script
	@${SU} portbuild -c "${MAKE} ${stage}-${name}-script"
    .  endif
    . endfor
    .endfor

With this approach the amount of time the building of a port as
root is reduced with (right now) the bigger part of extract, patch,
configure and build.

I've been running a what more optimized version than described at
home and except for some warnings regarding permissions of files
in tarballs I didn't encounter much problems. I'll keep running it
for a week and then submit it as a patch.

Hmm... this has taken more time (and lines in this email) than I
hoped for. Comments anyone?

Edwin

-- 
Edwin Groothuis      |            Personal website: http://www.MavEtJu.org
edwin@mavetju.org    |    Weblog: http://www.mavetju.org/weblog/weblog.php 
bash$ :(){ :|:&};:   | Interested in MUDs? http://www.FatalDimensions.org/

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021009065757.GA7253>