Skip to contentSkip to conversation

staging: lustre: integer overflow in obd_ioctl_is_invalid()

PATCH In review Dan Carpenter 3 participants 7 messages Apr 24, 2014 – Apr 28, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 2/2 staging: lustre: integer overflow in obd_ioctl_is_invalid()

The obd_ioctl_getdata() function caps "data->ioc_len" at OBD_MAX_IOCTL_BUFFER and then calls this obd_ioctl_is_invalid() to check that the other values inside data are valid.

There are several lengths inside data but when they are added together they must not be larger than "data->ioc_len". The checks against "(data->ioc_inllen1 > (1<<30))" are supposed to ensure that the addition does not have an integer overflow. But "(1<<30) * 4" actually can overflow 32 bits so the checks are insufficient.

I have changed it to "> OBD_MAX_IOCTL_BUFFER" instead.

drivers/staging/lustre/lustre/include/lustre_lib.h +5 -5
index 0368ca6..04f549e 100644
@@ -192,23 +192,23 @@ static inline int obd_ioctl_packlen(struct obd_ioctl_data *data)
 
 static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
 {
-	if (data->ioc_len > (1<<30)) {
+	if (data->ioc_len > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_len larger than 1<<30\n");
 		return 1;
 	}
-	if (data->ioc_inllen1 > (1<<30)) {
+	if (data->ioc_inllen1 > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
 		return 1;
 	}
-	if (data->ioc_inllen2 > (1<<30)) {
+	if (data->ioc_inllen2 > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_inllen2 larger than 1<<30\n");
 		return 1;
 	}
-	if (data->ioc_inllen3 > (1<<30)) {
+	if (data->ioc_inllen3 > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_inllen3 larger than 1<<30\n");
 		return 1;
 	}
-	if (data->ioc_inllen4 > (1<<30)) {
+	if (data->ioc_inllen4 > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_inllen4 larger than 1<<30\n");
 		return 1;
 	}
Reviewed-by on v1 2/2
#1 lore raw
Quoted 4 lines · Dan Carpenter

The obd_ioctl_getdata() function caps "data->ioc_len" at OBD_MAX_IOCTL_BUFFER and then calls this obd_ioctl_is_invalid() to check that the other values inside data are valid.

Quoted 8 lines

There are several lengths inside data but when they are added together they must not be larger than "data->ioc_len". The checks against "(data->ioc_inllen1 > (1<<30))" are supposed to ensure that the addition does not have an integer overflow. But "(1<<30) * 4" actually can overflow 32 bits so the checks are insufficient.

I have changed it to "> OBD_MAX_IOCTL_BUFFER" instead.

Thanks,
Tao

Quoted 35 lines
drivers/staging/lustre/lustre/include/lustre_lib.h +5 -5
index 0368ca6..04f549e 100644
@@ -192,23 +192,23 @@ static inline int obd_ioctl_packlen(struct obd_ioctl_data *data)
 
 static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
 {
-       if (data->ioc_len > (1<<30)) {
+       if (data->ioc_len > OBD_MAX_IOCTL_BUFFER) {
                CERROR("OBD ioctl: ioc_len larger than 1<<30\n");
                return 1;
        }
-       if (data->ioc_inllen1 > (1<<30)) {
+       if (data->ioc_inllen1 > OBD_MAX_IOCTL_BUFFER) {
                CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
                return 1;
        }
-       if (data->ioc_inllen2 > (1<<30)) {
+       if (data->ioc_inllen2 > OBD_MAX_IOCTL_BUFFER) {
                CERROR("OBD ioctl: ioc_inllen2 larger than 1<<30\n");
                return 1;
        }
-       if (data->ioc_inllen3 > (1<<30)) {
+       if (data->ioc_inllen3 > OBD_MAX_IOCTL_BUFFER) {
                CERROR("OBD ioctl: ioc_inllen3 larger than 1<<30\n");
                return 1;
        }
-       if (data->ioc_inllen4 > (1<<30)) {
+       if (data->ioc_inllen4 > OBD_MAX_IOCTL_BUFFER) {
                CERROR("OBD ioctl: ioc_inllen4 larger than 1<<30\n");
                return 1;
        }
#2 lore raw
In reply to Dan Carpenter

Am 24.04.2014 23:49, schrieb Dan Carpenter:

Quoted 19 lines

The obd_ioctl_getdata() function caps "data->ioc_len" at OBD_MAX_IOCTL_BUFFER and then calls this obd_ioctl_is_invalid() to check that the other values inside data are valid.

There are several lengths inside data but when they are added together they must not be larger than "data->ioc_len". The checks against "(data->ioc_inllen1 > (1<<30))" are supposed to ensure that the addition does not have an integer overflow. But "(1<<30) * 4" actually can overflow 32 bits so the checks are insufficient.

I have changed it to "> OBD_MAX_IOCTL_BUFFER" instead.

drivers/staging/lustre/lustre/include/lustre_lib.h +0 -0
index 0368ca6..04f549e 100644

drivers/staging/lustre/lustre/include/lustre_lib.h static inline int obd_ioctl_packlen(struct obd_ioctl_data *data) · line 198

Quoted 8 lines
drivers/staging/lustre/lustre/include/lustre_lib.h +1 -1
@@ -192,23 +192,23 @@ static inline int obd_ioctl_packlen(struct obd_ioctl_data *data)
 
 static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
 {
-	if (data->ioc_len > (1<<30)) {
+	if (data->ioc_len > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_len larger than 1<<30\n");
 		return 1;
 	}

I would suggest to adjust the errormsg also like:
CERROR("OBD ioctl: ioc_len larger than OBD_MAX_IOCTL_BUFFER\n");

otherwise future debuggers will be confused.

just my 2 cents

re,
wh

Quoted 25 lines
drivers/staging/lustre/lustre/include/lustre_lib.h +4 -5
-	if (data->ioc_inllen1 > (1<<30)) {
+	if (data->ioc_inllen1 > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
 		return 1;
 	}
-	if (data->ioc_inllen2 > (1<<30)) {
+	if (data->ioc_inllen2 > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_inllen2 larger than 1<<30\n");
 		return 1;
 	}
-	if (data->ioc_inllen3 > (1<<30)) {
+	if (data->ioc_inllen3 > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_inllen3 larger than 1<<30\n");
 		return 1;
 	}
-	if (data->ioc_inllen4 > (1<<30)) {
+	if (data->ioc_inllen4 > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_inllen4 larger than 1<<30\n");
 		return 1;
 	}
--

To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw
In reply to Dan Carpenter
Quoted 34 lines · walter harms

Am 24.04.2014 23:49, schrieb Dan Carpenter:

Quoted 19 lines

The obd_ioctl_getdata() function caps "data->ioc_len" at OBD_MAX_IOCTL_BUFFER and then calls this obd_ioctl_is_invalid() to check that the other values inside data are valid.

There are several lengths inside data but when they are added together they must not be larger than "data->ioc_len". The checks against "(data->ioc_inllen1 > (1<<30))" are supposed to ensure that the addition does not have an integer overflow. But "(1<<30) * 4" actually can overflow 32 bits so the checks are insufficient.

I have changed it to "> OBD_MAX_IOCTL_BUFFER" instead.

drivers/staging/lustre/lustre/include/lustre_lib.h +0 -0
index 0368ca6..04f549e 100644

drivers/staging/lustre/lustre/include/lustre_lib.h static inline int obd_ioctl_packlen(struct obd_ioctl_data *data) · line 198

Quoted 8 lines
drivers/staging/lustre/lustre/include/lustre_lib.h +1 -1
@@ -192,23 +192,23 @@ static inline int obd_ioctl_packlen(struct obd_ioctl_data *data)
 
 static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
 {
-	if (data->ioc_len > (1<<30)) {
+	if (data->ioc_len > OBD_MAX_IOCTL_BUFFER) {
 		CERROR("OBD ioctl: ioc_len larger than 1<<30\n");
 		return 1;
 	}

I would suggest to adjust the errormsg also like:
CERROR("OBD ioctl: ioc_len larger than OBD_MAX_IOCTL_BUFFER\n");

Quoted 4 lines

otherwise future debuggers will be confused.

just my 2 cents

Ah yes. I will resend.

regards,
dan carpenter

#4 lore raw

PATCH v2 2/2 staging: lustre: integer overflow in obd_ioctl_is_invalid()

The obd_ioctl_getdata() function caps "data->ioc_len" at OBD_MAX_IOCTL_BUFFER and then calls this obd_ioctl_is_invalid() to check that the other values inside data are valid.

There are several lengths inside data but when they are added together they must not be larger than "data->ioc_len". The checks against "(data->ioc_inllen1 > (1<<30))" are supposed to ensure that the addition does not have an integer overflow. But "(1<<30) * 4" actually can overflow 32 bits, so the checks are insufficient.

I have changed it to "> OBD_MAX_IOCTL_BUFFER" instead.

---
v2: Updated the error messages as Walter Harms pointed out.

drivers/staging/lustre/lustre/include/lustre_lib.h +11 -10
index bdc9812..3c26bbd 100644
@@ -179,24 +179,25 @@ static inline int obd_ioctl_packlen(struct obd_ioctl_data *data)
 
 static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
 {
-	if (data->ioc_len > (1<<30)) {
-		CERROR("OBD ioctl: ioc_len larger than 1<<30\n");
+	if (data->ioc_len > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_len larger than %d\n",
+		       OBD_MAX_IOCTL_BUFFER);
 		return 1;
 	}
-	if (data->ioc_inllen1 > (1<<30)) {
-		CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
+	if (data->ioc_inllen1 > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_inllen1 larger than ioc_len\n");
 		return 1;
 	}
-	if (data->ioc_inllen2 > (1<<30)) {
-		CERROR("OBD ioctl: ioc_inllen2 larger than 1<<30\n");
+	if (data->ioc_inllen2 > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_inllen2 larger than ioc_len\n");
 		return 1;
 	}
-	if (data->ioc_inllen3 > (1<<30)) {
-		CERROR("OBD ioctl: ioc_inllen3 larger than 1<<30\n");
+	if (data->ioc_inllen3 > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_inllen3 larger than ioc_len\n");
 		return 1;
 	}
-	if (data->ioc_inllen4 > (1<<30)) {
-		CERROR("OBD ioctl: ioc_inllen4 larger than 1<<30\n");
+	if (data->ioc_inllen4 > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_inllen4 larger than ioc_len\n");
 		return 1;
 	}
 	if (data->ioc_inlbuf1 && !data->ioc_inllen1) {
#5 lore raw

Am 28.04.2014 12:58, schrieb Dan Carpenter:

Quoted 27 lines

The obd_ioctl_getdata() function caps "data->ioc_len" at OBD_MAX_IOCTL_BUFFER and then calls this obd_ioctl_is_invalid() to check that the other values inside data are valid.

There are several lengths inside data but when they are added together they must not be larger than "data->ioc_len". The checks against "(data->ioc_inllen1 > (1<<30))" are supposed to ensure that the addition does not have an integer overflow. But "(1<<30) * 4" actually can overflow 32 bits, so the checks are insufficient.

I have changed it to "> OBD_MAX_IOCTL_BUFFER" instead.

---
v2: Updated the error messages as Walter Harms pointed out.

drivers/staging/lustre/lustre/include/lustre_lib.h +1 -2
index bdc9812..3c26bbd 100644
@@ -179,24 +179,25 @@ static inline int obd_ioctl_packlen(struct obd_ioctl_data *data)
 
 static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
 {
-	if (data->ioc_len > (1<<30)) {
-		CERROR("OBD ioctl: ioc_len larger than 1<<30\n");
+	if (data->ioc_len > OBD_MAX_IOCTL_BUFFER) {

drivers/staging/lustre/lustre/include/lustre_lib.h static inline int obd_ioctl_packlen(struct obd_ioctl_data *data) · line 190

Quoted 10 lines
drivers/staging/lustre/lustre/include/lustre_lib.h +4 -2
+		CERROR("OBD ioctl: ioc_len larger than %d\n",
+		       OBD_MAX_IOCTL_BUFFER);
 		return 1;
 	}
-	if (data->ioc_inllen1 > (1<<30)) {
-		CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
+	if (data->ioc_inllen1 > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_inllen1 larger than ioc_len\n");
 		return 1;
 	}

The error mention ioc_len the compare is OBD_MAX_IOCTL_BUFFER ? Is that intentional ?

re,
wh

Quoted 20 lines
drivers/staging/lustre/lustre/include/lustre_lib.h +6 -6
-	if (data->ioc_inllen2 > (1<<30)) {
-		CERROR("OBD ioctl: ioc_inllen2 larger than 1<<30\n");
+	if (data->ioc_inllen2 > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_inllen2 larger than ioc_len\n");
 		return 1;
 	}
-	if (data->ioc_inllen3 > (1<<30)) {
-		CERROR("OBD ioctl: ioc_inllen3 larger than 1<<30\n");
+	if (data->ioc_inllen3 > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_inllen3 larger than ioc_len\n");
 		return 1;
 	}
-	if (data->ioc_inllen4 > (1<<30)) {
-		CERROR("OBD ioctl: ioc_inllen4 larger than 1<<30\n");
+	if (data->ioc_inllen4 > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_inllen4 larger than ioc_len\n");
 		return 1;
 	}
 	if (data->ioc_inlbuf1 && !data->ioc_inllen1) {
#6 lore raw
Quoted 35 lines · walter harms

Am 28.04.2014 12:58, schrieb Dan Carpenter:

Quoted 32 lines

The obd_ioctl_getdata() function caps "data->ioc_len" at OBD_MAX_IOCTL_BUFFER and then calls this obd_ioctl_is_invalid() to check that the other values inside data are valid.

There are several lengths inside data but when they are added together they must not be larger than "data->ioc_len". The checks against "(data->ioc_inllen1 > (1<<30))" are supposed to ensure that the addition does not have an integer overflow. But "(1<<30) * 4" actually can overflow 32 bits, so the checks are insufficient.

I have changed it to "> OBD_MAX_IOCTL_BUFFER" instead.

---
v2: Updated the error messages as Walter Harms pointed out.

drivers/staging/lustre/lustre/include/lustre_lib.h +3 -3
index bdc9812..3c26bbd 100644
@@ -179,24 +179,25 @@ static inline int obd_ioctl_packlen(struct obd_ioctl_data *data)
 
 static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
 {
-	if (data->ioc_len > (1<<30)) {
-		CERROR("OBD ioctl: ioc_len larger than 1<<30\n");
+	if (data->ioc_len > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_len larger than %d\n",
+		       OBD_MAX_IOCTL_BUFFER);
 		return 1;
 	}
-	if (data->ioc_inllen1 > (1<<30)) {
Quoted 8 lines

drivers/staging/lustre/lustre/include/lustre_lib.h static inline int obd_ioctl_packlen(struct obd_ioctl_data *data) · line 190

Quoted 5 lines
drivers/staging/lustre/lustre/include/lustre_lib.h +2 -1
-		CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
+	if (data->ioc_inllen1 > OBD_MAX_IOCTL_BUFFER) {
+		CERROR("OBD ioctl: ioc_inllen1 larger than ioc_len\n");
 		return 1;
 	}

The error mention ioc_len the compare is OBD_MAX_IOCTL_BUFFER ? Is that intentional ?

Yep.

regards,
dan carpenter