Browse Source

pass-through stdin fd instead of content if not a terminal

Commit 299aea924c fixes the problem of
not logging terminal in case stdin & stdout are not a terminal. The
problem is that we are then trying to pass-through stdin content by
reading from the apt-process stdin and writing it to the stdin of the
child (dpkg), which works great for users who can control themselves,
but pipes and co are a bit less forgiving causing us to pass everything
to the first child process, which if the sending part of the pipe is
e.g. 'yes' we will never see the end of it (as the pipe is full at some
point and further writing blocks).

There is a simple solution for that of course: If stdin isn't a terminal,
we us the apt-process stdin as stdin for the child directly (We don't do
this if it is a terminal to be able to save the typed input in the log).

Closes: 773061
tags/debian/1.0.9.5
David Kalnischkies 6 years ago
parent
commit
748a2177dc
2 changed files with 32 additions and 6 deletions
  1. +12
    -4
      apt-pkg/deb/dpkgpm.cc
  2. +20
    -2
      test/integration/test-no-fds-leaked-to-maintainer-scripts

+ 12
- 4
apt-pkg/deb/dpkgpm.cc View File

@@ -73,7 +73,8 @@ public:
pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
term_out(NULL), history_out(NULL),
progress(NULL), tt_is_valid(false), master(-1),
slave(NULL), protect_slave_from_dying(-1)
slave(NULL), protect_slave_from_dying(-1),
direct_stdin(false)
{
dpkgbuf[0] = '\0';
}
@@ -100,6 +101,7 @@ public:
sigset_t sigmask;
sigset_t original_sigmask;

bool direct_stdin;
};

namespace
@@ -1079,6 +1081,9 @@ void pkgDPkgPM::StartPtyMagic()
return;
}

if (isatty(STDIN_FILENO) == 0)
d->direct_stdin = true;

_error->PushToStack();

d->master = posix_openpt(O_RDWR | O_NOCTTY);
@@ -1176,7 +1181,10 @@ void pkgDPkgPM::SetupSlavePtyMagic()
_error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd);
else
{
for (unsigned short i = 0; i < 3; ++i)
unsigned short i = 0;
if (d->direct_stdin == true)
++i;
for (; i < 3; ++i)
if (dup2(slaveFd, i) == -1)
_error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i);

@@ -1596,8 +1604,8 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress)

// wait for input or output here
FD_ZERO(&rfds);
if (d->master >= 0 && !d->stdin_is_dev_null)
FD_SET(0, &rfds);
if (d->master >= 0 && d->direct_stdin == false && d->stdin_is_dev_null == false)
FD_SET(STDIN_FILENO, &rfds);
FD_SET(_dpkgin, &rfds);
if(d->master >= 0)
FD_SET(d->master, &rfds);


+ 20
- 2
test/integration/test-no-fds-leaked-to-maintainer-scripts View File

@@ -11,8 +11,14 @@ configdpkgnoopchroot
setupsimplenativepackage "fdleaks" 'all' '1.0' 'unstable'
BUILDDIR="incoming/fdleaks-1.0"
for script in 'preinst' 'postinst' 'prerm' 'postrm'; do
echo '#!/bin/sh
ls -l /proc/self/fd/' > ${BUILDDIR}/debian/$script
cat > ${BUILDDIR}/debian/$script << EOF
#!/bin/sh
if [ -e "$(pwd)/rootdir/tmp/read_stdin" ]; then
read line;
echo "STDIN: -\$line-"
fi
ls -l /proc/self/fd/
EOF
done
buildpackage "$BUILDDIR" 'unstable' 'main' 'native'
rm -rf "$BUILDDIR"
@@ -99,3 +105,15 @@ 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

touch rootdir/tmp/read_stdin

rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
for i in $(seq 1 10); do echo "$i"; done | testsuccess aptget install -y fdleaks -qq
checkinstall
testequal '2' grep -c '^STDIN: ' rootdir/var/log/apt/term.log

rm -f rootdir/var/log/dpkg.log rootdir/var/log/apt/term.log
yes '' | testsuccess runapt command setsid -w "${BUILDDIRECTORY}/apt-get" purge -y fdleaks -qq
checkpurge
testequal '3' grep -c '^STDIN: ' rootdir/var/log/apt/term.log

Loading…
Cancel
Save