⬢ DragonFlyBSD Kernel Audit
DF-3112 / fix_combined_for_validation.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer/hammer_ioctl.c
+++ b/sys/vfs/hammer/hammer_ioctl.c
@@ -84,8 +84,10 @@
 		}
 		break;
 	case HAMMERIOC_GETHISTORY:
-		error = hammer_ioc_gethistory(&trans, ip,
+		if (error == 0) {
+			error = hammer_ioc_gethistory(&trans, ip,
 					(struct hammer_ioc_history *)data);
+		}
 		break;
 	case HAMMERIOC_REBLOCK:
 		if (error == 0 && hmp->ronly)
@@ -115,12 +117,16 @@
 		}
 		break;
 	case HAMMERIOC_SYNCTID:
-		error = hammer_ioc_synctid(&trans, ip,
+		if (error == 0) {
+			error = hammer_ioc_synctid(&trans, ip,
 					(struct hammer_ioc_synctid *)data);
+		}
 		break;
 	case HAMMERIOC_GET_PSEUDOFS:
-		error = hammer_ioc_get_pseudofs(&trans, ip,
+		if (error == 0) {
+			error = hammer_ioc_get_pseudofs(&trans, ip,
 				    (struct hammer_ioc_pseudofs_rw *)data);
+		}
 		break;
 	case HAMMERIOC_SET_PSEUDOFS:
 		if (error == 0 && hmp->ronly)
@@ -175,12 +181,16 @@
 		}
 		break;
 	case HAMMERIOC_GET_VERSION:
-		error = hammer_ioc_get_version(&trans, ip,
+		if (error == 0) {
+			error = hammer_ioc_get_version(&trans, ip,
 				    (struct hammer_ioc_version *)data);
+		}
 		break;
 	case HAMMERIOC_GET_INFO:
-		error = hammer_ioc_get_info(&trans,
+		if (error == 0) {
+			error = hammer_ioc_get_info(&trans,
 				    (struct hammer_ioc_info *)data);
+		}
 		break;
 	case HAMMERIOC_SET_VERSION:
 		if (error == 0 && hmp->ronly)
@@ -211,8 +221,10 @@
 		}
 		break;
 	case HAMMERIOC_LIST_VOLUMES:
-		error = hammer_ioc_volume_list(&trans, ip,
-		    (struct hammer_ioc_volume_list *)data);
+		if (error == 0) {
+			error = hammer_ioc_volume_list(&trans, ip,
+			    (struct hammer_ioc_volume_list *)data);
+		}
 		break;
 	case HAMMERIOC_ADD_SNAPSHOT:
 		if (error == 0 && hmp->ronly)
@@ -231,12 +243,18 @@
 		}
 		break;
 	case HAMMERIOC_GET_SNAPSHOT:
-		error = hammer_ioc_get_snapshot(
-					&trans, ip, (struct hammer_ioc_snapshot *)data);
+		if (error == 0) {
+			error = hammer_ioc_get_snapshot(
+					&trans, ip,
+					(struct hammer_ioc_snapshot *)data);
+		}
 		break;
 	case HAMMERIOC_GET_CONFIG:
-		error = hammer_ioc_get_config(
-					&trans, ip, (struct hammer_ioc_config *)data);
+		if (error == 0) {
+			error = hammer_ioc_get_config(
+					&trans, ip,
+					(struct hammer_ioc_config *)data);
+		}
 		break;
 	case HAMMERIOC_SET_CONFIG:
 		if (error == 0 && hmp->ronly)
@@ -261,8 +279,11 @@
 		}
 		break;
 	case HAMMERIOC_SCAN_PSEUDOFS:
-		error = hammer_ioc_scan_pseudofs(
-				&trans, ip, (struct hammer_ioc_pseudofs_rw *)data);
+		if (error == 0) {
+			error = hammer_ioc_scan_pseudofs(
+					&trans, ip,
+					(struct hammer_ioc_pseudofs_rw *)data);
+		}
 		break;
 	default:
 		error = EOPNOTSUPP;
@@ -296,6 +317,12 @@
 	if (hist->head.flags & HAMMER_IOC_HISTORY_ATKEY) {
 		if (hist->key > hist->nxt_key)
 			return(EINVAL);
+		/*
+		 * Reject the boundary: the REGFILE scan below increments
+		 * key_beg.key and would overflow int64 at HAMMER_MAX_KEY.
+		 */
+		if (hist->key >= HAMMER_MAX_KEY)
+			return(EINVAL);
 	}
 
 	hist->obj_id = ip->obj_id;
@@ -383,6 +410,15 @@
 					      HAMMER_LOCALIZE_INODE;
 	}
 
+	/*
+	 * Honor any validation error from the ATKEY switch() above
+	 * (e.g. unsupported object type) instead of overwriting it.
+	 */
+	if (error) {
+		hammer_done_cursor(&cursor);
+		return(error);
+	}
+
 	error = hammer_btree_first(&cursor);
 	while (error == 0) {
 		elm = &cursor.node->ondisk->elms[cursor.index];