0day Kernel Vulnerabilities

Solaris vfs_getvfssw() Loadable Kernel Module Traversal Vulnerability

Once again, let's look directly at the vulnerable code and make sense of what it does before delving into the details of the vulnerability.

 /*  * Find a vfssw entry given a file system type name.  * Try to autoload the filesystem if it's not found.  * If it's installed, return the vfssw locked to prevent unloading.  */ struct vfssw * vfs_getvfssw(char *type) {         struct vfssw *vswp;         char    *modname;         int rval;             RLOCK_VFSSW();         if ((vswp = vfs_getvfsswbyname(type)) == NULL) {                 RUNLOCK_VFSSW();                 WLOCK_VFSSW();                 if ((vswp = vfs_getvfsswbyname(type)) == NULL) { [1]                     if ((vswp = allocate_vfssw(type)) == NULL) {                                 WUNLOCK_VFSSW();                                 return (NULL);                         }                 }                 WUNLOCK_VFSSW();                 RLOCK_VFSSW();         }     [2]     modname = vfs_to_modname(type);             /*          * Try to load the filesystem.  Before calling modload(), we drop          * our lock on the VFS switch table, and pick it up after the          * module is loaded.  However, there is a potential race:  the          * module could be unloaded after the call to modload() completes          * but before we pick up the lock and drive on.  Therefore,          * we keep reloading the module until we've loaded the module          * _and_ we have the lock on the VFS switch table.          */         while (!VFS_INSTALLED(vswp)) {                 RUNLOCK_VFSSW();                 if (rootdir != NULL) [3]                     rval = modload("fs", modname);            [deleted] } 

The Solaris operating system has most of it kernel- related functionality implemented as kernel modules that are loaded on demand. Other than the core kernel functionality, most of the kernel services are implemented as dynamic kernel modules, including various file system types. When the kernel receives a service request for a file system that has not been previously loaded into kernel space, the kernel searches for a possible dynamic kernel module for that file system. It loads the module from one of the previously mentioned module directories, thus gaining the capability to serve the request. This particular vulnerability, much like the priocntl vulnerability, involves tricking the operating system into loading a user -supplied kernel module (in this particular case, a module representing a file system), thus gaining full kernel execution rights.

The Solaris kernel keeps track of loaded file systems with the Solaris file system switch table. Essentially, this table is an array of vfssw_t structures.

 typedef struct vfssw {         char            *vsw_name;      /* type name string */         int             (*vsw_init)(struct vfssw *, int);                                         /* init routine */         struct vfsops   *vsw_vfsops;    /* filesystem operations vector */         int             vsw_flag;       /* flags */ } vfssw_t; 

The vfs_getvfssw() function traverses the vfssw[] array searching for a matching entry based on the vsw_name (which is the type char string passed to the function). If no matching entry is found, vfs_getvfssw() function first allocates a new entry point in the vfssw[] array [1] and then calls a translation function [2] , which basically does nothing more than parse the type argument for certain strings. This behavior is of no real interest when exploiting the vulnerability. Finally, it autoloads the file system by calling the infamous modload function [3] .

During our kernel audit, we found that two of the Solaris system calls use the vfs_getvfssw() function with a user-land supplied type . It will be translated into the module name to be loaded from either the /kernel/fs/ directory or the /usr/kernel/fs/ directory. Once again, modload interface can be attacked with simple directory traversal tricks that will give us kernel execution. mount and sysfs system calls have been identified and successfully exploited during our audits . (Exploitation of this vulnerability will be presented in Chapter 24.) Let's now look at the two possible code paths that lead to the vfs_getvfssw() with user-controlled input.

The sysfs() System Call

The sysfs() syscall is one example of a code path to vfs_getvfssw() that will allow user-controlled input.

 int sysfs(int opcode, long a1, long a2) {         int error;             switch (opcode) {         case GETFSIND:                 error = sysfsind((char *)a1);      [deleted]                        V     static int sysfsind(char *fsname) {         /*          * Translate fs identifier to an index into the vfssw structure.          */         struct vfssw *vswp;         char fsbuf[FSTYPSZ];         int retval;         size_t len = 0;             retval = copyinstr(fsname, fsbuf, FSTYPSZ, &len);            [deleted]             /*          * Search the vfssw table for the fs identifier          * and return the index.          */         if ((vswp = vfs_getvfssw(fsbuf)) != NULL) {          [deleted] 

The mount() System Call

The mount() syscall is another example of a code path to vfs_getvfssw() that will allow user-controlled input.

 int mount(char *spec, char *dir, int flags,         char *fstype, char *dataptr, int datalen) {          [deleted]             ua.spec = spec;         ua.dir = dir;         ua.flags = flags;         ua.fstype = fstype;         ua.dataptr = dataptr;         ua.datalen = datalen;            [deleted]             error = domount(NULL, &ua, vp, CRED(), &vfsp);      [deleted]                       V     int domount(char *fsname, struct mounta *uap, vnode_t *vp, struct cred *credp,         struct vfs **vfspp) {      [deleted]                                 error = copyinstr(uap->fstype, name,                                     FSTYPSZ, &n);      [deleted]                       if ((vswp = vfs_getvfssw(name)) == NULL) {                         vn_vfsunlock(vp);      [deleted] } 

We must admit that we did not check all possible kernel interfaces that use the vfs_getvfssw() function, but most likely this is all there is. You are encouraged to look into modload() -related problems, which might reveal still more exploitable interfaces.



The Shellcoder's Handbook. Discovering and Exploiting Security
Hacking Ubuntu: Serious Hacks Mods and Customizations (ExtremeTech)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 198
Authors: Neal Krawetz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net