From: Michael Tremer Date: Wed, 26 Mar 2025 14:43:13 +0000 (+0000) Subject: python: execute: Implement bind-mounting mountpoints X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cc189cbd9c0ea49943634d4d6ea3a2957c46ff0c;p=pakfire.git python: execute: Implement bind-mounting mountpoints Signed-off-by: Michael Tremer --- diff --git a/src/python/pakfire.c b/src/python/pakfire.c index 884020b6..3c393857 100644 --- a/src/python/pakfire.c +++ b/src/python/pakfire.c @@ -566,7 +566,9 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* struct pakfire_input_buffer input = {}; struct pakfire_jail* jail = NULL; struct pakfire_env* env = NULL; + PyObject* mountpoint = NULL; const char** argv = NULL; + PyObject* bind = NULL; PyObject* ret = NULL; PyObject* k = NULL; PyObject* v = NULL; @@ -585,6 +587,7 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* const char* kwlist[] = { "command", "environ", + "bind", "nice", "return_output", "input", @@ -592,8 +595,8 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* }; // Parse arguments - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oiby#", (char**)kwlist, - &command, &environ, &nice, &return_output, &input.data, &input.length)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiby#", (char**)kwlist, + &command, &environ, &bind, &nice, &return_output, &input.data, &input.length)) goto ERROR; // Check if command is a list @@ -694,6 +697,42 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* } } + // Bind all mountpoints + if (bind) { + // Check if bind is a sequence, but it cannot be a string itself + if (!PySequence_Check(bind) || PyUnicode_Check(bind)) { + PyErr_SetString(PyExc_TypeError, "bind must be a sequence"); + goto ERROR; + } + + // Add all mountpoints + for (int i = 0; i < PySequence_Length(bind); i++) { + mountpoint = PySequence_GetItem(bind, i); + if (!mountpoint) + goto ERROR; + + // All elements must be strings + if (!PyUnicode_Check(mountpoint)) { + PyErr_SetString(PyExc_TypeError, "bind mountpoints must be strings"); + goto ERROR; + } + + // Fetch the string + const char* s = PyUnicode_AsUTF8(mountpoint); + + // Bind! + r = pakfire_jail_bind(jail, s, s, 0); + if (r < 0) { + errno = -r; + PyErr_SetFromErrno(PyExc_OSError); + goto ERROR; + } + + Py_DECREF(mountpoint); + mountpoint = NULL; + } + } + Py_BEGIN_ALLOW_THREADS // Execute command @@ -740,6 +779,7 @@ ERROR: Py_XDECREF(output.stdout); Py_XDECREF(output.stderr); + Py_XDECREF(mountpoint); return ret; } diff --git a/tests/python/execute.py b/tests/python/execute.py index c2ce2e89..30ddcebd 100755 --- a/tests/python/execute.py +++ b/tests/python/execute.py @@ -122,6 +122,23 @@ class ExecuteTests(tests.TestCase): with self.assertRaises(pakfire.CommandExecutionError): self.pakfire.execute(["/does-not-exist"], input=b"1234") + def test_execute_bind(self): + """ + Tries to bind-mount something + """ + # Try to mount the + mountpoint = self.path() + + # Check if this is actually a mountpoint + self.pakfire.execute(["/command", "check-mountpoint", mountpoint], bind=[mountpoint]) + + # Try some invalid inputs + with self.assertRaises(TypeError): + self.pakfire.execute(["/command", "exit-with-code", "0"], bind="/something") + + with self.assertRaises(TypeError): + self.pakfire.execute(["/command", "exit-with-code", "0"], bind=[123]) + def test_nice(self): """ Check if the jail is able to set the nice level