[IrDA patch] ir247_ias_fix_max.diff

Jean Tourrilhes (jt@bougret.hpl.hp.com)
Thu, 13 Sep 2001 16:18:25 -0700


ir247_ias_fix_max.diff :
----------------------
o [CRITICA] Check overflow in string duplicate code in IAS/IAP
- It was only done (more or less) if DEBUG was enabled
o [CORRECT] Fix deadlock on legal large OCT_SEQ IAP replies
o [CORRECT] Increase max IAS attribute size for IrDA compliance

diff -u -p linux/include/linux/irda.d8.h linux/include/linux/irda.h
--- linux/include/linux/irda.d8.h Thu Sep 13 11:35:56 2001
+++ linux/include/linux/irda.h Thu Sep 13 11:38:31 2001
@@ -92,10 +92,15 @@ enum {

#define IRTTP_MAX_SDU_SIZE IRLMP_MAX_SDU_SIZE /* Compatibility */

-#define IAS_MAX_STRING 256
-#define IAS_MAX_OCTET_STRING 1024
-#define IAS_MAX_CLASSNAME 64
-#define IAS_MAX_ATTRIBNAME 256
+#define IAS_MAX_STRING 256 /* See IrLMP 1.1, 4.3.3.2 */
+#define IAS_MAX_OCTET_STRING 1024 /* See IrLMP 1.1, 4.3.3.2 */
+#define IAS_MAX_CLASSNAME 60 /* See IrLMP 1.1, 4.3.1 */
+#define IAS_MAX_ATTRIBNAME 60 /* See IrLMP 1.1, 4.3.3.1 */
+#define IAS_MAX_ATTRIBNUMBER 256 /* See IrLMP 1.1, 4.3.3.1 */
+/* For user space backward compatibility - may be fixed in kernel 2.5.X
+ * Note : need 60+1 ('\0'), make it 64 for alignement - Jean II */
+#define IAS_EXPORT_CLASSNAME 64
+#define IAS_EXPORT_ATTRIBNAME 256

/* Attribute type needed for struct irda_ias_set */
#define IAS_MISSING 0
@@ -126,8 +131,8 @@ struct irda_device_list {
};

struct irda_ias_set {
- char irda_class_name[IAS_MAX_CLASSNAME];
- char irda_attrib_name[IAS_MAX_ATTRIBNAME];
+ char irda_class_name[IAS_EXPORT_CLASSNAME];
+ char irda_attrib_name[IAS_EXPORT_ATTRIBNAME];
unsigned int irda_attrib_type;
union {
unsigned int irda_attrib_int;
diff -u -p linux/include/net/irda/irias_object.d8.h linux/include/net/irda/irias_object.h
--- linux/include/net/irda/irias_object.d8.h Thu Sep 13 11:36:24 2001
+++ linux/include/net/irda/irias_object.h Thu Sep 13 11:38:31 2001
@@ -78,7 +78,7 @@ struct ias_attrib {
struct ias_value *value; /* Attribute value */
};

-char *strdup(char *str);
+char *strndup(char *str, int max);

struct ias_object *irias_new_object(char *name, int id);
void irias_insert_object(struct ias_object *obj);
diff -u -p linux/net/irda/irias_object.d8.c linux/net/irda/irias_object.c
--- linux/net/irda/irias_object.d8.c Thu Sep 13 11:36:46 2001
+++ linux/net/irda/irias_object.c Thu Sep 13 11:38:31 2001
@@ -37,25 +37,35 @@ hashbin_t *objects = NULL;
struct ias_value missing = { IAS_MISSING, 0, 0, 0, {0}};

/*
- * Function strdup (str)
+ * Function strndup (str, max)
*
- * My own kernel version of strdup!
+ * My own kernel version of strndup!
*
+ * Faster, check boundary... Jean II
*/
-char *strdup(char *str)
+char *strndup(char *str, int max)
{
char *new_str;
+ int len;

+ /* Check string */
if (str == NULL)
return NULL;
-
- ASSERT(strlen( str) < 64, return NULL;);
-
- new_str = kmalloc(strlen(str)+1, GFP_ATOMIC);
- if (new_str == NULL)
+ /* Check length, truncate */
+ len = strlen(str);
+ if(len > max)
+ len = max;
+
+ /* Allocate new string */
+ new_str = kmalloc(len + 1, GFP_ATOMIC);
+ if (new_str == NULL) {
+ WARNING(__FUNCTION__"(), Unable to kmalloc!\n");
return NULL;
-
- strcpy(new_str, str);
+ }
+
+ /* Copy and truncate */
+ memcpy(new_str, str, len);
+ new_str[len] = '\0';

return new_str;
}
@@ -81,7 +91,7 @@ struct ias_object *irias_new_object( cha
memset(obj, 0, sizeof( struct ias_object));

obj->magic = IAS_OBJECT_MAGIC;
- obj->name = strdup( name);
+ obj->name = strndup(name, IAS_MAX_CLASSNAME);
obj->id = id;

obj->attribs = hashbin_new(HB_LOCAL);
@@ -315,7 +325,7 @@ void irias_add_integer_attrib(struct ias
memset(attrib, 0, sizeof( struct ias_attrib));

attrib->magic = IAS_ATTRIB_MAGIC;
- attrib->name = strdup(name);
+ attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);

/* Insert value */
attrib->value = irias_new_integer_value(value);
@@ -351,7 +361,7 @@ void irias_add_octseq_attrib(struct ias_
memset(attrib, 0, sizeof( struct ias_attrib));

attrib->magic = IAS_ATTRIB_MAGIC;
- attrib->name = strdup( name);
+ attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);

attrib->value = irias_new_octseq_value( octets, len);

@@ -384,7 +394,7 @@ void irias_add_string_attrib(struct ias_
memset(attrib, 0, sizeof( struct ias_attrib));

attrib->magic = IAS_ATTRIB_MAGIC;
- attrib->name = strdup(name);
+ attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);

attrib->value = irias_new_string_value(value);

@@ -420,10 +430,13 @@ struct ias_value *irias_new_integer_valu
*
* Create new IAS string value
*
+ * Per IrLMP 1.1, 4.3.3.2, strings are up to 256 chars - Jean II
*/
struct ias_value *irias_new_string_value(char *string)
{
struct ias_value *value;
+ int len;
+ char *new_str;

value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
if (value == NULL) {
@@ -434,8 +447,8 @@ struct ias_value *irias_new_string_value

value->type = IAS_STRING;
value->charset = CS_ASCII;
- value->len = strlen(string);
- value->t.string = strdup(string);
+ value->t.string = strndup(string, IAS_MAX_STRING);
+ value->len = strlen(value->t.string);

return value;
}
@@ -446,6 +459,7 @@ struct ias_value *irias_new_string_value
*
* Create new IAS octet-sequence value
*
+ * Per IrLMP 1.1, 4.3.3.2, octet-sequence are up to 1024 bytes - Jean II
*/
struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
{
@@ -459,11 +473,15 @@ struct ias_value *irias_new_octseq_value
memset(value, 0, sizeof(struct ias_value));

value->type = IAS_OCT_SEQ;
+ /* Check length */
+ if(len > IAS_MAX_OCTET_STRING)
+ len = IAS_MAX_OCTET_STRING;
value->len = len;

value->t.oct_seq = kmalloc(len, GFP_ATOMIC);
if (value->t.oct_seq == NULL){
WARNING(__FUNCTION__"(), Unable to kmalloc!\n");
+ kfree(value);
return NULL;
}
memcpy(value->t.oct_seq, octseq , len);
diff -u -p linux/net/irda/iriap.d8.c linux/net/irda/iriap.c
--- linux/net/irda/iriap.d8.c Thu Sep 13 11:37:13 2001
+++ linux/net/irda/iriap.c Thu Sep 13 11:38:31 2001
@@ -379,7 +379,7 @@ int iriap_getvaluebyclass_request(struct
char *name, char *attr)
{
struct sk_buff *skb;
- int name_len, attr_len;
+ int name_len, attr_len, skb_len;
__u8 *frame;

ASSERT(self != NULL, return -1;);
@@ -400,13 +400,14 @@ int iriap_getvaluebyclass_request(struct
/* Give ourselves 10 secs to finish this operation */
iriap_start_watchdog_timer(self, 10*HZ);

- skb = dev_alloc_skb(64);
+ name_len = strlen(name); /* Up to IAS_MAX_CLASSNAME = 60 */
+ attr_len = strlen(attr); /* Up to IAS_MAX_ATTRIBNAME = 60 */
+
+ skb_len = self->max_header_size+2+name_len+1+attr_len+4;
+ skb = dev_alloc_skb(skb_len);
if (!skb)
return -ENOMEM;

- name_len = strlen(name);
- attr_len = strlen(attr);
-
/* Reserve space for MUX and LAP header */
skb_reserve(skb, self->max_header_size);
skb_put(skb, 3+name_len+attr_len);
@@ -500,20 +501,19 @@ void iriap_getvaluebyclass_confirm(struc
}
value_len = fp[n++];
IRDA_DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
- ASSERT(value_len < 64, return;);

/* Make sure the string is null-terminated */
fp[n+value_len] = 0x00;
-
IRDA_DEBUG(4, "Got string %s\n", fp+n);
+
+ /* Will truncate to IAS_MAX_STRING bytes */
value = irias_new_string_value(fp+n);
break;
case IAS_OCT_SEQ:
value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
n += 2;

- ASSERT(value_len <= 55, return;);
-
+ /* Will truncate to IAS_MAX_OCTET_STRING bytes */
value = irias_new_octseq_value(fp+n, value_len);
break;
default:
@@ -635,8 +635,8 @@ void iriap_getvaluebyclass_indication(st
struct ias_attrib *attrib;
int name_len;
int attr_len;
- char name[64];
- char attr[64];
+ char name[IAS_MAX_CLASSNAME + 1]; /* 60 bytes */
+ char attr[IAS_MAX_ATTRIBNAME + 1]; /* 60 bytes */
__u8 *fp;
int n;

@@ -1013,7 +1013,7 @@ int irias_proc_read(char *buf, char **st
attrib->value->t.string);
break;
case IAS_OCT_SEQ:
- len += sprintf(buf+len, "octet sequence\n");
+ len += sprintf(buf+len, "octet sequence (%d bytes)\n", attrib->value->len);
break;
case IAS_MISSING:
len += sprintf(buf+len, "missing\n");
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/