]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/fileutl.cc
Merge branch 'debian/jessie' into debian/experimental
[apt.git] / apt-pkg / contrib / fileutl.cc
index f6351b7b5dc9372a8b051603743cdcc1a90ed9cd..afc243b7f7dfe8442a8ddd68f0b2165979df3d72 100644 (file)
@@ -874,6 +874,25 @@ bool StartsWithGPGClearTextSignature(string const &FileName)
    return true;
 }
                                                                        /*}}}*/
+// ChangeOwnerAndPermissionOfFile - set file attributes to requested values /*{{{*/
+bool ChangeOwnerAndPermissionOfFile(char const * const requester, char const * const file, char const * const user, char const * const group, mode_t const mode)
+{
+   if (strcmp(file, "/dev/null") == 0)
+      return true;
+   bool Res = true;
+   if (getuid() == 0 && strlen(user) != 0 && strlen(group) != 0) // if we aren't root, we can't chown, so don't try it
+   {
+      // ensure the file is owned by root and has good permissions
+      struct passwd const * const pw = getpwnam(user);
+      struct group const * const gr = getgrnam(group);
+      if (pw != NULL && gr != NULL && chown(file, pw->pw_uid, gr->gr_gid) != 0)
+        Res &= _error->WarningE(requester, "chown to %s:%s of file %s failed", user, group, file);
+   }
+   if (chmod(file, mode) != 0)
+      Res &= _error->WarningE(requester, "chmod 0%o of file %s failed", mode, file);
+   return Res;
+}
+                                                                       /*}}}*/
 
 class FileFdPrivate {                                                  /*{{{*/
        public:
@@ -2066,9 +2085,11 @@ std::string GetTempDir()                                         /*{{{*/
       tmpdir = P_tmpdir;
 #endif
 
-   // check that tmpdir is set and exists
    struct stat st;
-   if (!tmpdir || strlen(tmpdir) == 0 || stat(tmpdir, &st) != 0)
+   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
+      )
       tmpdir = "/tmp";
 
    return string(tmpdir);
@@ -2168,12 +2189,6 @@ bool DropPrivileges()                                                    /*{{{*/
    if(_config->FindB("Debug::NoDropPrivs", false) == true)
       return true;
 
-   // empty setting disables DropPrivilidges - this also ensures
-   // backward compatibility, see bug #764506
-   const std::string toUser = _config->Find("APT::Sandbox::User");
-   if (toUser.empty())
-      return true;
-
 #if __gnu_linux__
 #if defined(PR_SET_NO_NEW_PRIVS) && ( PR_SET_NO_NEW_PRIVS != 38 )
 #error "PR_SET_NO_NEW_PRIVS is defined, but with a different value than expected!"
@@ -2185,6 +2200,12 @@ bool DropPrivileges()                                                    /*{{{*/
       _error->Warning("PR_SET_NO_NEW_PRIVS failed with %i", ret);
 #endif
 
+   // empty setting disables privilege dropping - this also ensures
+   // backward compatibility, see bug #764506
+   const std::string toUser = _config->Find("APT::Sandbox::User");
+   if (toUser.empty())
+      return true;
+
    // uid will be 0 in the end, but gid might be different anyway
    uid_t const old_uid = getuid();
    gid_t const old_gid = getgid();