/
usr
/
lib
/
python3.9
/
site-packages
/
rhn
/
/usr/lib/python3.9/site-packages/rhn
mkdir
upload
Name
Size
Mode
Actions
actions/
-
0755
rm
__pycache__/
-
0755
rm
connections.py
666
0644
edit
dl
rm
i18n.py
1773
0644
edit
dl
rm
rhnLockfile.py
5678
0644
edit
dl
rm
rpclib.py
5416
0644
edit
dl
rm
transports.py
4048
0644
edit
dl
rm
__init__.py
132
0644
edit
dl
rm
Edit:
/usr/lib/python3.9/site-packages/rhn/rhnLockfile.py
(5678B)
# # Copyright (c) 2008--2016 Red Hat, Inc. # # This software is licensed to you under the GNU General Public License, # version 2 (GPLv2). There is NO WARRANTY for this software, express or # implied, including the implied warranties of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 # along with this software; if not, see # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. # # Red Hat trademarks are not licensed under GPLv2. No permission is # granted to use or replicate Red Hat trademarks that are incorporated # in this software or its documentation. # import os import sys import stat import fcntl from errno import EWOULDBLOCK, EEXIST from rhn.i18n import bstr import fcntl class LockfileLockedException(Exception): """thrown ONLY when pid file is locked.""" pass class Lockfile: """class that provides simple access to a PID-style lockfile. methods: __init__(lockfile), acquire(), and release() NOTE: currently acquires upon init The *.pid file will be acquired, or an LockfileLockedException is raised. """ def __init__(self, lockfile, pid=None): """create (if need be), and acquire lock on lockfile lockfile example: '/var/run/up2date.pid' """ # cleanup the path and assign it. self.lockfile = os.path.abspath( os.path.expanduser( os.path.expandvars(lockfile))) self.pid = pid if not self.pid: self.pid = os.getpid() # create the directory structure dirname = os.path.dirname(self.lockfile) if not os.path.exists(dirname): try: os.makedirs(dirname) except OSError: e = sys.exc_info()[1] if hasattr(e, 'errno') and e.errno == EEXIST: # race condition... dirname exists now. pass else: raise # open the file -- non-destructive read-write, unless it needs # to be created. O_NOFOLLOW refuses to follow a symlink planted at # the final path component and O_CLOEXEC keeps the descriptor from # leaking across exec(); this brings the lockfile open up to the # CLOS-4287 hardening the sibling root-owned os.open sites already # carry (up2date_client/up2dateLog.py, rhnreg.py, up2dateAuth.py, # config.py). O_EXCL/O_TRUNC are intentionally NOT added: a PID # lockfile legitimately pre-exists (it may be held by a live peer) # and is only truncated under flock in acquire(). self.f = os.open(self.lockfile, os.O_RDWR | os.O_CREAT | os.O_SYNC | os.O_NOFOLLOW | os.O_CLOEXEC, 0o600) # Defense-in-depth: the opened descriptor must be a regular file # owned by this process. O_NOFOLLOW only rejects a symlink at the # final component; this fstat additionally rejects a pre-planted # FIFO/device/foreign-owned file at the lock path -- closing the # reusable-library attack steelmanned in the verdict for callers # that pass a path under a non-root-owned directory. Fail closed # (refuse to operate) rather than acting on a suspicious inode. st = os.fstat(self.f) if not stat.S_ISREG(st.st_mode) or st.st_uid != os.geteuid(): os.close(self.f) raise OSError( "refusing to use lockfile %s: not a regular file owned by " "uid %d (mode 0o%o, uid %d)" % (self.lockfile, os.geteuid(), st.st_mode, st.st_uid)) self.acquire() def acquire(self): """acquire the lock; else raise LockfileLockedException.""" try: fcntl.flock(self.f, fcntl.LOCK_EX|fcntl.LOCK_NB) except IOError: if sys.exc_info()[1].errno == EWOULDBLOCK: raise LockfileLockedException( "cannot acquire lock on %s." % self.lockfile, None, sys.exc_info()[2]) else: raise # unlock upon exit fcntl.fcntl(self.f, fcntl.F_SETFD, 1) # truncate and write the pid os.ftruncate(self.f, 0) os.write(self.f, bstr(str(self.pid) + '\n')) def release(self): # Remove the lock file, but only if the path still names the exact # inode we hold open. unlink-by-path is a TOCTOU sink: if the path # was swapped (or symlinked) between open and release, a bare # os.unlink(self.lockfile) would delete the attacker's substitute. # Compare the open fd's (dev, ino) against an lstat (no symlink # follow) of the path and only unlink on a match; otherwise leave # the foreign entry alone but still release our lock and fd. try: fd_st = os.fstat(self.f) path_st = os.lstat(self.lockfile) same_inode = (fd_st.st_dev == path_st.st_dev and fd_st.st_ino == path_st.st_ino) except OSError: same_inode = False if same_inode: os.unlink(self.lockfile) fcntl.flock(self.f, fcntl.LOCK_UN) os.close(self.f) def main(): """test code""" try: L = Lockfile('./test.pid') except LockfileLockedException: sys.stderr.write("%s\n" % sys.exc_info()[1]) sys.exit(-1) else: print("lock acquired ") print("...sleeping for 10 seconds") import time time.sleep(10) L.release() print("lock released ") if __name__ == '__main__': # test code sys.exit(main() or 0)
Save
cmd:
run