From f22b65b47990237bd5d9a1c171919c3059fbd9b0 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 9 Apr 2014 10:12:10 +0200 Subject: Fix insecure file permissions when using FileFd with OpenMode::Atomic Commit 7335eebea6dd43581d4650a8818b06383ab89901 introduced a bug that caused FileFd to create insecure permissions when FileFd::Atomic is used. This commit fixes the permissions and adds a test. The bug is most likely caused by the confusing "Perm" parameter that is passed to Open() - its not the file permissions but intead the "mode" part of open/creat. --- apt-pkg/contrib/fileutl.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 188bb87ee..8b57e87a3 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1067,6 +1067,10 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co if_FLAGGED_SET(Exclusive, O_EXCL); #undef if_FLAGGED_SET + // there is no getumask() so we read it by setting it and reset + mode_t current_umask = umask(0); + umask(current_umask); + if ((Mode & Atomic) == Atomic) { char *name = strdup((FileName + ".XXXXXX").c_str()); @@ -1080,11 +1084,11 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co TemporaryFileName = string(name); free(name); - if(Perms != 600 && fchmod(iFd, Perms) == -1) + if(Perms != 600 && fchmod(iFd, Perms & ~current_umask) == -1) return FileFdErrno("fchmod", "Could not change permissions for temporary file %s", TemporaryFileName.c_str()); } else - iFd = open(FileName.c_str(), fileflags, Perms); + iFd = open(FileName.c_str(), fileflags, Perms & ~current_umask); this->FileName = FileName; if (iFd == -1 || OpenInternDescriptor(Mode, compressor) == false) -- cgit v1.2.3 From e5f3f8c101b772a6eb6326203a2174e809ab406d Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 9 Apr 2014 10:24:47 +0200 Subject: Rename FileFd::Open() Perms to AccessMode Bug lp:#1304657 was caused by confusion around the name Perms. The new name AccessMode should make it clear that its not the literal file permissions but instead the AccessMode passed to open() (i.e. the umask needs to be applied) --- apt-pkg/contrib/fileutl.cc | 12 ++++++------ apt-pkg/contrib/fileutl.h | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 8b57e87a3..c6072ca15 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -958,10 +958,10 @@ class FileFdPrivate { /*{{{*/ // FileFd::Open - Open a file /*{{{*/ // --------------------------------------------------------------------- /* The most commonly used open mode combinations are given with Mode */ -bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, unsigned long const Perms) +bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, unsigned long const AccessMode) { if (Mode == ReadOnlyGzip) - return Open(FileName, ReadOnly, Gzip, Perms); + return Open(FileName, ReadOnly, Gzip, AccessMode); if (Compress == Auto && (Mode & WriteOnly) == WriteOnly) return FileFdError("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str()); @@ -1028,9 +1028,9 @@ bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, if (compressor == compressors.end()) return FileFdError("Can't find a match for specified compressor mode for file %s", FileName.c_str()); - return Open(FileName, Mode, *compressor, Perms); + return Open(FileName, Mode, *compressor, AccessMode); } -bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms) +bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const AccessMode) { Close(); Flags = AutoClose; @@ -1084,11 +1084,11 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co TemporaryFileName = string(name); free(name); - if(Perms != 600 && fchmod(iFd, Perms & ~current_umask) == -1) + if(AccessMode != 600 && fchmod(iFd, AccessMode & ~current_umask) == -1) return FileFdErrno("fchmod", "Could not change permissions for temporary file %s", TemporaryFileName.c_str()); } else - iFd = open(FileName.c_str(), fileflags, Perms & ~current_umask); + iFd = open(FileName.c_str(), fileflags, AccessMode & ~current_umask); this->FileName = FileName; if (iFd == -1 || OpenInternDescriptor(Mode, compressor) == false) diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index f25ed3622..cc1a98eae 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -103,10 +103,10 @@ class FileFd return T; } - bool Open(std::string FileName,unsigned int const Mode,CompressMode Compress,unsigned long const Perms = 0666); - bool Open(std::string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor,unsigned long const Perms = 0666); - inline bool Open(std::string const &FileName,unsigned int const Mode, unsigned long const Perms = 0666) { - return Open(FileName, Mode, None, Perms); + bool Open(std::string FileName,unsigned int const Mode,CompressMode Compress,unsigned long const AccessMode = 0666); + bool Open(std::string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor,unsigned long const AccessMode = 0666); + inline bool Open(std::string const &FileName,unsigned int const Mode, unsigned long const AccessMode = 0666) { + return Open(FileName, Mode, None, AccessMode); }; bool OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compress, bool AutoClose=false); bool OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose=false); @@ -129,13 +129,13 @@ class FileFd inline bool IsCompressed() {return (Flags & Compressed) == Compressed;}; inline std::string &Name() {return FileName;}; - FileFd(std::string FileName,unsigned int const Mode,unsigned long Perms = 0666) : iFd(-1), Flags(0), d(NULL) + FileFd(std::string FileName,unsigned int const Mode,unsigned long AccessMode = 0666) : iFd(-1), Flags(0), d(NULL) { - Open(FileName,Mode, None, Perms); + Open(FileName,Mode, None, AccessMode); }; - FileFd(std::string FileName,unsigned int const Mode, CompressMode Compress, unsigned long Perms = 0666) : iFd(-1), Flags(0), d(NULL) + FileFd(std::string FileName,unsigned int const Mode, CompressMode Compress, unsigned long AccessMode = 0666) : iFd(-1), Flags(0), d(NULL) { - Open(FileName,Mode, Compress, Perms); + Open(FileName,Mode, Compress, AccessMode); }; FileFd() : iFd(-1), Flags(AutoClose), d(NULL) {}; FileFd(int const Fd, unsigned int const Mode = ReadWrite, CompressMode Compress = None) : iFd(-1), Flags(0), d(NULL) -- cgit v1.2.3 From db5bf949ed796395d281474c49033f882e73f3a9 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 10 Apr 2014 09:11:57 +0200 Subject: improve umask/fchmod code readability --- apt-pkg/contrib/fileutl.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index c6072ca15..69a675648 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1067,9 +1067,12 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co if_FLAGGED_SET(Exclusive, O_EXCL); #undef if_FLAGGED_SET - // there is no getumask() so we read it by setting it and reset - mode_t current_umask = umask(0); - umask(current_umask); + // umask() will always set the umask and return the previous value, so + // we first set the umask and then reset it to the old value + mode_t CurrentUmask = umask(0); + umask(CurrentUmask); + // calculate the actual file permissions (just like open/creat) + mode_t FilePermissions = (AccessMode & ~CurrentUmask); if ((Mode & Atomic) == Atomic) { @@ -1084,11 +1087,11 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co TemporaryFileName = string(name); free(name); - if(AccessMode != 600 && fchmod(iFd, AccessMode & ~current_umask) == -1) + if(FilePermissions != 600 && fchmod(iFd, FilePermissions) == -1) return FileFdErrno("fchmod", "Could not change permissions for temporary file %s", TemporaryFileName.c_str()); } else - iFd = open(FileName.c_str(), fileflags, AccessMode & ~current_umask); + iFd = open(FileName.c_str(), fileflags, FilePermissions); this->FileName = FileName; if (iFd == -1 || OpenInternDescriptor(Mode, compressor) == false) -- cgit v1.2.3