Commit 4bf613c6 authored by Dan Carpenter's avatar Dan Carpenter Committed by David S. Miller

irda: buffer overflow in irnet_ctrl_read()

The comments here say that the /* Max event is 61 char */ but in 2003 we
changed the event format and now the max event size is 75.  The longest
event is:

	"Discovered %08x (%s) behind %08x {hints %02X-%02X}\n",
         12345678901    23  456789012    34567890    1    2 3
	            +8    +21        +8          +2   +2     +1
         = 75 characters.

There was a check to return -EOVERFLOW if the user gave us a "count"
value that was less than 64.  Raising it to 75 might break backwards
compatability.  Instead I removed the check and now it returns a
truncated string if "count" is too low.
Signed-off-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6efecd8c
...@@ -214,8 +214,7 @@ irnet_get_discovery_log(irnet_socket * ap) ...@@ -214,8 +214,7 @@ irnet_get_discovery_log(irnet_socket * ap)
* After reading : discoveries = NULL ; disco_index = Y ; disco_number = -1 * After reading : discoveries = NULL ; disco_index = Y ; disco_number = -1
*/ */
static inline int static inline int
irnet_read_discovery_log(irnet_socket * ap, irnet_read_discovery_log(irnet_socket *ap, char *event, int buf_size)
char * event)
{ {
int done_event = 0; int done_event = 0;
...@@ -237,12 +236,13 @@ irnet_read_discovery_log(irnet_socket * ap, ...@@ -237,12 +236,13 @@ irnet_read_discovery_log(irnet_socket * ap,
if(ap->disco_index < ap->disco_number) if(ap->disco_index < ap->disco_number)
{ {
/* Write an event */ /* Write an event */
sprintf(event, "Found %08x (%s) behind %08x {hints %02X-%02X}\n", snprintf(event, buf_size,
ap->discoveries[ap->disco_index].daddr, "Found %08x (%s) behind %08x {hints %02X-%02X}\n",
ap->discoveries[ap->disco_index].info, ap->discoveries[ap->disco_index].daddr,
ap->discoveries[ap->disco_index].saddr, ap->discoveries[ap->disco_index].info,
ap->discoveries[ap->disco_index].hints[0], ap->discoveries[ap->disco_index].saddr,
ap->discoveries[ap->disco_index].hints[1]); ap->discoveries[ap->disco_index].hints[0],
ap->discoveries[ap->disco_index].hints[1]);
DEBUG(CTRL_INFO, "Writing discovery %d : %s\n", DEBUG(CTRL_INFO, "Writing discovery %d : %s\n",
ap->disco_index, ap->discoveries[ap->disco_index].info); ap->disco_index, ap->discoveries[ap->disco_index].info);
...@@ -282,27 +282,24 @@ irnet_ctrl_read(irnet_socket * ap, ...@@ -282,27 +282,24 @@ irnet_ctrl_read(irnet_socket * ap,
size_t count) size_t count)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
char event[64]; /* Max event is 61 char */ char event[75];
ssize_t ret = 0; ssize_t ret = 0;
DENTER(CTRL_TRACE, "(ap=0x%p, count=%Zd)\n", ap, count); DENTER(CTRL_TRACE, "(ap=0x%p, count=%Zd)\n", ap, count);
/* Check if we can write an event out in one go */
DABORT(count < sizeof(event), -EOVERFLOW, CTRL_ERROR, "Buffer to small.\n");
#ifdef INITIAL_DISCOVERY #ifdef INITIAL_DISCOVERY
/* Check if we have read the log */ /* Check if we have read the log */
if(irnet_read_discovery_log(ap, event)) if (irnet_read_discovery_log(ap, event, sizeof(event)))
{ {
/* We have an event !!! Copy it to the user */ count = min(strlen(event), count);
if(copy_to_user(buf, event, strlen(event))) if (copy_to_user(buf, event, count))
{ {
DERROR(CTRL_ERROR, "Invalid user space pointer.\n"); DERROR(CTRL_ERROR, "Invalid user space pointer.\n");
return -EFAULT; return -EFAULT;
} }
DEXIT(CTRL_TRACE, "\n"); DEXIT(CTRL_TRACE, "\n");
return strlen(event); return count;
} }
#endif /* INITIAL_DISCOVERY */ #endif /* INITIAL_DISCOVERY */
...@@ -339,79 +336,81 @@ irnet_ctrl_read(irnet_socket * ap, ...@@ -339,79 +336,81 @@ irnet_ctrl_read(irnet_socket * ap,
switch(irnet_events.log[ap->event_index].event) switch(irnet_events.log[ap->event_index].event)
{ {
case IRNET_DISCOVER: case IRNET_DISCOVER:
sprintf(event, "Discovered %08x (%s) behind %08x {hints %02X-%02X}\n", snprintf(event, sizeof(event),
irnet_events.log[ap->event_index].daddr, "Discovered %08x (%s) behind %08x {hints %02X-%02X}\n",
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].saddr, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].hints.byte[0], irnet_events.log[ap->event_index].saddr,
irnet_events.log[ap->event_index].hints.byte[1]); irnet_events.log[ap->event_index].hints.byte[0],
irnet_events.log[ap->event_index].hints.byte[1]);
break; break;
case IRNET_EXPIRE: case IRNET_EXPIRE:
sprintf(event, "Expired %08x (%s) behind %08x {hints %02X-%02X}\n", snprintf(event, sizeof(event),
irnet_events.log[ap->event_index].daddr, "Expired %08x (%s) behind %08x {hints %02X-%02X}\n",
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].saddr, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].hints.byte[0], irnet_events.log[ap->event_index].saddr,
irnet_events.log[ap->event_index].hints.byte[1]); irnet_events.log[ap->event_index].hints.byte[0],
irnet_events.log[ap->event_index].hints.byte[1]);
break; break;
case IRNET_CONNECT_TO: case IRNET_CONNECT_TO:
sprintf(event, "Connected to %08x (%s) on ppp%d\n", snprintf(event, sizeof(event), "Connected to %08x (%s) on ppp%d\n",
irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].unit); irnet_events.log[ap->event_index].unit);
break; break;
case IRNET_CONNECT_FROM: case IRNET_CONNECT_FROM:
sprintf(event, "Connection from %08x (%s) on ppp%d\n", snprintf(event, sizeof(event), "Connection from %08x (%s) on ppp%d\n",
irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].unit); irnet_events.log[ap->event_index].unit);
break; break;
case IRNET_REQUEST_FROM: case IRNET_REQUEST_FROM:
sprintf(event, "Request from %08x (%s) behind %08x\n", snprintf(event, sizeof(event), "Request from %08x (%s) behind %08x\n",
irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].saddr); irnet_events.log[ap->event_index].saddr);
break; break;
case IRNET_NOANSWER_FROM: case IRNET_NOANSWER_FROM:
sprintf(event, "No-answer from %08x (%s) on ppp%d\n", snprintf(event, sizeof(event), "No-answer from %08x (%s) on ppp%d\n",
irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].unit); irnet_events.log[ap->event_index].unit);
break; break;
case IRNET_BLOCKED_LINK: case IRNET_BLOCKED_LINK:
sprintf(event, "Blocked link with %08x (%s) on ppp%d\n", snprintf(event, sizeof(event), "Blocked link with %08x (%s) on ppp%d\n",
irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].unit); irnet_events.log[ap->event_index].unit);
break; break;
case IRNET_DISCONNECT_FROM: case IRNET_DISCONNECT_FROM:
sprintf(event, "Disconnection from %08x (%s) on ppp%d\n", snprintf(event, sizeof(event), "Disconnection from %08x (%s) on ppp%d\n",
irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].unit); irnet_events.log[ap->event_index].unit);
break; break;
case IRNET_DISCONNECT_TO: case IRNET_DISCONNECT_TO:
sprintf(event, "Disconnected to %08x (%s)\n", snprintf(event, sizeof(event), "Disconnected to %08x (%s)\n",
irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].name); irnet_events.log[ap->event_index].name);
break; break;
default: default:
sprintf(event, "Bug\n"); snprintf(event, sizeof(event), "Bug\n");
} }
/* Increment our event index */ /* Increment our event index */
ap->event_index = (ap->event_index + 1) % IRNET_MAX_EVENTS; ap->event_index = (ap->event_index + 1) % IRNET_MAX_EVENTS;
DEBUG(CTRL_INFO, "Event is :%s", event); DEBUG(CTRL_INFO, "Event is :%s", event);
/* Copy it to the user */ count = min(strlen(event), count);
if(copy_to_user(buf, event, strlen(event))) if (copy_to_user(buf, event, count))
{ {
DERROR(CTRL_ERROR, "Invalid user space pointer.\n"); DERROR(CTRL_ERROR, "Invalid user space pointer.\n");
return -EFAULT; return -EFAULT;
} }
DEXIT(CTRL_TRACE, "\n"); DEXIT(CTRL_TRACE, "\n");
return strlen(event); return count;
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment