gplv3/python-keyring/python-keyring/remove-reader-lock.patch

137 lines
5.6 KiB
Diff

---
keyring/backends/file.py | 85 ++++++++++++++++++++++-------------------------
1 file changed, 41 insertions(+), 44 deletions(-)
--- a/keyring/backends/file.py
+++ b/keyring/backends/file.py
@@ -18,6 +18,7 @@ from ..backend import KeyringBackend
from ..util import platform_, properties
from ..util.escape import escape as escape_for_ini
from oslo_concurrency import lockutils
+from tempfile import mkstemp
lockfile = "keyringlock"
@@ -102,11 +103,9 @@ class BaseKeyring(FileBacked, KeyringBac
# encode with base64
password_base64 = base64.encodestring(password_encrypted).decode()
- lockdir = os.path.dirname(self.file_path)
-
- with lockutils.lock(lockfile,external=True,lock_path=lockdir):
-
+ keyringdir = os.path.dirname(self.file_path)
+ with lockutils.lock(lockfile, external=True, lock_path=keyringdir):
config = None
try:
# Load the keyring from the disk
@@ -121,16 +120,20 @@ class BaseKeyring(FileBacked, KeyringBac
config.add_section(service)
config.set(service, username, password_base64)
- # Save the keyring back to the file
- storage_root = os.path.dirname(self.file_path)
- tmpfile = "tmpfile.%s" % os.getpid()
- with open(storage_root + "/" + tmpfile, 'w') as config_file:
- config.write(config_file)
- # copy will overwrite but move will not
- shutil.copy(storage_root + "/" + tmpfile,self.file_path)
- # wipe out tmpfile here
- os.remove(storage_root + "/" + tmpfile)
+ # remove any residual temporary files here
+ try:
+ for tmpfile in glob.glob("%s/tmp*" % keyringdir):
+ os.remove(tmpfile)
+ except:
+ logging.warning("_check_file: tmpfile removal failed")
+ # Write the keyring to a temp file, then move the new file
+ # to avoid overwriting the existing inode
+ (fd, fname) = mkstemp(dir=keyringdir)
+ with os.fdopen(fd, "w") as config_file:
+ config.write(config_file)
+ os.chmod(fname, os.stat(self.file_path).st_mode)
+ shutil.move(fname, self.file_path)
def _ensure_file_path(self):
@@ -167,8 +170,8 @@ class BaseKeyring(FileBacked, KeyringBac
service = escape_for_ini(service)
username = escape_for_ini(username)
- lockdir = os.path.dirname(self.file_path)
- with lockutils.lock(lockfile,external=True,lock_path=lockdir):
+ keyringdir = os.path.dirname(self.file_path)
+ with lockutils.lock(lockfile, external=True, lock_path=keyringdir):
config = configparser.RawConfigParser()
if os.path.exists(self.file_path):
config.read(self.file_path)
@@ -177,15 +180,21 @@ class BaseKeyring(FileBacked, KeyringBac
raise PasswordDeleteError("Password not found")
except configparser.NoSectionError:
raise PasswordDeleteError("Password not found")
- # update the file
- storage_root = os.path.dirname(self.file_path)
- tmpfile = "tmpfile.%s" % os.getpid()
- with open(storage_root + "/" + tmpfile, 'w') as config_file:
+
+ # remove any residual temporary files here
+ try:
+ for tmpfile in glob.glob("%s/tmp*" % keyringdir):
+ os.remove(tmpfile)
+ except:
+ logging.warning("_check_file: tmpfile removal failed")
+
+ # Write the keyring to a temp file, then move the new file
+ # to avoid overwriting the existing inode
+ (fd, fname) = mkstemp(dir=keyringdir)
+ with os.fdopen(fd, "w") as config_file:
config.write(config_file)
- # copy will overwrite but move will not
- shutil.copy(storage_root + "/" + tmpfile,self.file_path)
- # wipe out tmpfile
- os.remove(storage_root + "/" + tmpfile)
+ os.chmod(fname, os.stat(self.file_path).st_mode)
+ shutil.move(fname, self.file_path)
class PlaintextKeyring(BaseKeyring):
@@ -294,27 +303,15 @@ class EncryptedKeyring(Encrypted, BaseKe
return False
self._migrate()
- lockdir = os.path.dirname(self.file_path)
- # lock access to the file_path here, make sure it's not being written
- # to while while we're checking for keyring-setting
- with lockutils.lock(lockfile,external=True,lock_path=lockdir):
- config = configparser.RawConfigParser()
- config.read(self.file_path)
- try:
- config.get(
- escape_for_ini('keyring-setting'),
- escape_for_ini('password reference'),
- )
- except (configparser.NoSectionError, configparser.NoOptionError):
- return False
-
- # remove any residual temporary files here
- try:
- for tmpfile in glob.glob(os.path.dirname(self.file_path) + "/" + "tmpfile.*"):
- os.remove(tmpfile)
- except:
- logging.warning("_check_file: tmpfile removal failed")
-
+ config = configparser.RawConfigParser()
+ config.read(self.file_path)
+ try:
+ config.get(
+ escape_for_ini('keyring-setting'),
+ escape_for_ini('password reference'),
+ )
+ except (configparser.NoSectionError, configparser.NoOptionError):
+ return False
return True