Subject: NetBSD/systrace error: EINVAL
To: None <tech-misc@NetBSD.org>
From: Kristaps Johnson <kristaps@gradient-enterprises.com>
List: tech-misc
Date: 07/03/2006 17:52:08
Hello all!

I wonder if somebody can help me with a strange error I receive under 
systrace on NetBSD.  I've included a sample programme below with 
error-checking stripped in non-applicable areas.  The "sys/systrace.h" 
header file is current from CVS. Overall system NetBSD 3.0, GENERIC.  I'm 
trying to port sysjail (sysjail.bsd.lv) to NetBSD and this is keeping me 
hard up.  Suggestions?

Note that this works fine with the OpenBSD systrace (3.9), which adds to 
the mystification.

The "strange error" is EINVAL: Invalid argument.

The below is run as "./a.out 5123", where 5123 is a process doing things (I 
have a script looping echo -n '.').


#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#ifdef __NetBSD__
# include <sys/systrace.h>
#elif __OpenBSD__
# include <dev/systrace.h>
#endif

#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int
main(int argc, const char *argv[])
{
         struct str_message msg;
         struct systrace_policy pol;
         struct pollfd pfd;
         int fd, ofd;
         pid_t cpid;

         cpid = atoi(argv[1]);

         ofd = open("/dev/systrace", O_RDWR | O_NONBLOCK, 0);
#ifdef __OpenBSD__
         ioctl(ofd, STRIOCCLONE, &fd);
         close(ofd);
#elif __NetBSD__
         fd = ofd;
#endif
         fcntl(fd, F_SETFD, FD_CLOEXEC);

         memset(&pol, 0, sizeof(pol));
         pol.strp_op = SYSTR_POLICY_NEW;
         pol.strp_num = -1;
         pol.strp_maxents = 512;

         ioctl(fd, STRIOCPOLICY, &pol);
         ioctl(fd, STRIOCATTACH, &cpid);

         memset(&pfd, 0, sizeof(pfd));
         pfd.fd = fd;
         pfd.events = POLLIN;

         poll(&pfd, 1, -1);

         /* RETURNS AN ERROR:
          * read: /dev/systrace: Invalid argument */
         if (read(fd, &msg, sizeof(struct str_message))
                         != sizeof(struct str_message)) {
                 err(1, "read: /dev/systrace");
         }

         return(0);
}