I've written the following files:
jailtest/jailtest.h
jailtest/jailtest_priv.h
jailtest/main.c
prog/main.c
These are built and run with the following commands:
Then there is the respective Python code
jailtest/jailtest.py
Using the custom libjailtest.so the code works:
But apparently FreeBSD's jail_set cannot be called like this:
What's the issue here? How do I need to correctly call jail_set?
Greetings
Fips
jailtest/jailtest.h
C:
#include <sys/uio.h>
/*
* Public API of the jailtest library.
*/
typedef struct jail {
char *name;
int jid;
} jail;
typedef struct iovec iovec;
int jail_set(iovec*, int niov, int flags);
C:
/* empty */
C:
#include "jailtest.h"
#include "jailtest_priv.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int jail_set(struct iovec *iov, int niov, int flags)
{
printf("flags: %d\n", flags);
for (int i=0; i<niov; i++) {
if (i%2 == 0) {
printf("%s=", (char *)iov[I].iov_base);
} else if (i%2 == 1) {
if (iov[I].iov_base != NULL) {
printf("'%s'\n", (char *)iov[I].iov_base);
} else {
printf("NULL\n");
}
}
}
return 23;
}
prog/main.c
C:
#include <jailtest.h>
#include <stdio.h>
int main()
{
jail* jails = listjails();
printf("name: %s\njid: %d\n", jails[0].name, jails[0].jid);
iovec iovecs[] = {
{ .iov_base = "name", .iov_len = 5 },
{ .iov_base = "emptyjail", .iov_len = 10},
{ .iov_base = "persist", .iov_len = 8},
{ .iov_base = NULL, .iov_len = 0},
{ .iov_base = "vnet", .iov_len = 5},
{ .iov_base = "", .iov_len = 1},
{ .iov_base = "errormsg", .iov_len = 8},
{ .iov_base = "", .iov_len = 1},
};
int ret = jail_set(iovecs, 8, 0);
printf("jail_set returned %d\n", ret);
return 0;
}
These are built and run with the following commands:
sh:
# cc -Wall -Wextra -Werror -Wno-unused-result -fPIC -c -o jailtest/main.o jailtest/main.c
# cc -Wall -Wextra -Werror -Wno-unused-result -fPIC -shared -o jailtest/libjailtest.so jailtest/main.o
# cc -Ijailtest -Wall -Wextra -Werror -Wno-unused-result -fPIC -c -o prog/main.o prog/main.c
# cc -Ijailtest -Wall -Wextra -Werror -Wno-unused-result -fPIC -o prog/prog prog/main.o -Ljailtest -ljailtest
# LD_LIBRARY_PATH=jailtest prog/prog
name='emptyjail'
persist=NULL
vnet=''
errormsg=''
jail_set returned 23
Then there is the respective Python code
jailtest/jailtest.py
Code:
from ctypes import (
CDLL,
Structure,
c_char_p,
c_int,
c_void_p,
c_size_t,
POINTER as Pointer,
create_string_buffer,
cast,
)
lib = CDLL('./libjailtest.so')
#lib = CDLL('libjail.so')
class Jail(Structure):
_fields_ = [
("name", c_char_p),
("jid", c_int),
]
class iovec(Structure):
_fields_ = [
('iov_base', c_void_p),
('iov_len', c_size_t),
]
class Iovecs:
def __init__(self, values={}):
self._values = values
def iovs(self):
v = self._values
n = len(v)
s = n * 2
iovec_array = (iovec * s)()
i = 0
for key,value in v.items():
iovec_array[I].iov_base = cast(create_string_buffer(key), c_void_p)
iovec_array[I].iov_len = len(key)
i += 1
iovec_array[I].iov_base = cast(create_string_buffer(value), c_void_p)
iovec_array[I].iov_len = len(value)
i += 1
return iovec_array
def niovs(self):
return len(self._values)*2
def add(self, name, value):
self._values[name] = value
jail_set = lib.jail_set
jail_set.argtypes = [Pointer(iovec), c_int, c_int]
jail_set.restype = c_int
iv = Iovecs({
b'name': b'emptyjail',
b'persist': b'\0',
b'vnet': b'',
b'errormsg': b'',
})
ret = jail_set(iv.iovs(), iv.niovs(), 1)
print('jail_set: %d'%ret)
Using the custom libjailtest.so the code works:
sh:
# python3.11 jailtest.py
flags: 1
name='emptyjail'
persist=''
vnet=''
errormsg=''
jail_set: 23
But apparently FreeBSD's jail_set cannot be called like this:
sh:
# python3.11 jailtest.py
jail_set: -1
What's the issue here? How do I need to correctly call jail_set?
Greetings
Fips