diff options
Diffstat (limited to 'jail.go')
-rw-r--r-- | jail.go | 194 |
1 files changed, 194 insertions, 0 deletions
@@ -0,0 +1,194 @@ +package jail + +// #include <stdio.h> +// #include <stdlib.h> +// #include <string.h> +// #include <sys/param.h> +// #include <sys/jail.h> +// #include <sys/uio.h> +// #include <errno.h> +// +// void set_iov_field(struct iovec *iov, int field, void *val, size_t len) { +// iov[field].iov_base = val; +// iov[field].iov_len = len; +// } +// +// void *get_iov_field(struct iovec *iov, int field, size_t *len) { +// *len = iov[field].iov_len; +// return iov[field].iov_base; +// } +// +// void print_iov(struct iovec *iov, int niov) { +// for (int i = 0; i < niov; i++) { +// if (iov[i].iov_base == NULL) +// fprintf(stderr, "(NULL), %lu\n", iov[i].iov_len); +// else +// fprintf(stderr, "%s, %lu\n", iov[i].iov_base, iov[i].iov_len); +// } +// } +// +// void set_int_val(int *dst, int src) { +// *dst = src; +// } +// +// int get_errno() { +// return errno; +// } +import "C" +import "errors" +import "unsafe" + +const ( + JAIL_CREATE = C.JAIL_CREATE + JAIL_UPDATE = C.JAIL_UPDATE + JAIL_ATTACH = C.JAIL_ATTACH + JAIL_DYING = C.JAIL_DYING +) + +var EPerm = errors.New(C.GoString(C.strerror(C.EPERM))) +var EFault = errors.New(C.GoString(C.strerror(C.EFAULT))) +var EInval = errors.New(C.GoString(C.strerror(C.EINVAL))) +var EAgain = errors.New(C.GoString(C.strerror(C.EAGAIN))) +var ENoent = errors.New(C.GoString(C.strerror(C.ENOENT))) +var EExist = errors.New(C.GoString(C.strerror(C.EEXIST))) +var ENameTooLong = errors.New(C.GoString(C.strerror(C.ENAMETOOLONG))) + +func mapToIov(params map[string]interface{}) (unsafe.Pointer, int, []unsafe.Pointer) { + var freeList []unsafe.Pointer + var i = 0 + + iov := C.malloc(C.ulong(C.sizeof_struct_iovec * C.int(len(params)*2))) + freeList = append(freeList, iov) + + for k, v := range params { + c_key := C.CString(k) + freeList = append(freeList, unsafe.Pointer(c_key)) + + C.set_iov_field((*C.struct_iovec)(iov), C.int(i), unsafe.Pointer(c_key), C.strlen(c_key)+1) + i++ + + if v_i, ok := v.(int); ok { + c_val := C.malloc(C.sizeof_int) + freeList = append(freeList, unsafe.Pointer(c_val)) + + C.set_int_val((*C.int)(c_val), C.int(v_i)) + C.set_iov_field((*C.struct_iovec)(iov), C.int(i), c_val, C.sizeof_int) + } else if v_s, ok := v.(string); ok { + c_val := C.CString(v_s) + freeList = append(freeList, unsafe.Pointer(c_val)) + + C.set_iov_field((*C.struct_iovec)(iov), C.int(i), unsafe.Pointer(c_val), C.strlen(c_val)+1) + } else if _, ok := v.(bool); ok { + C.set_iov_field((*C.struct_iovec)(iov), C.int(i), unsafe.Pointer(nil), C.ulong(0)) + } else { + panic("Unknown type") + } + + i++ + } + + //C.print_iov((*C.struct_iovec)(iov), C.int(len(params)*2)) + + return iov, len(params)*2, freeList +} + +func iovToMap(iov unsafe.Pointer, niov int, params map[string]interface{}) { + for i := 0; i < len(params)*2; i+=2 { + var key *C.char + var key_len C.ulong + var val unsafe.Pointer + var val_len C.ulong + + key = (*C.char)(C.get_iov_field((*C.struct_iovec)(iov), C.int(i+0), &key_len)) + val = C.get_iov_field((*C.struct_iovec)(iov), C.int(i+1), &val_len) + + go_key := C.GoStringN(key, C.int(key_len)) + if v, ok := params[go_key]; !ok { + if _, ok := v.(int); ok { + params[go_key] = int(*(*C.int)(val)) + } else if _, ok := v.(string); ok { + params[go_key] = C.GoStringN((*C.char)(val), C.int(val_len)) + } else if _, ok := v.(bool); ok { + // XXX: noop for now + } else { + panic("Got unknown type from kernel") + } + } else { + panic("Got unknown key from kernel") + } + } +} + +func freeIov(freeList []unsafe.Pointer) { + for _, e := range freeList { + C.free(e) + } +} + +func errnoToError() error { + errno := C.get_errno() + + if errno == C.EPERM { + return EPerm + } else if errno == C.EFAULT { + return EFault + } else if errno == C.EINVAL { + return EInval + } else if errno == C.EAGAIN { + return EAgain + } else if errno == C.ENOENT { + return ENoent + } else if errno == C.EEXIST { + return EExist + } else if errno == C.ENAMETOOLONG { + return ENameTooLong + } else { + return errors.New("Unknown error") + } +} + +func Set(params map[string]interface{}, flags int) (int, error) { + iov, niov, freeList := mapToIov(params) + + defer freeIov(freeList) + + ret := C.jail_set((*C.struct_iovec)(iov), C.uint(niov), C.int(flags)) + if ret == -1 { + return 0, errnoToError() + } + + return int(ret), nil +} + +func Get(params map[string]interface{}, flags int) (int, error) { + iov, niov, freeList := mapToIov(params) + + defer freeIov(freeList) + + ret := C.jail_get((*C.struct_iovec)(iov), C.uint(niov), C.int(flags)) + if ret == -1 { + return 0, errnoToError() + } + + iovToMap(iov, niov, params) + + return int(ret), nil +} + +func Attach(jid int) error { + ret := C.jail_attach(C.int(jid)) + if ret == -1 { + return errnoToError() + } + + return nil +} + +func Remove(jid int) error { + ret := C.jail_remove(C.int(jid)) + if ret == -1 { + return errnoToError() + } + + return nil +} |