From f4c02899a1ea8ccd69278d7314be0b1409c8fa66 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Wed, 31 Oct 2012 22:11:42 -0400 Subject: [PATCH] Update KillFilter to handle 'deleted' exe's. Updates KillFilter so that it handles the case where the executable linked to by /proc/PID/exe is updated or deleted. Includes new test case with coverage for this fix as well. Fixes LP Bug #1073768 Change-Id: If568693e0b491f8806ff0156701766929ca0b3e0 --- quantum/rootwrap/filters.py | 4 ++++ quantum/tests/unit/test_rootwrap.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/quantum/rootwrap/filters.py b/quantum/rootwrap/filters.py index 2e0e12c9a3c..06b38e1c021 100644 --- a/quantum/rootwrap/filters.py +++ b/quantum/rootwrap/filters.py @@ -158,6 +158,10 @@ def match(self, userargs): try: command = os.readlink("/proc/%d/exe" % int(args[1])) + # 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 doesn't match return False diff --git a/quantum/tests/unit/test_rootwrap.py b/quantum/tests/unit/test_rootwrap.py index 427c7da137c..1c5b6963913 100644 --- a/quantum/tests/unit/test_rootwrap.py +++ b/quantum/tests/unit/test_rootwrap.py @@ -17,6 +17,7 @@ import os import subprocess +import mock import unittest2 as unittest from quantum.common import utils @@ -35,6 +36,9 @@ def setUp(self): filters.CommandFilter("/nonexistant/cat", "root"), filters.CommandFilter("/bin/cat", "root")] # Keep this one last + def tearDown(self): + super(RootwrapTestCase, self).tearDown() + def test_RegExpFilter_match(self): usercmd = ["ls", "/root"] filtermatch = wrapper.match_filter(self.filters, usercmd) @@ -112,6 +116,16 @@ def test_KillFilter_no_raise(self): usercmd = ['kill', 'notapid'] self.assertFalse(f.match(usercmd)) + def test_KillFilter_deleted_exe(self): + """Makes sure deleted exe's are killed correctly""" + # See bug #1073768. + with mock.patch('os.readlink') as mock_readlink: + mock_readlink.return_value = '/bin/commandddddd (deleted)' + f = filters.KillFilter("root", "/bin/commandddddd") + usercmd = ['kill', 1234] + self.assertTrue(f.match(usercmd)) + mock_readlink.assert_called_once_with("/proc/1234/exe") + def test_ReadFileFilter(self): goodfn = '/good/file.name' f = filters.ReadFileFilter(goodfn)