Sertonix cd56127d1d testing/py3-libacl: do not rely on UB
This causes a memory leak but IMHO that is much better than the
use-after-free which existed previously
2025-10-16 21:58:39 +00:00

77 lines
2.3 KiB
Diff

Ref https://github.com/iustin/pylibacl/commit/65e6c78eb9338c8b3ac77b89880ca4f5f85d62b5
--- a/acl.c
+++ b/acl.c
@@ -90,12 +90,14 @@ typedef struct {
typedef struct {
PyObject_HEAD
PyObject *parent_acl; /* The parent acl, so it won't run out on us */
+ acl_t true_parent_acl;
acl_entry_t entry;
} Entry_Object;
typedef struct {
PyObject_HEAD
PyObject *parent_entry; /* The parent entry, so it won't run out on us */
+ acl_t true_parent_acl;
acl_permset_t permset;
} Permset_Object;
@@ -231,10 +233,7 @@ static int ACL_init(PyObject* obj, PyObject* args, PyObject *keywds) {
return -1;
}
- /* Free the old acl_t without checking for error, we don't
- * care right now */
- if(self->acl != NULL)
- acl_free(self->acl);
+ // May still have reference to self->acl. Don't free it since memory leak is better than UB
self->acl = new;
@@ -606,6 +605,7 @@ static PyObject* ACL_iternext(PyObject *obj) {
the_entry_obj->entry = the_entry_t;
the_entry_obj->parent_acl = obj;
+ the_entry_obj->true_parent_acl = self->acl;
Py_INCREF(obj); /* For the reference we have in entry->parent */
return (PyObject*)the_entry_obj;
@@ -635,9 +635,16 @@ static PyObject* ACL_delete_entry(PyObject *obj, PyObject *args) {
"Can't remove un-owned entry");
return NULL;
}
+ if (e->true_parent_acl != self->acl) {
+ PyErr_SetString(PyExc_ValueError,
+ "Can't remove entry after reinitialization");
+ return NULL;
+ }
if(acl_delete_entry(self->acl, e->entry) == -1)
return PyErr_SetFromErrno(PyExc_IOError);
+ e->entry = NULL;
+
Py_RETURN_NONE;
}
@@ -799,6 +806,7 @@ static PyObject* Entry_new(PyTypeObject* type, PyObject* args,
}
Py_INCREF(parent);
entry->parent_acl = (PyObject*)parent;
+ entry->true_parent_acl = parent->acl;
return newentry;
}
@@ -815,6 +823,11 @@ static int Entry_init(PyObject* obj, PyObject* args, PyObject *keywds) {
"Can't reinitialize with a different parent");
return -1;
}
+ if ((PyObject*)parent != self->parent_acl) {
+ PyErr_SetString(PyExc_ValueError,
+ "Can't reinitialize with a reinitialized parent");
+ return -1;
+ }
return 0;
}