On Wed, Jul 02, 2014 at 09:41:07PM +0200, Cédric Barboiron wrote: > Package: apt > Version: 1.0.5 > Severity: important
Thanks for your bugreport. > (warning: attached patch is not a solution, it is just intended to show > the problem) > > Setting Dir::Cache::archives and Dir::Cache to the empty string (as > instructed by man 5 apt.conf) do NOT disable cache but set it to '/'. > > Consequence: apt-get clean then effectively cleans '/' and removes all > files here. > > Not true anymore but even worse, on squeeze it also removes the '/lib64' > symlink, breaking the loader and preventing any new dynamically linked > binary to be launched. This sounds like we want to improve the description of the apt.conf manpage. I assume your use-case was to disable the binary cache? Maybe you can suggest a way to make the description clearer to avoid the issue for others? As for protecting against this, I attached a patch that makes clean a bit more careful and fix the example where Dir::Cache::archives="" is empty. But there is only so much we can do, e.g. if someone sets Dir::Cache=/vmlinuz its hard to have a programmatic way to detect that this is a bad idea. But I'm happy to protect against obvious ones (like Clean("/")). Cheers, Michael > - - - > all following tests done on debian testing, up to date on 2014-07-02 > > current result: > > debdev# cat apt.conf > Dir::Cache ""; > Dir::Cache::archives ""; > debdev# touch /VERY_SECRET > debdev# ls / > bin boot dev etc home initrd.img initrd.img.old lib lib64 lost+found > media mnt opt proc root run sbin srv sys tmp usr var VERY_SECRET > vmlinuz vmlinuz.old > debdev# apt-get clean > debdev# ls / > bin boot dev etc home lib lib64 lock lost+found media mnt opt > proc root run sbin srv sys tmp usr var > > > reading source code (contrib/configuration.cc) instead of the man page of > apt.conf: > > debdev# cat apt.conf > Dir::Cache "/dev/null"; > Dir::Cache::archives "/dev/null"; > debdev# touch /VERY_SECRET > debdev# ls / > bin boot dev etc home lib lib64 lock lost+found media mnt opt > proc root run sbin srv sys tmp usr var VERY_SECRET > debdev# apt-get clean > debdev# ls / > bin boot dev etc home lib lib64 lock lost+found media mnt opt > proc root run sbin srv sys tmp usr var VERY_SECRET > > expected result, BUT BUT BUT its not a good idea at all : > > debdev# cat /etc/apt/apt.conf > Dir::Cache "/dev/null"; > Dir::Cache::archives "/dev/null"; > debdev# ls -l /dev/null > crw-rw-rw- 1 root root 1, 3 Jul 2 20:11 /dev/null > debdev# apt-get install libcaca > Reading package lists... Error! > E: Write error - write (28: No space left on device) > E: Can't mmap an empty file > E: Failed to truncate file - ftruncate (9: Bad file descriptor) > E: The package lists or status file could not be parsed or opened. > debdev# ls -l /dev/null > -rw-r--r-- 1 root root 0 Jul 2 20:17 /dev/null > debdev# df -h > Filesystem Size Used Avail Use% Mounted on > /dev/mapper/debdev-root 95G 5.0G 85G 6% / > udev 10M 10M 0 100% /dev > tmpfs 202M 200K 201M 1% /run > tmpfs 5.0M 0 5.0M 0% /run/lock > tmpfs 403M 0 403M 0% /run/shm > /dev/sda1 228M 80M 137M 37% /boot > none 4.0K 0 4.0K 0% /sys/fs/cgroup > > and finally with attached patch (built without "make test" because it has > other side-effects): > > debdev# cat /etc/apt/apt.conf > Dir::Cache ""; > Dir::Cache::archives ""; > debdev# touch /MYTRALALA > debdev# ls / > bin dev home lib64 lost+found mnt opt root sbin sys usr > boot etc lib lock media MYTRALALA proc run srv tmp var > debdev# apt-get clean > E: Ignored empty string directory configuration (would have been expanded to > '/' otherwise) > debdev# ls / > bin dev home lib64 lost+found mnt opt root sbin sys usr > boot etc lib lock media MYTRALALA proc run srv tmp var > > > diff --git a/apt-pkg/contrib/configuration.cc > b/apt-pkg/contrib/configuration.cc > index 00f6ad0..3dd63aa 100644 > --- a/apt-pkg/contrib/configuration.cc > +++ b/apt-pkg/contrib/configuration.cc > @@ -240,6 +240,11 @@ string Configuration::FindFile(const char *Name,const > char *Default) const > string Configuration::FindDir(const char *Name,const char *Default) const > { > string Res = FindFile(Name,Default); > + if (Res == "") > + { > + _error->Error(_("Ignored empty string directory configuration (would > have been expanded to '/' otherwise)")); > + return Res; > + } > if (Res.end()[-1] != '/') > { > size_t const found = Res.rfind("/dev/null"); > diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml > index fcbf20d..e30898c 100644 > --- a/doc/apt.conf.5.xml > +++ b/doc/apt.conf.5.xml > @@ -607,8 +607,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure > --apt";}; > <para><literal>Dir::Cache</literal> contains locations pertaining to > local cache > information, such as the two package caches > <literal>srcpkgcache</literal> and > <literal>pkgcache</literal> as well as the location to place downloaded > archives, > - <literal>Dir::Cache::archives</literal>. Generation of caches can be > turned off > - by setting their names to the empty string. This will slow down startup > but > + <literal>Dir::Cache::archives</literal>. Generation of caches CANNOT BE > TURNED OFF. > + This would slow down startup but could > save disk space. It is probably preferable to turn off the pkgcache rather > than the srcpkgcache. Like <literal>Dir::State</literal> the default > directory is contained in <literal>Dir::Cache</literal></para>
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index a187a00..057bc24 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -486,6 +486,9 @@ bool pkgAcquire::Clean(string Dir) if (DirectoryExists(Dir) == false) return true; + if(Dir == "/") + return _error->Error(_("Clean of %s is not supported"), Dir.c_str()); + DIR *D = opendir(Dir.c_str()); if (D == 0) return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str()); diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc index 0ee3b76..37128e9 100644 --- a/apt-pkg/clean.cc +++ b/apt-pkg/clean.cc @@ -34,7 +34,10 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache) { bool CleanInstalled = _config->FindB("APT::Clean-Installed",true); - + + if(Dir == "/") + return _error->Error(_("Clean of %s is not supported"), Dir.c_str()); + DIR *D = opendir(Dir.c_str()); if (D == 0) return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());