summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2014-12-22 23:14:08 +0100
committerDavid Kalnischkies <david@kalnischkies.de>2014-12-23 11:43:16 +0100
commit748a2177dcf8ff72bca90f5c7d516559ddd67352 (patch)
treebbcd34b959dc1b9640bb2ad68eb898d204818c09
parenta2a75ff4516f7609f4c55b42270abb8d08943c60 (diff)
pass-through stdin fd instead of content if not a terminal
Commit 299aea924ccef428219ed6f1a026c122678429e6 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
-rw-r--r--apt-pkg/deb/dpkgpm.cc16
-rwxr-xr-xtest/integration/test-no-fds-leaked-to-maintainer-scripts22
2 files changed, 32 insertions, 6 deletions
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index d54b7b50f..e23ca466d 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -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);
diff --git a/test/integration/test-no-fds-leaked-to-maintainer-scripts b/test/integration/test-no-fds-leaked-to-maintainer-scripts
index 7d0c1c6c1..41c057042 100755
--- a/test/integration/test-no-fds-leaked-to-maintainer-scripts
+++ b/test/integration/test-no-fds-leaked-to-maintainer-scripts
@@ -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