The branch, master has been updated via 61670169d52 Clean up reference used with PyDict_Setxxx via 2814690d8fc Cleanup (decref) some objects added to list. via e29c34942dc decref results of PyStr_FromString via 85b7574b91f pidl: Fix Generated ndr python code to DECREF imported modules via 53d973f59c3 Cleanup references to module objects returned from PyImport_ImportModule via 1be9b0cf1bc Examine result of SetList (and prevent sending NULL to PyList_SetItem) via a8e10a12493 Decrement references to python objects passed to Py_BuildValue from bf91ee0a972 tldap: avoid more use after free errors
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 61670169d5241f742bc80bec37b02800af8c8517 Author: Noel Power <noel.po...@suse.com> Date: Thu Jan 31 17:01:26 2019 +0000 Clean up reference used with PyDict_Setxxx PyDictSetxxx methods don't steal reference so if the items added to the dictionary were created just for the purpose of inserting into the dict then we need to decref them. Signed-off-by: Noel Power <noel.po...@suse.com> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Autobuild-User(master): Noel Power <npo...@samba.org> Autobuild-Date(master): Thu Feb 7 17:17:46 CET 2019 on sn-devel-144 commit 2814690d8fc302e79b041b3175e85bef1ac98e51 Author: Noel Power <noel.po...@suse.com> Date: Wed Jan 23 18:43:43 2019 +0000 Cleanup (decref) some objects added to list. PyList_Append doesn't steal references, so if the item created is a temp object, created just to be added to the list we need to decref the item appended in order for it to be released. Signed-off-by: Noel Power <noel.po...@suse.com> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit e29c34942dcc29721f8f3dc8dbb58a18afda1e60 Author: Noel Power <noel.po...@suse.com> Date: Wed Jan 23 18:08:58 2019 +0000 decref results of PyStr_FromString Where we create temporary objects (which are added to containers) these objects already get there ref count incremented. In this case we need to decref those objects to ensure they are released. Signed-off-by: Noel Power <noel.po...@suse.com> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 85b7574b91f3dfcf751de8ae81876dc64fc5e686 Author: Noel Power <noel.po...@suse.com> Date: Wed Jan 23 17:10:44 2019 +0000 pidl: Fix Generated ndr python code to DECREF imported modules Generated code calls Py_ImportModule but in all error returns and also successful exit the code fails to decrement reference to loaded modules in MODULE_INIT_FUNC function. Signed-off-by: Noel Power <noel.po...@suse.com> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 53d973f59c3514f9c288cc8e53a682176a5fc415 Author: Noel Power <noel.po...@suse.com> Date: Wed Jan 23 15:15:07 2019 +0000 Cleanup references to module objects returned from PyImport_ImportModule Signed-off-by: Noel Power <noel.po...@suse.com> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 1be9b0cf1bc95715e83c27eabecbd4fa2022530b Author: Noel Power <noel.po...@suse.com> Date: Fri Jan 25 12:02:50 2019 +0000 Examine result of SetList (and prevent sending NULL to PyList_SetItem) Signed-off-by: Noel Power <noel.po...@suse.com> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit a8e10a12493fdb6b8347b14e157aeb619cf2d2da Author: Noel Power <noel.po...@suse.com> Date: Tue Jan 22 18:26:23 2019 +0000 Decrement references to python objects passed to Py_BuildValue Py_BuildValue when processing format 'O' will 'Pass a Python object untouched (except for its reference count, which is incremented by one' Basically this means if you are using a new reference to a PyObject to pass to BuildValue (to be used with the 'O' format) the reference *isn't* stolen so you really do need to DECREF it in order to ensure it gets cleaned up. Signed-off-by: Noel Power <noel.po...@suse.com> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: auth/credentials/pycredentials.c | 7 +- lib/ldb-samba/pyldb.c | 10 +- lib/ldb/pyldb.c | 79 ++++++- pidl/lib/Parse/Pidl/Samba4/Python.pm | 18 +- source3/libsmb/pylibsmb.c | 8 +- source3/passdb/py_passdb.c | 437 +++++++++++++++++++++-------------- source4/dns_server/pydns.c | 6 +- source4/dsdb/pydsdb.c | 23 +- source4/lib/policy/pypolicy.c | 18 +- source4/libnet/py_net.c | 12 +- source4/librpc/ndr/py_auth.c | 1 + source4/librpc/ndr/py_security.c | 1 + source4/librpc/ndr/py_xattr.c | 1 + source4/librpc/rpc/pyrpc.c | 30 ++- source4/librpc/rpc/pyrpc_util.c | 7 +- source4/param/provision.c | 23 +- 16 files changed, 453 insertions(+), 228 deletions(-) Changeset truncated at 500 lines: diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c index d1ee12e45a9..1b86e001557 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -75,9 +75,10 @@ static PyObject *py_creds_get_ntlm_username_domain(PyObject *self, PyObject *unu PyObject *ret = NULL; cli_credentials_get_ntlm_username_domain(PyCredentials_AsCliCredentials(self), frame, &user, &domain); - ret = Py_BuildValue("(OO)", - PyString_FromStringOrNULL(user), - PyString_FromStringOrNULL(domain)); + ret = Py_BuildValue("(ss)", + user, + domain); + TALLOC_FREE(frame); return ret; } diff --git a/lib/ldb-samba/pyldb.c b/lib/ldb-samba/pyldb.c index 57c5397bc06..0cf550bc7a5 100644 --- a/lib/ldb-samba/pyldb.c +++ b/lib/ldb-samba/pyldb.c @@ -180,8 +180,10 @@ static PyObject *py_ldb_set_session_info(PyObject *self, PyObject *args) return NULL; PyAuthSession_Type = PyObject_GetAttrString(mod_samba_auth, "session_info"); - if (PyAuthSession_Type == NULL) + if (PyAuthSession_Type == NULL) { + Py_CLEAR(mod_samba_auth); return NULL; + } ret = PyArg_ParseTuple(args, "O!", PyAuthSession_Type, &py_session_info); @@ -262,11 +264,15 @@ MODULE_INIT_FUNC(_ldb) return NULL; PySambaLdb.tp_base = (PyTypeObject *)PyObject_GetAttrString(pyldb_module, "Ldb"); - if (PySambaLdb.tp_base == NULL) + if (PySambaLdb.tp_base == NULL) { + Py_CLEAR(pyldb_module); return NULL; + } py_ldb_error = PyObject_GetAttrString(pyldb_module, "LdbError"); + Py_CLEAR(pyldb_module); + if (PyType_Ready(&PySambaLdb) < 0) return NULL; diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 8e48fa5d56d..3deb393e467 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -1673,9 +1673,13 @@ static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif) Py_RETURN_NONE; } else { /* We don't want this attached to the 'ldb' any more */ - return Py_BuildValue(discard_const_p(char, "(iO)"), - ldif->changetype, - PyLdbMessage_FromMessage(ldif->msg)); + PyObject *obj = PyLdbMessage_FromMessage(ldif->msg); + PyObject *result = + Py_BuildValue(discard_const_p(char, "(iO)"), + ldif->changetype, + obj); + Py_CLEAR(obj); + return result; } } @@ -1737,7 +1741,21 @@ static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args) ldif = ldb_ldif_read_string(self->ldb_ctx, &s); talloc_steal(mem_ctx, ldif); if (ldif) { - PyList_Append(list, ldb_ldif_to_pyobject(ldif)); + int res = 0; + PyObject *py_ldif = ldb_ldif_to_pyobject(ldif); + if (py_ldif == NULL) { + Py_CLEAR(list); + PyErr_BadArgument(); + talloc_free(mem_ctx); + return NULL; + } + res = PyList_Append(list, py_ldif); + Py_CLEAR(py_ldif); + if (res == -1) { + Py_CLEAR(list); + talloc_free(mem_ctx); + return NULL; + } last_dn = ldif->msg->dn; } else { const char *last_dn_str = NULL; @@ -1746,6 +1764,7 @@ static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args) PyErr_SetString(PyExc_ValueError, "unable to parse LDIF " "string at first chunk"); + Py_CLEAR(list); talloc_free(mem_ctx); return NULL; } @@ -1762,6 +1781,7 @@ static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args) PyErr_SetString(PyExc_ValueError, err_string); talloc_free(mem_ctx); + Py_CLEAR(list); return NULL; } } @@ -2197,8 +2217,24 @@ static PyObject *py_ldb_modules(PyLdbObject *self) PyObject *ret = PyList_New(0); struct ldb_module *mod; + if (ret == NULL) { + return PyErr_NoMemory(); + } for (mod = ldb->modules; mod; mod = mod->next) { - PyList_Append(ret, PyLdbModule_FromModule(mod)); + PyObject *item = PyLdbModule_FromModule(mod); + int res = 0; + if (item == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "Failed to load LdbModule"); + Py_CLEAR(ret); + return NULL; + } + res = PyList_Append(ret, item); + Py_CLEAR(item); + if (res == -1) { + Py_CLEAR(ret); + return NULL; + } } return ret; @@ -3426,14 +3462,41 @@ static PyObject *py_ldb_msg_items(PyLdbMessageObject *self) struct ldb_message *msg = pyldb_Message_AsMessage(self); Py_ssize_t i, j = 0; PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1)); + if (l == NULL) { + return PyErr_NoMemory(); + } if (msg->dn != NULL) { - PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", pyldb_Dn_FromDn(msg->dn))); + PyObject *value = NULL; + PyObject *obj = pyldb_Dn_FromDn(msg->dn); + int res = 0; + value = Py_BuildValue("(sO)", "dn", obj); + Py_CLEAR(obj); + if (value == NULL) { + Py_CLEAR(l); + return NULL; + } + res = PyList_SetItem(l, 0, value); + if (res == -1) { + Py_CLEAR(l); + return NULL; + } j++; } for (i = 0; i < msg->num_elements; i++, j++) { + PyObject *value = NULL; PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements); - PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el); - PyList_SetItem(l, j, value); + int res = 0; + Py_CLEAR(py_el); + value = Py_BuildValue("(sO)", msg->elements[i].name, py_el); + if (value == NULL ) { + Py_CLEAR(l); + return NULL; + } + res = PyList_SetItem(l, 0, value); + if (res == -1) { + Py_CLEAR(l); + return NULL; + } } return l; } diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm index 5697b52c4fe..efa80d7cdd1 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -2367,9 +2367,9 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $self->pidl("MODULE_INIT_FUNC($basename)"); $self->pidl("{"); $self->indent; - $self->pidl("PyObject *m;"); + $self->pidl("PyObject *m = NULL;"); foreach my $h (@{$self->{module_imports}}) { - $self->pidl("PyObject *$h->{'key'};"); + $self->pidl("PyObject *$h->{'key'} = NULL;"); } $self->pidl(""); @@ -2378,7 +2378,7 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) my $module_path = $h->{'val'}; $self->pidl("$var_name = PyImport_ImportModule(\"$module_path\");"); $self->pidl("if ($var_name == NULL)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); $self->pidl(""); } @@ -2391,7 +2391,7 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $module_var =~ s/\./_/g; $self->pidl("$type_var = (PyTypeObject *)PyObject_GetAttrString($module_var, \"$pretty_name\");"); $self->pidl("if ($type_var == NULL)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); $self->pidl(""); } @@ -2399,7 +2399,7 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) foreach (@{$self->{ready_types}}) { $self->pidl("if (PyType_Ready($_) < 0)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); } $self->pidl($_) foreach (@{$self->{postreadycode}}); @@ -2415,7 +2415,7 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $self->pidl("m = PyModule_Create(&moduledef);"); $self->pidl("if (m == NULL)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); $self->pidl(""); foreach my $h (@{$self->{constants}}) { my $pretty_name = PrettifyTypeName($h->{'key'}, $basename); @@ -2441,7 +2441,11 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $self->pidl("#ifdef PY_MOD_".uc($basename)."_PATCH"); $self->pidl("PY_MOD_".uc($basename)."_PATCH(m);"); $self->pidl("#endif"); - + $self->pidl("out:"); + foreach my $h (@{$self->{module_imports}}) { + my $mod_var = $h->{'key'}; + $self->pidl("Py_XDECREF($mod_var);"); + } $self->pidl("return m;"); $self->pidl(""); $self->deindent; diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c index 629ff0a4fd3..5f3e6a8c724 100644 --- a/source3/libsmb/pylibsmb.c +++ b/source3/libsmb/pylibsmb.c @@ -1124,13 +1124,14 @@ static NTSTATUS list_helper(const char *mntpoint, struct file_info *finfo, { PyObject *result = (PyObject *)state; PyObject *file = NULL; + PyObject *size = NULL; int ret; /* suppress '.' and '..' in the results we return */ if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) { return NT_STATUS_OK; } - + size = PyLong_FromUnsignedLongLong(finfo->size); /* * Build a dictionary representing the file info. * Note: Windows does not always return short_name (so it may be None) @@ -1139,15 +1140,18 @@ static NTSTATUS list_helper(const char *mntpoint, struct file_info *finfo, "name", finfo->name, "attrib", (int)finfo->mode, "short_name", finfo->short_name, - "size", PyLong_FromUnsignedLongLong(finfo->size), + "size", size, "mtime", convert_timespec_to_time_t(finfo->mtime_ts)); + Py_CLEAR(size); + if (file == NULL) { return NT_STATUS_NO_MEMORY; } ret = PyList_Append(result, file); + Py_CLEAR(file); if (ret == -1) { return NT_STATUS_INTERNAL_ERROR; } diff --git a/source3/passdb/py_passdb.c b/source3/passdb/py_passdb.c index 2ac2942a47f..30273141eb7 100644 --- a/source3/passdb/py_passdb.c +++ b/source3/passdb/py_passdb.c @@ -1483,6 +1483,8 @@ static PyObject *py_pdb_domain_info(PyObject *self, PyObject *args) PyObject *py_domain_info; struct dom_sid *sid; struct GUID *guid; + PyObject *py_dom_sid = NULL; + PyObject *py_guid = NULL; methods = pytalloc_get_ptr(self); @@ -1506,18 +1508,20 @@ static PyObject *py_pdb_domain_info(PyObject *self, PyObject *args) } *guid = domain_info->guid; - if ((py_domain_info = PyDict_New()) == NULL) { - PyErr_NoMemory(); - talloc_free(frame); - return NULL; - } + py_dom_sid = pytalloc_steal(dom_sid_Type, sid); + py_guid = pytalloc_steal(guid_Type, guid); - PyDict_SetItemString(py_domain_info, "name", PyStr_FromString(domain_info->name)); - PyDict_SetItemString(py_domain_info, "dns_domain", PyStr_FromString(domain_info->dns_domain)); - PyDict_SetItemString(py_domain_info, "dns_forest", PyStr_FromString(domain_info->dns_forest)); - PyDict_SetItemString(py_domain_info, "dom_sid", pytalloc_steal(dom_sid_Type, sid)); - PyDict_SetItemString(py_domain_info, "guid", pytalloc_steal(guid_Type, guid)); + py_domain_info = Py_BuildValue( + "{s:s, s:s, s:s, s:O, s:O}", + "name", domain_info->name, + "dns_domain", domain_info->dns_domain, + "dns_forest", domain_info->dns_forest, + "dom_sid", py_dom_sid, + "guid", py_guid); + + Py_CLEAR(py_dom_sid); + Py_CLEAR(py_guid); talloc_free(frame); return py_domain_info; } @@ -2107,12 +2111,19 @@ static PyObject *py_pdb_enum_group_mapping(PyObject *self, PyObject *args) for(i=0; i<num_entries; i++) { py_group_map = py_groupmap_new(&PyGroupmap, NULL, NULL); if (py_group_map) { + int res = 0; group_map = pytalloc_get_ptr(py_group_map); *group_map = *gmap[i]; talloc_steal(group_map, gmap[i]->nt_name); talloc_steal(group_map, gmap[i]->comment); - PyList_Append(py_gmap_list, py_group_map); + res = PyList_Append(py_gmap_list, py_group_map); + Py_CLEAR(py_group_map); + if (res == -1) { + Py_CLEAR(py_gmap_list); + talloc_free(frame); + return NULL; + } } } @@ -2165,8 +2176,18 @@ static PyObject *py_pdb_enum_group_members(PyObject *self, PyObject *args) domain_sid = get_global_sam_sid(); for(i=0; i<num_members; i++) { + int res = 0; + PyObject *py_member_sid = NULL; member_sid = dom_sid_add_rid(frame, domain_sid, member_rids[i]); - PyList_Append(py_sid_list, pytalloc_steal(dom_sid_Type, member_sid)); + py_member_sid = pytalloc_steal(dom_sid_Type, member_sid); + res = PyList_Append(py_sid_list, + py_member_sid); + Py_CLEAR(py_member_sid); + if (res == -1) { + talloc_free(frame); + Py_CLEAR(py_sid_list); + return NULL; + } } talloc_free(frame); @@ -2215,7 +2236,11 @@ static PyObject *py_pdb_enum_group_memberships(PyObject *self, PyObject *args) } for(i=0; i<num_groups; i++) { - PyList_Append(py_sid_list, pytalloc_steal(dom_sid_Type, dom_sid_dup(NULL, &user_group_sids[i]))); + PyObject *py_sid = + pytalloc_steal(dom_sid_Type, + dom_sid_dup(NULL, &user_group_sids[i])); + PyList_Append(py_sid_list, py_sid); + Py_CLEAR(py_sid); } talloc_free(frame); @@ -2375,19 +2400,11 @@ static PyObject *py_pdb_get_aliasinfo(PyObject *self, PyObject *args) return NULL; } - py_alias_info = PyDict_New(); - if (py_alias_info == NULL) { - PyErr_NoMemory(); - talloc_free(frame); - return NULL; - } - - PyDict_SetItemString(py_alias_info, "acct_name", - PyStr_FromString(alias_info->acct_name)); - PyDict_SetItemString(py_alias_info, "acct_desc", - PyStr_FromString(alias_info->acct_desc)); - PyDict_SetItemString(py_alias_info, "rid", - PyInt_FromLong(alias_info->rid)); + py_alias_info = Py_BuildValue( + "{s:s, s:s, s:l}", + "acct_name", alias_info->acct_name, + "acct_desc", alias_info->acct_desc, + "rid", alias_info->rid); talloc_free(frame); return py_alias_info; @@ -2543,15 +2560,23 @@ static PyObject *py_pdb_enum_aliasmem(PyObject *self, PyObject *args) } for(i=0; i<num_members; i++) { + int res = 0; py_member_sid = pytalloc_new(struct dom_sid, dom_sid_Type); if (py_member_sid == NULL) { PyErr_NoMemory(); + Py_CLEAR(py_member_list); talloc_free(frame); return NULL; } tmp_sid = pytalloc_get_ptr(py_member_sid); *tmp_sid = member_sid[i]; - PyList_Append(py_member_list, py_member_sid); + res = PyList_Append(py_member_list, py_member_sid); + Py_CLEAR(py_member_sid); + if (res == -1) { + Py_CLEAR(py_member_list); + talloc_free(frame); + return NULL; + } } talloc_free(frame); @@ -2584,7 +2609,20 @@ static PyObject *py_pdb_get_account_policy(PyObject *self, PyObject *unused) type = account_policy_name_to_typenum(names[i]); status = methods->get_account_policy(methods, type, &value); if (NT_STATUS_IS_OK(status)) { - PyDict_SetItemString(py_acct_policy, names[i], Py_BuildValue("i", value)); + int res = 0; + PyObject *py_value = Py_BuildValue("i", value); + if (py_value == NULL) { + Py_CLEAR(py_acct_policy); + break; + } + res = PyDict_SetItemString(py_acct_policy, + names[i], + py_value); + Py_CLEAR(py_value); + if (res == -1) { + Py_CLEAR(py_acct_policy); + break; + } } } @@ -2672,21 +2710,30 @@ static PyObject *py_pdb_search_users(PyObject *self, PyObject *args) } while (search->next_entry(search, entry)) { - py_dict = PyDict_New(); + int res = 1; + py_dict = Py_BuildValue( + "{s:l, s:l, s:l, s:s, s:s, s:s}", + "idx", entry->idx, + "rid", entry->rid, + "acct_flags", entry->acct_flags, + "account_name", entry->account_name, + "fullname", entry->fullname, + "description", entry->description); if (py_dict == NULL) { - PyErr_NoMemory(); - } else { - PyDict_SetItemString(py_dict, "idx", PyInt_FromLong(entry->idx)); - PyDict_SetItemString(py_dict, "rid", PyInt_FromLong(entry->rid)); - PyDict_SetItemString(py_dict, "acct_flags", PyInt_FromLong(entry->acct_flags)); - PyDict_SetItemString(py_dict, "account_name", PyStr_FromString(entry->account_name)); - PyDict_SetItemString(py_dict, "fullname", PyStr_FromString(entry->fullname)); - PyDict_SetItemString(py_dict, "description", PyStr_FromString(entry->description)); - PyList_Append(py_userlist, py_dict); + Py_CLEAR(py_userlist); + goto out; + } + + res = PyList_Append(py_userlist, py_dict); + Py_CLEAR(py_dict); + if (res == -1) { + Py_CLEAR(py_userlist); + goto out; } } search->search_end(search); +out: talloc_free(frame); return py_userlist; } @@ -2730,21 +2777,30 @@ static PyObject *py_pdb_search_groups(PyObject *self, PyObject *unused) } -- Samba Shared Repository