Browse Source

do not make PTY slave the controlling terminal

If we have no controlling terminal opening a terminal will make this
terminal our controller, which is a serious problem if this happens to
be the pseudo terminal we created to run dpkg in as we will close this
terminal at the end hanging ourself up in the process…

The offending open is the one we do to have at least one slave fd open
all the time, but for good measure, we apply the flag also to the slave
fd opening in the child process as we set the controlling terminal
explicitely here.

This is a regression from 150bdc9ca5 with
the slight twist that this usecase was silently broken before in that it
wasn't logging the output in term.log (as a pseudo terminal wasn't
created).

Closes: 772641
tags/debian/1.0.9.5
David Kalnischkies 6 years ago
parent
commit
e18f6133b2
3 changed files with 70 additions and 45 deletions
  1. +2
    -2
      apt-pkg/deb/dpkgpm.cc
  2. +1
    -1
      test/integration/framework
  3. +67
    -42
      test/integration/test-no-fds-leaked-to-maintainer-scripts

+ 2
- 2
apt-pkg/deb/dpkgpm.cc View File

@@ -1131,7 +1131,7 @@ void pkgDPkgPM::StartPtyMagic()
on kfreebsd we get an incorrect ("step like") output then while it has
no problem with closing all references… so to avoid platform specific
code here we combine both and be happy once more */
d->protect_slave_from_dying = open(d->slave, O_RDWR | O_CLOEXEC);
d->protect_slave_from_dying = open(d->slave, O_RDWR | O_CLOEXEC | O_NOCTTY);
}
}
}
@@ -1163,7 +1163,7 @@ void pkgDPkgPM::SetupSlavePtyMagic()
if (setsid() == -1)
_error->FatalE("setsid", "Starting a new session for child failed!");

int const slaveFd = open(d->slave, O_RDWR);
int const slaveFd = open(d->slave, O_RDWR | O_NOCTTY);
if (slaveFd == -1)
_error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
else if (ioctl(slaveFd, TIOCSCTTY, 0) < 0)


+ 1
- 1
test/integration/framework View File

@@ -102,7 +102,7 @@ runapt() {
local CMD="$1"
shift
case $CMD in
sh|aptitude|*/*) ;;
sh|aptitude|*/*|command) ;;
*) CMD="${BUILDDIRECTORY}/$CMD";;
esac
MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${BUILDDIRECTORY} $CMD "$@"


+ 67
- 42
test/integration/test-no-fds-leaked-to-maintainer-scripts View File

@@ -5,7 +5,7 @@ TESTDIR=$(readlink -f $(dirname $0))
. $TESTDIR/framework

setupenvironment
configarchitecture 'native'
configarchitecture 'amd64' 'i386'
configdpkgnoopchroot

setupsimplenativepackage "fdleaks" 'all' '1.0' 'unstable'
@@ -17,58 +17,83 @@ done
buildpackage "$BUILDDIR" 'unstable' 'main' 'native'
rm -rf "$BUILDDIR"

PKGNAME='fdleaks:all'
if ! dpkg-checkbuilddeps -d 'dpkg (>= 1.16.2)' /dev/null >/dev/null 2>&1; then
PKGNAME='fdleaks'
fi

setupaptarchive

rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
testsuccess aptget install -y fdleaks -qq < /dev/null
msgtest 'Check if fds were not' 'leaked'
if [ "$(grep 'root root' rootdir/tmp/testsuccess.output | wc -l)" = '8' ]; then
msgpass
else
echo
cat rootdir/tmp/testsuccess.output
msgfail
fi

cp rootdir/tmp/testsuccess.output terminal.output
tail -n +3 rootdir/var/log/apt/term.log | head -n -1 > terminal.log
testfileequal 'terminal.log' "$(cat terminal.output)"
checkfdleak() {
msgtest 'Check if fds were not' 'leaked'
if [ "$(grep 'root root' rootdir/tmp/testsuccess.output | wc -l)" = "$1" ]; then
msgpass
else
echo
cat rootdir/tmp/testsuccess.output
msgfail
fi
}
checkinstall() {
checkfdleak 8

cp rootdir/tmp/testsuccess.output terminal.output
tail -n +3 rootdir/var/log/apt/term.log | head -n -1 > terminal.log
testfileequal 'terminal.log' "$(cat terminal.output)"

testequal 'startup archives unpack
install fdleaks:all <none> 1.0
status half-installed fdleaks:all 1.0
status unpacked fdleaks:all 1.0
status unpacked fdleaks:all 1.0
testequal "startup archives unpack
install $PKGNAME <none> 1.0
status half-installed $PKGNAME 1.0
status unpacked $PKGNAME 1.0
status unpacked $PKGNAME 1.0
startup packages configure
configure fdleaks:all 1.0 <none>
status unpacked fdleaks:all 1.0
status half-configured fdleaks:all 1.0
status installed fdleaks:all 1.0' cut -f 3- -d' ' rootdir/var/log/dpkg.log
configure $PKGNAME 1.0 <none>
status unpacked $PKGNAME 1.0
status half-configured $PKGNAME 1.0
status installed $PKGNAME 1.0" cut -f 3- -d' ' rootdir/var/log/dpkg.log
}
checkinstall

rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
testsuccess aptget purge -y fdleaks -qq
msgtest 'Check if fds were not' 'leaked'
if [ "$(grep 'root root' rootdir/tmp/testsuccess.output | wc -l)" = '12' ]; then
checkpurge() {
checkfdleak 12

cp rootdir/tmp/testsuccess.output terminal.output
tail -n +3 rootdir/var/log/apt/term.log | head -n -1 > terminal.log
testfileequal 'terminal.log' "$(cat terminal.output)"

testequal "startup packages purge
status installed $PKGNAME 1.0
remove $PKGNAME 1.0 <none>
status half-configured $PKGNAME 1.0
status half-installed $PKGNAME 1.0
status config-files $PKGNAME 1.0
purge $PKGNAME 1.0 <none>
status config-files $PKGNAME 1.0
status config-files $PKGNAME 1.0
status config-files $PKGNAME 1.0
status config-files $PKGNAME 1.0
status config-files $PKGNAME 1.0
status not-installed $PKGNAME <none>" cut -f 3- -d' ' rootdir/var/log/dpkg.log
}
checkpurge

msgtest 'setsid provided is new enough to support' '-w'
if dpkg-checkbuilddeps -d 'util-linux (>= 2.24.2-1)' /dev/null >/dev/null 2>&1; then
msgpass
else
echo
cat rootdir/tmp/testsuccess.output
msgfail
msgskip "$(command dpkg -l util-linux)"
exit
fi
cp rootdir/tmp/testsuccess.output terminal.output
tail -n +3 rootdir/var/log/apt/term.log | head -n -1 > terminal.log
testfileequal 'terminal.log' "$(cat terminal.output)"

testequal 'startup packages purge
status installed fdleaks:all 1.0
remove fdleaks:all 1.0 <none>
status half-configured fdleaks:all 1.0
status half-installed fdleaks:all 1.0
status config-files fdleaks:all 1.0
purge fdleaks:all 1.0 <none>
status config-files fdleaks:all 1.0
status config-files fdleaks:all 1.0
status config-files fdleaks:all 1.0
status config-files fdleaks:all 1.0
status config-files fdleaks:all 1.0
status not-installed fdleaks:all <none>' cut -f 3- -d' ' rootdir/var/log/dpkg.log
rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
testsuccess runapt command setsid -w "${BUILDDIRECTORY}/apt-get" install -y fdleaks -qq < /dev/null
checkinstall

rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
testsuccess runapt command setsid -w "${BUILDDIRECTORY}/apt-get" purge -y fdleaks -qq
checkpurge

Loading…
Cancel
Save