SOLARIS: Reset syscalls on mod_install failure
authorAndrew Deason <adeason@sinenomine.net>
Thu, 19 May 2011 22:02:35 +0000 (17:02 -0500)
committerDerrick Brashear <shadow@dementia.org>
Fri, 20 May 2011 19:28:19 +0000 (12:28 -0700)
If our call to mod_install fails for any reason (for example, if the
afs entry is missing from /etc/name_to_sysnum), we may still have set
the sysent structures for setgroups and ioctl to point at libafs code.
So calls to those syscalls will cause a panic, since the code they
point to is no longer loaded.

To avoid this, just reset the sysent entries back to what they were if
we fail to load, just like we do when unloading the module.

Change-Id: Ia0d6691780c749a0f550e640783c093ae45604ac
Reviewed-on: http://gerrit.openafs.org/4685
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/afs/SOLARIS/osi_vfsops.c

index dbc76ab..254c9ac 100644 (file)
@@ -574,6 +574,19 @@ static struct modlinkage afs_modlinkage = {
     NULL
 };
 
+static void
+reset_sysent(void)
+{
+    if (afs_sinited) {
+       sysent[SYS_setgroups].sy_callc = afs_orig_setgroups;
+       sysent[SYS_ioctl].sy_call = afs_orig_ioctl;
+#if defined(AFS_SUN57_64BIT_ENV)
+       sysent32[SYS_setgroups].sy_callc = afs_orig_setgroups32;
+       sysent32[SYS_ioctl].sy_call = afs_orig_ioctl32;
+#endif
+    }
+}
+
 /** This is the function that modload calls when loading the afs kernel
   * extensions. The solaris modload program searches for the _init
   * function in a module and calls it when modloading
@@ -670,6 +683,11 @@ _init()
     osi_Init();                        /* initialize global lock, etc */
 
     code = mod_install(&afs_modlinkage);
+    if (code) {
+       /* we failed to load, so make sure we don't leave behind any
+        * references to our syscall handlers */
+       reset_sysent();
+    }
     return code;
 }
 
@@ -689,14 +707,7 @@ _fini()
     if (afs_globalVFS)
        return EBUSY;
 
-    if (afs_sinited) {
-       sysent[SYS_setgroups].sy_callc = afs_orig_setgroups;
-       sysent[SYS_ioctl].sy_call = afs_orig_ioctl;
-#if defined(AFS_SUN57_64BIT_ENV)
-       sysent32[SYS_setgroups].sy_callc = afs_orig_setgroups32;
-       sysent32[SYS_ioctl].sy_call = afs_orig_ioctl32;
-#endif
-    }
+    reset_sysent();
     code = mod_remove(&afs_modlinkage);
     return code;
 }