From 7559ed92f9e0f3f75a80d8f5d2b4cadba1a319eb Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 22 Mar 2025 11:11:36 -0400 Subject: [PATCH] src/geoipyupdate/__init__.py: respect umask for the database All python temporary files are created with mode 600, and that includes the temporary files that we use to download/decompress the database. When we eventually move the database to its destination, it retains these permissions and needs to be chmod'ed. This leads to a race condition where web applications can raise permission errors in the instant that the database is unreadable. The solution to this is obvious, we should just respect the umask. But python makes this very hard to do: the tempfile module ignores the umask, and you can't obtain the umask without changing it, and changing it affects other threads... anyway, it can be done, if carefully. This commit uses os.chmod() on the database file to make it world readable and group writable, minus whatever permissions the user has masked. --- src/geoipyupdate/__init__.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/geoipyupdate/__init__.py b/src/geoipyupdate/__init__.py index 4353a68..ace4bdc 100644 --- a/src/geoipyupdate/__init__.py +++ b/src/geoipyupdate/__init__.py @@ -114,5 +114,22 @@ def main(): f"{edition} hash doesn't match X-Database-MD5 header" ) + # All python temporary files are hard-coded to mode 0600, + # which isn't what we want if we're going to move this one in + # to the live database directory. At the very least, we want + # it to respect the umask. This gets a little stupid: to + # obtain the current umask, you have to change it. We change + # it to 0777 (mask all permissions), because that's the only + # safe choice, and because the temporary umask we set should + # not actually affect anything. Afterwards, we immediate set + # the umask (again) to what it was originally. This "gets" the + # umask, albeit with extra steps. + old_umask = os.umask(0o777) + os.umask(old_umask) + + # Finally, we chmod g to be world readable and group writable, + # minus whatever the user has set in his umask. + os.chmod(g.name, 0o664 & ~old_umask) + # Overwrite the old database file with the new (gunzipped) one. shutil.move(g.name, dbfile) -- 2.49.0