Skip to content

Commit 5285bef

Browse files
authored
Support java profiling without root privilege in a container (#987)
* Support Java sudoless profiling Signed-off-by: Min Lim <min.yeol.lim@intel.com> * Fix linter issue Signed-off-by: Min Lim <min.yeol.lim@intel.com> --------- Signed-off-by: Min Lim <min.yeol.lim@intel.com>
1 parent 1523207 commit 5285bef

2 files changed

Lines changed: 16 additions & 8 deletions

File tree

gprofiler/profilers/java.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
get_process_nspid,
5555
resolve_proc_root_links,
5656
run_in_ns_wrapper,
57+
is_root,
5758
)
5859
from granulate_utils.linux.oom import get_oom_entry
5960
from granulate_utils.linux.process import (
@@ -527,7 +528,7 @@ def __init__(
527528
# ancestor is still alive.
528529
# there is a hidden assumption here that neither the ancestor nor the process will change their mount
529530
# namespace. I think it's okay to assume that.
530-
self._process_root = get_proc_root_path(process)
531+
self._process_root = get_proc_root_path(process, from_ancestor=True if is_root() else False)
531532
self._cmdline = process.cmdline()
532533
self._cwd = process.cwd()
533534
self._nspid = get_process_nspid(self.process.pid)
@@ -583,6 +584,11 @@ def _find_rw_exec_dir(self) -> str:
583584
if not full_dir.parent.exists():
584585
continue # we do not create the parent.
585586

587+
# Bypass the root check in case of rootless collection
588+
if not is_root():
589+
logger.debug("_find_rw_exec_dir", full_dir=full_dir)
590+
return str(full_dir)
591+
586592
if not is_owned_by_root(full_dir.parent):
587593
continue # the parent needs to be owned by root
588594

@@ -606,9 +612,11 @@ def __enter__(self: T) -> T:
606612
# for sanity & simplicity, mkdir_owned_root() does not support creating parent directories, as this allows
607613
# the caller to absentmindedly ignore the check of the parents ownership.
608614
# hence we create the structure here part by part.
609-
assert is_owned_by_root(
610-
Path(self._ap_dir_base)
611-
), f"expected {self._ap_dir_base} to be owned by root at this point"
615+
# Bypass the root check in case of rootless collection
616+
if is_root():
617+
assert is_owned_by_root(
618+
Path(self._ap_dir_base)
619+
), f"expected {self._ap_dir_base} to be owned by root at this point"
612620
mkdir_owned_root(self._ap_dir_versioned)
613621
mkdir_owned_root(self._ap_dir_host)
614622
os.makedirs(self._storage_dir_host, 0o755, exist_ok=True)

gprofiler/utils/fs.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,16 @@ def mkdir_owned_root(path: Union[str, Path], mode: int = 0o755) -> None:
112112
If the directory exists and is not owned by root, it is removed and recreated. If after recreation
113113
it is still not owned by root, the function raises.
114114
"""
115-
assert is_root() # this function behaves as we expect only when run as root
116115

117116
path = path if isinstance(path, Path) else Path(path)
118117
# parent is expected to be root - otherwise, after we create the root-owned directory, it can be removed
119118
# as re-created as non-root by a regular user.
120-
if not is_owned_by_root(path.parent):
119+
if is_root() and not is_owned_by_root(path.parent):
121120
raise Exception(f"expected {path.parent} to be owned by root!")
122121

123122
if path.exists():
124-
if is_owned_by_root(path):
123+
return
124+
if is_root() and is_owned_by_root(path):
125125
return
126126

127127
shutil.rmtree(path)
@@ -132,6 +132,6 @@ def mkdir_owned_root(path: Union[str, Path], mode: int = 0o755) -> None:
132132
# likely racing with another thread of gprofiler. as long as the directory is root after all, we're good.
133133
pass
134134

135-
if not is_owned_by_root(path):
135+
if is_root() and not is_owned_by_root(path):
136136
# lost race with someone else?
137137
raise Exception(f"Failed to create directory {str(path)} as owned by root")

0 commit comments

Comments
 (0)