Problems...

... and solutions by <creative.sysadms@chalmers.se>

Maintained by <appro@fy.chalmers.se>


P. MathLM, Mathematica License Manager, is vulnerable to trivial denial-of-service attack...
S. The LD_PRELOAD module below agressively timeouts transactions as well as fixes several other problems with mathlm, see commentary section in the source for further details.

mathlm.sentry.c


P. ICA Client for Unix, version 5.x and below disregards umask and ignorantly chmods all the files it touches to rwxrwxrwx...
S. Shortest module ever:-) Compile with gcc -shared and LD_PRELOAD to wfica.

wfica_chmod.c


P. Solaris lpq exhausts privileged ports...
S. We run SAMBA and export a bunch of printers, lpq is called rather often and privileged ports tend to get exhausted now and then. So I intercept calls to rresvport and set SO_LINGER option on allocated socket.

lpq_letitgo.c


P. VMware 2.x didn't support mounting of CD-ROM images, you had to burn a CD to access the data...
S. The module below intercepts open and ioctl system calls and emulates minimum set of CD-ROM ioctls on a plain file. See the source for details on usage.

vmcdimage.c


P. VMware 3.x doesn't support mounting of DVD-ROM images. Well, you can mount it, but it fails to read beyond 2GB...
S. I've started by extending vmcdimage.c above with minimum support for CDROM_SEND_PACKET ioctls, to make it possible to mount the image as "raw" CD-ROM... But it turned out that following is more than sufficient to cross the 2GB limit.

open64.c


P. It's impossible to get VMware 4.x working with ESD, Enlightenment Sound Daemon...
S. VMware recommends to get rid of it, but I see no reason why should I do that:-) But there is a catch! esddsp is the very same kind of fiddler as myself. It plays on LD_PRELOAD-ing modules intercepting calls to open(2) and couple of others. Setting LD_PRELOAD variable prior esddsp vmware invocation wouldn't work, as it will be [ignorantly] overridden by the esddsp script. Therefore, LD_PRELOAD variable has to be set according to the example in attached code. Order is important! In case you wonder what's the heck with VMware 4.x. As the code implies the problem is that VMware 4.x calls open64(2) while libesddps.so re-implements open(2). So the snippet simply forwards calls to open64(2) to open(2) enforcing in O_LARGEFILE flag, so that the result is equivalent.

64open.c


P. SCSI analyzers cost thousands of dollars...
S. If you have VMware, you can easily spy on SCSI "traffic" by exporting "Generic" SCSI devices to the guest OS and pre-loading this module to vmware binary. You most likely want to customize it for your own particular needs.

sgiosniffer.c


P. Solaris doesn't recognize HOSTALIASES environment variable:-(
S. Compile and LD_PRELOAD this libhost.c module of Johan Rudholm's design. See the source for further details. Posted with explicit Johan's permission.

libhost.c


P. Adobe PDF Writer requires LPT1: to be present, while nowadays you can run into a PC without parallel port (laptops and slim-line servers)
S. Yes, this is a Windows thing! The code targets Windows 2000/XP/.NET and requires DLL_PRELOAD module loaded. The idea is to create a symbolic link from LPT1 to \Devices\Null before Print Spooler service starts. The module is therefore can be pre-loaded to SERVICES.EXE, parent to all services.

lptone.c


P. Sometimes it takes 2 minutes to logout Windows 2000/XP (yes, Windows again)
S. If you're observant enough, you'll also notice that when it happens, your [roaming] profile will not be updated and the recent changes will consequently be lost. The problem is recognized by Microsoft, and several attempts to work it around were actually made, but none of them was successful. The problem is that Win32 Subsystem server, CSRSS.EXE, (well, rather one of DLLs dynamically loaded to its address space) leaks handle[s] to your personal registry hive, which makes it improssible to unload the latter. So we do it the hard way:-) In order to catch the moment of logout, I intercept call to UnloadUserProfile in WINLOGON.EXE (yes, this means that module in question is to be pre-loaded to WINLOGON.EXE). Upon call to this function, I list processes to identify my Win32 Subsystem server, "attach" to it, then "steal" the handles to my registry hive and just close them. Needless to mention that it requires DLL_PRELOAD module loaded.

WINLOGOUT.c


P. Sometimes I/O buffers are required to be aligned in a specific manner (most notably when accessing /dev/raw/raw* in Linux)
S. This module maintains single common intermediate buffer aligned at page boundary and makes sure all I/O requests are aligned. This is very quick-n-dirty hack! But it does the job if all you want to do is to fool around with such programs as tar, dd, cpio, ... and /dev/raw/raw*. See the code for an example...

aligned_io.c
#if 0 # # This LD_PRELOAD-able module keeps buffers [passed to /dev/raw/...] # aligned according to 'man raw'. Maintaining appropriate blocking # factor is still up to the application this module will be # LD_PRELOAD-ed to. Most common example would most likely be: # # env LD_PRELOAD=`pwd`/aligned_io.so tar cBbf 64 /dev/raw/raw1 ... # /bin/sh << EOS MODNAME=\`basename "$0" .c\` (set -x; gcc -O -fomit-frame-pointer -fPIC -shared -o \$MODNAME.so "$0") [ $# -gt 0 ] && (set -x; env LD_PRELOAD=`pwd`/\$MODNAME.so $*) EOS exit # #endif #ifndef __linux # error "Linux only, at least for the moment..." #endif #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <unistd.h> #define ALIGN 2048 #define ASIZE (32*1024) #ifndef DEBUG #define DEBUG 0 #endif static void *aligned_buffer; typedef ssize_t (*io_op) (int fd,void *buf,size_t count); extern ssize_t __write(int fd, void *buf, size_t count); extern ssize_t __read(int fd, void *buf, size_t count); static ssize_t do_io (io_op op,int fd,void *buf,size_t count) { int ret; #if DEBUG fprintf (stderr,"-%d:%p\n",fd,buf); #endif if ((size_t)buf&(ALIGN-1)) { if (aligned_buffer == NULL) aligned_buffer = mmap (NULL,ASIZE,PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON,-1,0); #if DEBUG fprintf (stderr,"+%d:%p\n",fd,aligned_buffer); #endif /* I count on caller to notice that the return value is smaller */ if (count>ASIZE) count=ASIZE; if (op==__write) memcpy (aligned_buffer,buf,count); ret=(*op) (fd,aligned_buffer,count); if (op==__read && ret>0) memcpy (buf,aligned_buffer,ret); return ret; } return (*op) (fd,buf,count); } ssize_t write(int fd, const void *buf, size_t count) { return do_io (__write,fd,(void *)buf,count); } ssize_t read(int fd, void *buf, size_t count) { return do_io (__read,fd,buf,count); }


P. Tru64 clu_upgrade(8) floods root file system when performing preinstall procedure for rolling TruCluster upgrade...
S. Tru64 tar exhibits [annoying] quality to follow symbolic links at autofs(8) mount point(s) even if instructed not to. Apparently it's intentional (they probably want to maintain an illusion of loopback mount point), but in this particluar case is totally inappropriate. Ideally clu_upgrade should explicitly backup files without crossing the device boundary. Meanwhile it's possible to work around the problem by tricking tar to cache first device being returned by lstat(2) and return failure upon cache miss...

tardeviceonly.c


P. Sometimes you have to maintain virtual identity...
S. Imagine you have a virtual interface or cluster alias set up. Most network server programs allow you to bind their incoming sockets to the interface of interest [e.g. "bind interfaces only" in Samba]. But there come occasions when you have to maintain virtual identity even on outgoing sockets, maybe without having the luxuary or not willing to modify the source code to suit your needs. TruCluster for example provides for this on per target port basis [out_alias parameter in /etc/clua_services], but this affect all applications and applies to default cluster alias only, which is not necessarily what you had in mind. Therefore attached module:-) If pre-loaded into target application's address space, this module maintains virtual identity on all sockets opened by that particular process and its direct siblings.

bind_to.c


P. Why not per-executable environment variables?
S. Yet another DLL_PRELOAD Windows module. Idea is to set environment variables on per-executable basis. E.g. _CLUSTER_NETWORK_NAME_ set to %USERNAME% in ICA Client context on Terminal Server can become very handy;-) But why not a wrapper script [such as we used to do in Unix] you ask? Well, then you might have to re-associate application CLSID, which is nothing but boring... And if you use simpler interpretator (such as CMD or Perl), you might end up with an ugly black window instantly popping up and disappe.a..r...

environ.c


P. Ever tried to access files with zapped ACL on NTFS volume? Doesn't work even for privileged user, does it?
S. Here is yet another DLL_PRELOAD Windows module which allows commodity programs executed by privileged user to bypass access control mechanisms [therefore the name: BYPass ACcess Control]. With this module pre-loaded you [being a privileged user!] can traverse directories, open files and manipulate ACLs on NTFS objects without regard to their effective permissions. This is achieved by "unlocking" the Backup privilege for current process and patching a system call to open all files "for Backup." This is essentially what NTBACKUP.EXE does... A reminder that DLL_PRELOAD works only with programs linked with USER32.DLL is due here. Because [X]CACLS.EXE are not linked with it and don't work:-( So don't ask... Explorer works fine, but it's tricky to pre-load the module on temporary need-for-a-moment basis. I personally recommend [and stick to] following procedure:
  • open Folder Options control panel -> View pane and make sure you "Launch folder windows in a separate process,"
  • close all folder views and double-check that you have only one explorer.exe process left running,
  • open Command Prompt window and issue "set DLL_PRELOAD=bypacc.dll" command followed by "explorer,"
  • at this point you should have unconstrained Explorer window...
  • proceed to step 2 when done!

bypacc.c


P. ActiveSync 4.1 does not work in Citrix Presentation Server [nor "vanilla" Terminal Server] environment.
S. Yes, Windows again. Gr-r-r-r... This module is designed to modify behaviour of ActiveSync components, wcescomm.exe, wcesmg.exe and rapimgr.exe, in following manner. First of all the module places itself between KERNEL32.DLL and NTDLL.DLL and strips Global\ prefix from mutex and semaphore objects created/opened by either component. This makes ActiveSync adhere to session-specific object name space. Secondly it places itself between WS2_32.DLL and currently registered WSP, Windows Socket Provider, and re-bias references to 127.0.0.1 to a session-specific address from 127. subnet. This effectively isolates concurrently executing instances of the application suite in question in every given session, which is the key to successful application deployment in Terminal Server environment. It should be noted that Citrix already arranges for the latter, per-session loopback communication interface, so one can wonder why did I do it? Well, because we've found that it's actually possible to make ActiveSync work [at least] with rdesktop COM-port redirection even without Citrix! Reliable and seamless deployment, in particular of USB-connected PDAs, requires some Linux kernel as well as rdesktop patching. We plan to publish these patches as we make progress.

vsync.c


P. Adobe Acrobat [Reader] 9 for Windows crashes upon startup...
S. Crash occurs if there is an unreadable yet traversable directory on your %APPDATA% path. I.e. such directory where you can not run 'dir' in, but can 'chdir' to a subdirectory. In our particular case %APPDATA% is redirected through a DFS root, where we forbid users to list referrals for security and primarily performance reasons. Crash takes places in MSVCRT and is worked around [naturally with DLL_PRELOAD's help] by pulling directory status information for '...\unreadable\subdir\.' instead of '...\unreadable\subdir'.

statpatch.c


P. Low-traffic TCP connections tend to hang and ultimately break in NAT-ed environment...
S. For TCP to work through a NAT device, such as residential gateway, latter maintains table of active TCP connections. The table is periodically traversed and connections that are considered stale are removed from the table. This means that if there was no activity on a given TCP connection for certain period of time, chances are that it will be evicted from the NAT table, i.e. will be effectively broken. And given current state of busyness it takes inapproriately long time to detect that it's broken. This poses major irritation for remote interactive sessions, such as SSH or RDP. Periodic TCP keep-alive can come to rescue, but in addition to the fact that the default system-wide interval is surrealistically high, 2 hours, application has to explicitly set SO_KEEPALIVE socket option. In other words in addition to setting kernel parameter (net.ipv4.tcp_keepalive_time on Linux and Services\Tcpip\Parameters\KeepAliveTime on Windows) to lower value you might have to modify application code. Naturally you might find yourself in position of not being able to do the latter, especially on Windows. Therefore below Windows-specific DLL_PRELOAD module that sets up keep-alive on all sockets opened by chosen application. Example suggests to pre-load it to mstsc.exe, Windows RDP client...

keepalive.c


To be continued...