]> git.saurik.com Git - apt.git/commitdiff
ignore for _apt inaccessible TMPDIR in pkgAcqChangelog
authorDavid Kalnischkies <david@kalnischkies.de>
Mon, 31 Aug 2015 00:31:10 +0000 (02:31 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Mon, 31 Aug 2015 00:31:10 +0000 (02:31 +0200)
Using libpam-tmpdir caused us to create our download tmp directory in
root's private tmp before changing to _apt, which wouldn't have access
to it.

By extending our GetTempDir method with an optional wrapper changing the
effective user, we can test if a given user can access the directory and
ignore TMPDIR if not instead of ignoring TMPDIR completely.

Closes: 797270
apt-pkg/acquire-item.cc
apt-pkg/contrib/fileutl.cc
apt-pkg/contrib/fileutl.h

index f505531c1eaac0f908a68a590319f2ef1c40c2d6..b6b6d8e48c38b96e845c0611f812b31e0ab9563e 100644 (file)
@@ -2999,7 +2999,8 @@ void pkgAcqChangelog::Init(std::string const &DestDir, std::string const &DestFi
 
    if (DestDir.empty())
    {
-      std::string const systemTemp = GetTempDir();
+      std::string const SandboxUser = _config->Find("APT::Sandbox::User");
+      std::string const systemTemp = GetTempDir(SandboxUser);
       char tmpname[100];
       snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", systemTemp.c_str());
       if (NULL == mkdtemp(tmpname))
@@ -3010,7 +3011,6 @@ void pkgAcqChangelog::Init(std::string const &DestDir, std::string const &DestFi
       }
       DestFile = TemporaryDirectory = tmpname;
 
-      std::string SandboxUser = _config->Find("APT::Sandbox::User");
       ChangeOwnerAndPermissionOfFile("Item::QueueURI", DestFile.c_str(),
                                      SandboxUser.c_str(), "root", 0700);
    }
index d7c9424cf63ce25e11cb5a3bed84281bb11f7709..1d20c9c35148612eacbf87757120c8d5f0469bc7 100644 (file)
@@ -2123,12 +2123,37 @@ std::string GetTempDir()                                                /*{{{*/
 
    struct stat st;
    if (!tmpdir || strlen(tmpdir) == 0 || // tmpdir is set
-        stat(tmpdir, &st) != 0 || (st.st_mode & S_IFDIR) == 0 || // exists and is directory
-        access(tmpdir, R_OK | W_OK | X_OK) != 0 // current user has rwx access to directory
-      )
+        stat(tmpdir, &st) != 0 || (st.st_mode & S_IFDIR) == 0) // exists and is directory
+      tmpdir = "/tmp";
+   else if (geteuid() != 0 && // root can do everything anyway
+        faccessat(-1, tmpdir, R_OK | W_OK | X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) != 0) // current user has rwx access to directory
       tmpdir = "/tmp";
 
    return string(tmpdir);
+}
+std::string GetTempDir(std::string const &User)
+{
+   // no need/possibility to drop privs
+   if(getuid() != 0 || User.empty() || User == "root")
+      return GetTempDir();
+
+   struct passwd const * const pw = getpwnam(User.c_str());
+   if (pw == NULL)
+      return GetTempDir();
+
+   if (setegid(pw->pw_gid) != 0)
+      _error->Errno("setegid", "setegid %u failed", pw->pw_gid);
+   if (seteuid(pw->pw_uid) != 0)
+      _error->Errno("seteuid", "seteuid %u failed", pw->pw_uid);
+
+   std::string const tmp = GetTempDir();
+
+   if (seteuid(0) != 0)
+      _error->Errno("seteuid", "seteuid %u failed", 0);
+   if (setegid(0) != 0)
+      _error->Errno("setegid", "setegid %u failed", 0);
+
+   return tmp;
 }
                                                                        /*}}}*/
 FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink, FileFd * const TmpFd)     /*{{{*/
index acfd560ab34dae5bbb45d94c9df728f97dbbce4d..cddfe2b45cfa5c51c6a7c80aa0b9bdfe812231ac 100644 (file)
@@ -159,6 +159,7 @@ time_t GetModificationTime(std::string const &Path);
 bool Rename(std::string From, std::string To);
 
 std::string GetTempDir();
+std::string GetTempDir(std::string const &User);
 FileFd* GetTempFile(std::string const &Prefix = "",
                     bool ImmediateUnlink = true,
                    FileFd * const TmpFd = NULL);