I'm constantly getting SEGFAULTs using libjail from C as well as from Python. Is it my fault or am I triggering a bug? === listjailparams.c === #include <stdio.h> #include <jail.h> int main(int argc, char *argv[]) { struct jailparam *params; int nparams = jailparam_all(¶ms); printf("number of params: %d\n", nparams); for (int i=0; i<nparams; i++) { printf("jailparam: %s\n", jailparam_export(¶ms[i])); } jailparam_free(params, nparams); return 0; } === listjailparams.c === === listjailparams.py === #!/usr/local/bin/python3 from ctypes import Structure, c_char_p, CDLL, POINTER, c_int, byref class JailParam(Structure): _fields_ = [ ("name", c_char_p), ("value", c_char_p), ] JailParam_PTR = POINTER(JailParam) lib = CDLL("libjail.so") jailparam_all = lib.jailparam_all jailparam_all.argtypes = [POINTER(JailParam_PTR)] jailparam_all.restype = c_int jailparam_free = lib.jailparam_free jailparam_free.argtypes = [JailParam_PTR, c_int] params = JailParam_PTR() nparams = jailparam_all(byref(params)) print(f'nparams: {nparams}') for i in range(nparams): param = params[i] name = param.name.decode('utf-8') value = param.value if param.value is None else param.value.decode('utf-8') print(f'Name: {name}, Value: {value}') jailparam_free(params, nparams) === listjailparams.py ===
The problem is that your code is not calling jailparam_import() or jailparam_get() (with some JID specified in the parameters). In this case, there is no value to export, i.e., jd_value == NULL and we trigger a null pointer dereference. But, the library should probably check for this case and return an error instead of crashing.
Ah, of course I'm an idiot! How can I expect any param to have a value in such a "list all possible param NAMES" call? The C program works now as expected, but I still get the SEGFAULT in Python after the first parameter (zfs.mount_snapshot). What is there still a problem? --- listjailparams.c.old 2024-02-03 20:07:04.525535000 +0100 +++ listjailparams.c 2024-02-03 19:55:56.447438000 +0100 @@ -8,7 +8,7 @@ printf("number of params: %d\n", nparams); for (int i=0; i<nparams; i++) { - printf("jailparam: %s\n", jailparam_export(¶ms[i])); + printf("jailparam: %s\n", params[i].jp_name); } jailparam_free(params, nparams); return 0; --- listjailparams.py.old 2024-02-03 20:07:38.644856000 +0100 +++ listjailparams.py 2024-02-03 20:08:03.131423000 +0100 @@ -25,8 +25,7 @@ for i in range(nparams): param = params[i] name = param.name.decode('utf-8') - value = param.value if param.value is None else param.value.decode('utf-8') - print(f'Name: {name}, Value: {value}') + print('jailparam: %s'%name) jailparam_free(params, nparams) # vim:ts=2:noet:
(In reply to Fabiano Sidler from comment #2) The python representation of struct jailparam is incomplete. To access params[1], it needs to know the size of params[0], but JailParam's definition would yield an incorrect result.
https://reviews.freebsd.org/D43732 makes jailparam_export() fail cleanly if the value hasn't already been exported.
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=dfabf3efaa795e657f3858b7e2d0b11f8a51ecb5 commit dfabf3efaa795e657f3858b7e2d0b11f8a51ecb5 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2024-02-04 02:22:09 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2024-02-04 22:52:30 +0000 libjail: Guard against programmer error in jailparam_export() If the caller didn't use jailparam_import() to fetch the parameter value, an attempt to export it will trigger a segfault. Make it a bit easier to figure out what's happening in this situation. PR: 276809 Reviewed by: jamie MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D43732 lib/libjail/jail.c | 6 ++++++ 1 file changed, 6 insertions(+)
A commit in branch stable/14 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=5e21d7cd31194faf8c2bdda2bc60adf34eaa405a commit 5e21d7cd31194faf8c2bdda2bc60adf34eaa405a Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2024-02-04 02:22:09 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2024-02-11 15:14:59 +0000 libjail: Guard against programmer error in jailparam_export() If the caller didn't use jailparam_import() to fetch the parameter value, an attempt to export it will trigger a segfault. Make it a bit easier to figure out what's happening in this situation. PR: 276809 Reviewed by: jamie MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D43732 (cherry picked from commit dfabf3efaa795e657f3858b7e2d0b11f8a51ecb5) lib/libjail/jail.c | 6 ++++++ 1 file changed, 6 insertions(+)