Linux VLM workarounds
Linux VLM workarounds

/* sordid hack to get VLM to run without special privilege. * * Inhibit certain calls which require net capabilities or root, * but lie, and say they succeeded. * * Note fd returned by opening /dev/net/tun, with the intent to * override the tun0 (sic) tap requested by VLM with the tap * device specified in the VLM_TAP environment variable. * * Use LD_PRELOAD to load this ahead of the VLM binary. * * N.B. VLM doesn't like xlib-xcb based libX11.so. You need * an older variant such as the one in Slackware 10.2. Use * LD_LIBRARY_PATH so this shadows the normal library. * * Also, if you run NFS different machine than on your host, you * need to tell Genera the IP of the NFS host prior to invoking * Define Site. * * Say you've set up the NFS on a Linux VM with a tap configured * as 10.0.0.1, and your VLM is at 10.0.0.2. Assuming you've * properly configured your .VLM file, on booting Genera, you need * to tell the listener: * * (setf (cadar (send net:*emb-host* :address)) "10.0.0.1") * * Now you may Define Site/Reset Network/Save World. * * Happy hacking! * * `(john q ,(gensym)) - July 16, 2009 */ #include <dlfcn.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <fcntl.h> #include <stdarg.h> #include <stdio.h> #include <string.h> #include <net/if.h> #include <sys/ioctl.h> #include <linux/if_tun.h> #define RTLD_NEXT ((void *) -1l) static int tunfd = -1; int open(const char *file, int flags, ...) { va_list ap; mode_t mode; static int (*oldfn_open)(const char *file, int flags, ...); int fd; if (oldfn_open == NULL) oldfn_open = dlsym(RTLD_NEXT, "open"); va_start(ap, flags); mode = va_arg(ap, mode_t); va_end(ap); fd = oldfn_open(file, flags, mode); if (!strcmp(file, "/dev/net/tun")) tunfd = fd; return fd; } /* Block the call to system("/sbin/ifconfig tun...") */ int system(const char *command) { static int (*oldfn_system)(const char *command); if (oldfn_system == NULL) oldfn_system = dlsym(RTLD_NEXT, "system"); if (!strncmp("/sbin/ifconfig tun0", command, 19)) return 0; return oldfn_system(command); } int ioctl(int fd, unsigned long req, ...) { va_list ap; void *ioctlarg; struct ifreq *ifr; static int (*oldfn_ioctl)(int fd, unsigned long req, ...); char *ifname; if (oldfn_ioctl == NULL) oldfn_ioctl = dlsym(RTLD_NEXT, "ioctl"); va_start(ap, req); ioctlarg = va_arg(ap, void *); va_end(ap); if (req == SIOCSARP) return 0; if (fd != tunfd || req != TUNSETIFF) return oldfn_ioctl(fd, req, ioctlarg); if (!(ifname = getenv("VLM_TAP")) || strlen(ifname) >= IFNAMSIZ) { write(2, "Invalid VLM_TAP.\n", 20); exit(1); } ifr = ioctlarg; strncpy(ifr->ifr_name, ifname, IFNAMSIZ); return oldfn_ioctl(fd, req, ifr); }