⬢ DragonFlyBSD Kernel Audit
DF-3124 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/isofs/cd9660/cd9660_vfsops.c b/sys/vfs/isofs/cd9660/cd9660_vfsops.c
index 1111111..2222222 100644
--- a/sys/vfs/isofs/cd9660/cd9660_vfsops.c
+++ b/sys/vfs/isofs/cd9660/cd9660_vfsops.c
@@ -488,13 +488,28 @@ iso_mountfs(struct vnode *devvp, struct mount *mp, struct iso_args *argp)
 					 ISOFSMNT_UID | ISOFSMNT_GID);
 
 	if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
+		/*
+		 * The charset names come from the mount arguments and are
+		 * not guaranteed to be NUL-terminated (ICONV_CSNMAXLEN-1
+		 * usable bytes); force termination before they are used as
+		 * C strings by iconv_open().
+		 */
 		bcopy(argp->cs_local, cs_local, sizeof(cs_local));
 		bcopy(argp->cs_disk, cs_disk, sizeof(cs_disk));
-		cd9660_iconv->open(cs_local, cs_disk, &isomp->im_d2l);
-		cd9660_iconv->open(cs_disk, cs_local, &isomp->im_l2d);
+		cs_local[sizeof(cs_local) - 1] = 0;
+		cs_disk[sizeof(cs_disk) - 1] = 0;
+		if (cd9660_iconv->open(cs_local, cs_disk, &isomp->im_d2l) != 0)
+			isomp->im_d2l = NULL;
+		if (cd9660_iconv->open(cs_disk, cs_local, &isomp->im_l2d) != 0)
+			isomp->im_l2d = NULL;
+		if (isomp->im_d2l == NULL || isomp->im_l2d == NULL) {
+			/*
+			 * The charset pair is unavailable.  Fall back to no
+			 * conversion instead of keeping NULL handles that
+			 * isochar()/sgetrune() would pass to convchr()
+			 * (NULL-deref panic on the first lookup/readdir).
+			 */
+			if (isomp->im_d2l != NULL) {
+				cd9660_iconv->close(isomp->im_d2l);
+				isomp->im_d2l = NULL;
+			}
+			if (isomp->im_l2d != NULL) {
+				cd9660_iconv->close(isomp->im_l2d);
+				isomp->im_l2d = NULL;
+			}
+			isomp->im_flags &= ~ISOFSMNT_KICONV;
+		}
 	} else {
 		isomp->im_d2l = NULL;
 		isomp->im_l2d = NULL;