diff options
author | Dirk Mueller <dirk@dmllr.de> | 2013-05-18 12:17:59 +0200 |
---|---|---|
committer | Dirk Mueller <dirk@dmllr.de> | 2013-06-12 20:00:45 +0200 |
commit | 8b95b1e91d46f1bc7a37d210dc15e6f4072afaaa (patch) | |
tree | abb62f5cae6c6dbdb6d61cdfd00ffad2627ce91b | |
parent | 706fa4b31d1e13ab8774bcd10a917849d14033d9 (diff) | |
download | oslo-8b95b1e91d46f1bc7a37d210dc15e6f4072afaaa.tar.gz oslo-8b95b1e91d46f1bc7a37d210dc15e6f4072afaaa.tar.xz oslo-8b95b1e91d46f1bc7a37d210dc15e6f4072afaaa.zip |
Handle relative path arguments in Killfilter
KillFilter currently expects an absolute path
to be specified for the process name to kill. This
is inconvenient when the exact location of the running
binary is not known or differs accross installs.
Extend KillFilter to accept also commands in $PATH
to be killed if the given argument is not absolute.
Change-Id: I6b90206b587ff3f949af2c256a78ca21af31867a
-rw-r--r-- | openstack/common/rootwrap/filters.py | 35 | ||||
-rw-r--r-- | tests/unit/test_rootwrap.py | 14 |
2 files changed, 36 insertions, 13 deletions
diff --git a/openstack/common/rootwrap/filters.py b/openstack/common/rootwrap/filters.py index ae7c62c..0cc55ce 100644 --- a/openstack/common/rootwrap/filters.py +++ b/openstack/common/rootwrap/filters.py @@ -34,7 +34,7 @@ class CommandFilter(object): if self.real_exec is not None: return self.real_exec self.real_exec = "" - if self.exec_path.startswith('/'): + if os.path.isabs(self.exec_path): if os.access(self.exec_path, os.X_OK): self.real_exec = self.exec_path else: @@ -164,8 +164,10 @@ class DeprecatedDnsmasqFilter(DnsmasqFilter): class KillFilter(CommandFilter): """Specific filter for the kill calls. + 1st argument is the user to run /bin/kill under 2nd argument is the location of the affected executable + if the argument is not absolute, it is checked against $PATH Subsequent arguments list the accepted signals (if any) This filter relies on /proc to accurately determine affected @@ -194,21 +196,28 @@ class KillFilter(CommandFilter): return False try: command = os.readlink("/proc/%d/exe" % int(args[1])) - # NOTE(yufang521247): /proc/PID/exe may have '\0' on the - # end, because python doen't stop at '\0' when read the - # target path. - command = command.split('\0')[0] - # NOTE(dprince): /proc/PID/exe may have ' (deleted)' on - # the end if an executable is updated or deleted - if command.endswith(" (deleted)"): - command = command[:command.rindex(" ")] - if command != self.args[0]: - # Affected executable does not match - return False except (ValueError, OSError): # Incorrect PID return False - return True + + # NOTE(yufang521247): /proc/PID/exe may have '\0' on the + # end, because python doen't stop at '\0' when read the + # target path. + command = command.partition('\0')[0] + + # NOTE(dprince): /proc/PID/exe may have ' (deleted)' on + # the end if an executable is updated or deleted + if command.endswith(" (deleted)"): + command = command[:-len(" (deleted)")] + + kill_command = self.args[0] + + if os.path.isabs(kill_command): + return kill_command == command + + return (os.path.isabs(command) and + kill_command == os.path.basename(command) and + os.path.dirname(command) in os.environ['PATH'].split(':')) class ReadFileFilter(CommandFilter): diff --git a/tests/unit/test_rootwrap.py b/tests/unit/test_rootwrap.py index 25b2051..0e08b5e 100644 --- a/tests/unit/test_rootwrap.py +++ b/tests/unit/test_rootwrap.py @@ -107,6 +107,20 @@ class RootwrapTestCase(utils.BaseTestCase): usercmd = ['kill', p.pid] # Providing no signal should work self.assertTrue(f.match(usercmd) or f2.match(usercmd)) + + # verify that relative paths are matched against $PATH + f = filters.KillFilter("root", "cat") + # Our own PID does not match so it should fail + usercmd = ['kill', os.getpid()] + self.assertFalse(f.match(usercmd)) + # Filter should find cat in /bin or /usr/bin + usercmd = ['kill', p.pid] + self.assertTrue(f.match(usercmd)) + # Filter shouldn't be able to find binary in $PATH, so fail + with fixtures.EnvironmentVariable("PATH", "/foo:/bar"): + self.assertFalse(f.match(usercmd)) + pass + finally: # Terminate the "cat" process and wait for it to finish p.terminate() |