-
Notifications
You must be signed in to change notification settings - Fork 4
Jv rox 33034 track xattr changes test all events #864
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: jv-ROX-33034-track-xattr-changes
Are you sure you want to change the base?
Changes from all commits
a6c0405
b9efab6
26b9c59
a24d4fe
3f224bf
3a60638
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,7 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import subprocess | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from shutil import rmtree | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from tempfile import NamedTemporaryFile, mkdtemp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from time import sleep | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -12,8 +13,41 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import requests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import yaml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from event import Event, EventType, Process | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from server import FileActivityService | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_dockerd_process() -> Process | None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result = subprocess.run( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ['pgrep', 'dockerd'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| capture_output=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| text=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if result.returncode != 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pid = int(result.stdout.strip().split('\n')[0]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| proc = Process.from_proc(pid) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Process.from_proc uses os.path.realpath on /proc/<pid>/exe, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # which may not resolve across mount namespaces (e.g. CoreOS). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Use the path from pgrep -a instead. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result = subprocess.run( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ['pgrep', '-a', 'dockerd'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| capture_output=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| text=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exe_path = result.stdout.strip().split('\n')[0].split()[1] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+33
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Avoid mixed process identity and brittle parsing in the second Line 33-38 can pair Suggested fix- result = subprocess.run(
+ result = subprocess.run(
['pgrep', '-a', 'dockerd'],
capture_output=True,
text=True,
)
- exe_path = result.stdout.strip().split('\n')[0].split()[1]
+ if result.returncode != 0:
+ return None
+
+ exe_path = None
+ for line in result.stdout.splitlines():
+ parts = line.split(maxsplit=1)
+ if len(parts) != 2:
+ continue
+ if parts[0] != str(pid):
+ continue
+ cmdline = parts[1].strip()
+ if not cmdline:
+ continue
+ exe_path = cmdline.split()[0]
+ break
+ if exe_path is None:
+ return None📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Process( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pid=None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uid=proc.uid, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gid=proc.gid, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exe_path=exe_path, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args=proc.args, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name=proc.name, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| container_id=proc.container_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loginuid=proc.loginuid, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Declare files holding fixtures | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pytest_plugins = ['test_editors.commons'] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -185,6 +219,47 @@ def test_container( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| container.remove() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @pytest.fixture | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def docker_selinux_xattr( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| docker_client: docker.DockerClient, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| monitored_dir: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| test_file: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> list[Event]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Expected xattr events from Docker SELinux relabeling. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| When Docker creates a container with ':z' volume mounts, it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| relabels files with security.selinux. This fixture returns the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expected events if Docker has SELinux enabled, or an empty list | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| otherwise. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Docker relabels both the file and its parent directory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| info = docker_client.info() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| selinux = any('selinux' in opt for opt in info.get('SecurityOptions', [])) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not selinux: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dockerd = get_dockerd_process() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if dockerd is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Event( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process=dockerd, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event_type=EventType.XATTR_SET, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file='', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| host_path=test_file, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| xattr_name='security.selinux', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Event( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process=dockerd, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| event_type=EventType.XATTR_SET, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file='', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| host_path=monitored_dir, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| xattr_name='security.selinux', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @pytest.fixture(autouse=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def fact( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| request: pytest.FixtureRequest, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Harden dockerd discovery failure paths.
Line 21 and Line 29 can raise (
pgrepunavailable, PID race on/proc), which aborts tests instead of gracefully returningNonelike the rest of this helper intends.Suggested fix
🧰 Tools
🪛 ast-grep (0.44.0)
[error] 20-24: Command coming from incoming request
Context: subprocess.run(
['pgrep', 'dockerd'],
capture_output=True,
text=True,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
🤖 Prompt for AI Agents