DF-2234 / addtest.c
/* * DF-2234 -- boundary prover for kern.iconv.add (sys/libiconv/iconv.c:394-424). * * iconv_sysctl_add() validates: * strlen(din.ia_from) >= ICONV_CSNMAXLEN -> EINVAL * strlen(din.ia_to) >= ICONV_CSNMAXLEN -> EINVAL * * usage: addtest <namelen> * root, namelen=30 -> pair registered (csid printed) * root, namelen=31 -> EINVAL (kernel-side bound holds on THIS path) * unprivileged -> EPERM (kern_sysctl.c:1447 caps_priv_check * SYSCAP_NOSYSCTL_WR on sysctl writes) */ #include <sys/types.h> #include <sys/sysctl.h> #include <sys/iconv.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv) { struct iconv_add_in din; struct iconv_add_out dout; size_t olen = sizeof(dout); int n, r; if (argc < 2) return (2); n = atoi(argv[1]); if (n > ICONV_CSNMAXLEN) { printf("namelen %d exceeds userland field, use <= 31\n", n); return (2); } memset(&din, 0, sizeof(din)); memset(&dout, 0, sizeof(dout)); din.ia_version = ICONV_ADD_VER; strlcpy(din.ia_converter, "UTF-16BE", sizeof(din.ia_converter)); memset(din.ia_to, 'T', n); memset(din.ia_from, 'F', n); din.ia_to[n] = 0; din.ia_from[n] = 0; din.ia_datalen = 0; din.ia_data = NULL; r = sysctlbyname("kern.iconv.add", &dout, &olen, &din, sizeof(din)); printf("addtest namelen=%d: sysctl=%d errno=%d (%s) csid=%d\n", n, r, errno, r ? strerror(errno) : "ok", r ? -1 : dout.ia_csid); return (r ? 1 : 0); } |