fix race condition allowing attackers to access destination file
authorW. Felix Handte <w@felixhandte.com>
Thu, 18 Feb 2021 11:59:48 +0000 (11:59 +0000)
committerÉtienne Mollier <etienne.mollier@mailoo.org>
Thu, 18 Feb 2021 11:59:48 +0000 (11:59 +0000)
Origin: upstream
Bug: https://github.com/facebook/zstd/issues/2491
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=982519
Applied-Upstream: commit:a774c5797399040af62db21d8a9b9769e005430e
Reviewed-by: Étienne Mollier <etienne.mollier@mailoo.org>
Last-Update: 2021-02-18

This commit addresses https://github.com/facebook/zstd/issues/2491.

Note that a downside of this solution is that it is global: `umask()` affects
all file creation calls in the process. I believe this is safe since
`fileio.c` functions should only ever be used in the zstd binary, and these
are (almost) the only files ever created by zstd, and AIUI they're only
created in a single thread. So we can get away with messing with global state.

Note that this doesn't change the permissions of files created by `dibio.c`.
I'm not sure what those should be...
Last-Update: 2021-02-18
Gbp-Pq: Name 0017-fix-file-permissions-on-compression.patch

programs/fileio.c
programs/util.c
programs/util.h

index 9fb795ed3f27bbfbb9b45e6f1087112449060c56..e17a0b47fd5035f8bea5442328fc5bdb5d965c64 100644 (file)
@@ -481,7 +481,9 @@ static FILE* FIO_openDstFile(const char* srcFileName, const char* dstFileName)
             FIO_remove(dstFileName);
     }   }
 
-    {   FILE* const f = fopen( dstFileName, "wb" );
+    {   const int old_umask = UTIL_umask(0177); /* u-x,go-rwx */
+        FILE* const f = fopen( dstFileName, "wb" );
+        UTIL_umask(old_umask);
         if (f == NULL)
             DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno));
         return f;
index 34634318c638ac71f040627245cf68efc8e9581c..120ad40eda4c3d06cd30ae6e52190fb465af3c7c 100644 (file)
@@ -51,6 +51,15 @@ int UTIL_getFileStat(const char* infilename, stat_t *statbuf)
     return 1;
 }
 
+int UTIL_umask(int mode) {
+#if PLATFORM_POSIX_VERSION > 0
+    return umask(mode);
+#else
+    /* do nothing, fake return value */
+    return mode;
+#endif
+}
+
 int UTIL_setFileStat(const char *filename, stat_t *statbuf)
 {
     int res = 0;
index f78bcbe1b3f8c0fb2daa5be8f7ae737aff5441ec..22a688edaf6b11d5525d35e0cbba9776d45a016d 100644 (file)
@@ -181,6 +181,11 @@ U64 UTIL_getFileSize(const char* infilename);
 
 U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles);
 
+/**
+ * Wraps umask(). Does nothing when the platform doesn't have that concept.
+ */
+int UTIL_umask(int mode);
+
 /*
  * A modified version of realloc().
  * If UTIL_realloc() fails the original block is freed.