diff options
author | Jenkins <jenkins@review.openstack.org> | 2013-06-12 22:00:04 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2013-06-12 22:00:04 +0000 |
commit | fb13686a00e933c17bca163b51fb3d7119d34e5a (patch) | |
tree | 35abd4ff5686b515ddb7753536e2571f2c286f1f | |
parent | f9cc093ab6c3f34bd2f3bceb831ba6b937704a54 (diff) | |
parent | 8b95b1e91d46f1bc7a37d210dc15e6f4072afaaa (diff) | |
download | oslo-fb13686a00e933c17bca163b51fb3d7119d34e5a.tar.gz oslo-fb13686a00e933c17bca163b51fb3d7119d34e5a.tar.xz oslo-fb13686a00e933c17bca163b51fb3d7119d34e5a.zip |
Merge "Handle relative path arguments in Killfilter"
-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() |