Bug 276809 - SEGFAULTs using libjail
Summary: SEGFAULTs using libjail
Status: Closed Not A Bug
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 13.2-RELEASE
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-jail (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-02-03 17:53 UTC by Fabiano Sidler
Modified: 2024-02-11 15:15 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fabiano Sidler 2024-02-03 17:53:03 UTC
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(&params);
	printf("number of params: %d\n", nparams);
	for (int i=0; i<nparams; i++) {   
		printf("jailparam: %s\n", jailparam_export(&params[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 ===
Comment 1 Mark Johnston freebsd_committer freebsd_triage 2024-02-03 18:32:27 UTC
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.
Comment 2 Fabiano Sidler 2024-02-03 19:58:32 UTC
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(&params[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:
Comment 3 Mark Johnston freebsd_committer freebsd_triage 2024-02-04 02:13:35 UTC
(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.
Comment 4 Mark Johnston freebsd_committer freebsd_triage 2024-02-04 02:24:08 UTC
https://reviews.freebsd.org/D43732 makes jailparam_export() fail cleanly if the value hasn't already been exported.
Comment 5 commit-hook freebsd_committer freebsd_triage 2024-02-04 22:54:13 UTC
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(+)
Comment 6 commit-hook freebsd_committer freebsd_triage 2024-02-11 15:15:46 UTC
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(+)