From 92bf4713e457813363a03261b207498df53f3a5a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 13 Nov 2024 16:19:46 +0100 Subject: [PATCH 1/2] Check the return value of PyCapsule_New() PyCapsule_New() can fail and return NULL. Check the return value and go right to OUT on failure. --- fuseparts/_fusemodule.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fuseparts/_fusemodule.c b/fuseparts/_fusemodule.c index 691b286..2e09c15 100644 --- a/fuseparts/_fusemodule.c +++ b/fuseparts/_fusemodule.c @@ -1273,8 +1273,13 @@ poll_func(const char *path, struct fuse_file_info *fi, { PyObject *pollhandle = Py_None; - if (ph) + if (ph) { pollhandle = PyCapsule_New(ph, pollhandle_name, pollhandle_destructor); + if (!pollhandle) { + PyErr_Print(); + goto OUT; + } + } #ifdef FIX_PATH_DECODING PROLOGUE(PYO_CALLWITHFI(fi, poll_cb, O&O, &Path_AsDecodedUnicode, path, pollhandle)); From 26ee2c9e4319a83eca66fd60f4bd47418c83d0f4 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 13 Nov 2024 16:20:30 +0100 Subject: [PATCH 2/2] pull PyCapsule_New() into the PYLOCK() section in poll_func() If we call PyCapsule_New() from a thread created by libfuse before ensuring the python interpreter is initialized, the thread state will be NULL and the program will crash with SEGFAULT. As suggested by David Lechner: pull the call to PyCapsule_New() into the PYLOCK() section and open-code the rest of what was previously in the PROLOGUE() macro. Closes: https://github.com/libfuse/python-fuse/issues/82 --- fuseparts/_fusemodule.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/fuseparts/_fusemodule.c b/fuseparts/_fusemodule.c index 2e09c15..8655af5 100644 --- a/fuseparts/_fusemodule.c +++ b/fuseparts/_fusemodule.c @@ -1272,6 +1272,10 @@ poll_func(const char *path, struct fuse_file_info *fi, struct fuse_pollhandle *ph, unsigned *reventsp) { PyObject *pollhandle = Py_None; + int ret = -EINVAL; + PyObject *v; + + PYLOCK(); if (ph) { pollhandle = PyCapsule_New(ph, pollhandle_name, pollhandle_destructor); @@ -1282,10 +1286,22 @@ poll_func(const char *path, struct fuse_file_info *fi, } #ifdef FIX_PATH_DECODING - PROLOGUE(PYO_CALLWITHFI(fi, poll_cb, O&O, &Path_AsDecodedUnicode, path, pollhandle)); + v = PYO_CALLWITHFI(fi, poll_cb, O&O, &Path_AsDecodedUnicode, path, pollhandle); #else - PROLOGUE(PYO_CALLWITHFI(fi, poll_cb, sO, path, pollhandle)); + v = PYO_CALLWITHFI(fi, poll_cb, sO, path, pollhandle); #endif + if (!v) { + PyErr_Print(); + goto OUT; + } + if (v == Py_None) { + ret = 0; + goto OUT_DECREF; + } + if (PyInt_Check(v)) { + ret = PyInt_AsLong(v); + goto OUT_DECREF; + } OUT_DECREF: Py_DECREF(v);