Skip to content

Commit

Permalink
fix: where mode named pipe permissions
Browse files Browse the repository at this point in the history
We change the permissions on the named pipe to allow processes not
necessarily spawned by the superuse to write to it, thus allowing the
where mode to work in greater generality.
  • Loading branch information
P403n1x87 committed Oct 14, 2023
1 parent 27b4023 commit 08fcad9
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 17 deletions.
25 changes: 16 additions & 9 deletions echion/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,24 @@ def detach(pid: int) -> None:
def attach(args: argparse.Namespace) -> None:
from hypno import inject_py

script = dedent(
f"""
from echion.bootstrap.attach import attach
attach({args.__dict__!r})
"""
).strip()

pid = args.pid or args.where

try:
pipe_name = None
if args.where:
pipe_name = Path(tempfile.gettempdir()) / f"echion-{pid}"
os.mkfifo(pipe_name)
# This named pipe is likely created by the superuser, so we need to
# make it writable by everyone to allow the target process to write
# to it.
os.chmod(pipe_name, 0o666)

script = dedent(
f"""
from echion.bootstrap.attach import attach
attach({args.__dict__!r}, {repr(str(pipe_name)) if pipe_name is not None else str(None)})
"""
).strip()

inject_py(pid, script)

Expand All @@ -53,6 +58,7 @@ def attach(args: argparse.Namespace) -> None:
from time import monotonic as time

end = time() + args.exposure

while not args.where:
try:
os.kill(pid, 0)
Expand All @@ -61,11 +67,12 @@ def attach(args: argparse.Namespace) -> None:
if end is not None and time() > end:
break
os.sched_yield()

except (KeyboardInterrupt, ProcessLookupError):
pass

# Read the output
if args.where and pipe_name.exists():
if args.where and pipe_name is not None and pipe_name.exists():
with pipe_name.open("r") as f:
while True:
line = f.readline()
Expand All @@ -76,7 +83,7 @@ def attach(args: argparse.Namespace) -> None:
detach(pid)

finally:
if args.where and pipe_name.exists():
if args.where and pipe_name is not None and pipe_name.exists():
pipe_name.unlink()


Expand Down
8 changes: 7 additions & 1 deletion echion/bootstrap/attach.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import typing as t


def attach(config: t.Dict[str, str]) -> None:
def attach(config: t.Dict[str, str], pipe_name: t.Optional[str] = None) -> None:
os.environ["ECHION_CPU"] = str(int(config["cpu"]))
os.environ["ECHION_NATIVE"] = str(int(config["native"]))
os.environ["ECHION_OUTPUT"] = config["output"]
Expand All @@ -15,6 +15,12 @@ def attach(config: t.Dict[str, str]) -> None:

from echion.bootstrap import start

# This is used in where mode for IPC.
if pipe_name is not None:
from echion.core import set_pipe_name

set_pipe_name(pipe_name)

start()


Expand Down
16 changes: 16 additions & 0 deletions echion/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ static int native = 0;
// Where mode
static int where = 0;

// Pipe name (where mode IPC)
static std::string pipe_name;

// ----------------------------------------------------------------------------
static PyObject *
set_interval(PyObject *Py_UNUSED(m), PyObject *args)
Expand Down Expand Up @@ -77,3 +80,16 @@ set_where(PyObject *Py_UNUSED(m), PyObject *args)

Py_RETURN_NONE;
}

// ----------------------------------------------------------------------------
static PyObject *
set_pipe_name(PyObject *Py_UNUSED(m), PyObject *args)
{
const char *name;
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;

pipe_name = name;

Py_RETURN_NONE;
}
1 change: 1 addition & 0 deletions echion/core.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ def set_interval(interval: int) -> None: ...
def set_cpu(cpu: bool) -> None: ...
def set_native(native: bool) -> None: ...
def set_where(where: bool) -> None: ...
def set_pipe_name(name: str) -> None: ...
13 changes: 6 additions & 7 deletions echion/coremodule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,13 @@ _sampler()

if (where)
{
auto pipe_name = std::filesystem::temp_directory_path() / ("echion-" + std::to_string(getpid()));
std::ofstream pipe(pipe_name, std::ios::out);
if (!pipe)
{
std::cerr << "Failed to open pipe " << pipe_name << std::endl;
return;
}

do_where(pipe);
if (pipe)
do_where(pipe);

else
std::cerr << "Failed to open pipe " << pipe_name << std::endl;

running = 0;

Expand Down Expand Up @@ -398,6 +396,7 @@ static PyMethodDef echion_core_methods[] = {
{"set_cpu", set_cpu, METH_VARARGS, "Set whether to use CPU time instead of wall time"},
{"set_native", set_native, METH_VARARGS, "Set whether to sample the native stacks"},
{"set_where", set_where, METH_VARARGS, "Set whether to use where mode"},
{"set_pipe_name", set_pipe_name, METH_VARARGS, "Set the pipe name"},
{NULL, NULL, 0, NULL} /* Sentinel */
};

Expand Down

0 comments on commit 08fcad9

Please sign in to comment.