⬢ DragonFlyBSD Kernel Audit
DF-4599 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/raid/vinum/vinumioctl.c
+++ b/sys/dev/raid/vinum/vinumioctl.c
@@ -217,13 +217,24 @@
 		 * Note the open count.  We may be called from v, so we'll be open.
 		 * Keep the count so we don't underflow
 		 */
-		free_vinum(1);				    /* clean up everything */
-		log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n");
-		ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */
-		ioctl_reply->error = 0;
+		error = lock_config();			    /* DF-4599: free_vinum() must not race
+								 * VINUM_CREATE, which holds the config
+								 * lock while growing and freeing the
+								 * DRIVE/SD/PLEX/VOL arrays */
+		if (error)
+		    break;
+		error = setjmp(command_fail);		    /* free_vinum -> remove_drive -> save_config may throw */
+		if (error == 0) {
+		    free_vinum(1);			    /* clean up everything */
+		    log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n");
+		    ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */
+		    ioctl_reply->error = 0;
+		}
+		unlock_config();
 	    } else {
 		error = EBUSY;
 	    }
+	    break;					    /* DF-1741: no fallthrough into VINUM_SETSTATE */
 
 	case VINUM_SETSTATE:
 	    setstate((struct vinum_ioctl_msg *) data);	    /* set an object state */