diff options
author | David Kalnischkies <david@kalnischkies.de> | 2015-08-31 02:31:10 +0200 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2015-08-31 02:31:10 +0200 |
commit | dd6da7d2392e2ad35c444ebc2d7bc2308380530c (patch) | |
tree | 905b124b2b99dcb5ff212918332715900776136b /apt-pkg | |
parent | 3090ae6972fd0e15767a96708c248f3ab87502f2 (diff) |
ignore for _apt inaccessible TMPDIR in pkgAcqChangelog
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
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/acquire-item.cc | 4 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 31 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.h | 1 |
3 files changed, 31 insertions, 5 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index f505531c1..b6b6d8e48 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -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); } diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index d7c9424cf..1d20c9c35 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2123,13 +2123,38 @@ 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) /*{{{*/ { diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index acfd560ab..cddfe2b45 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -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); |