port_init() parses the port channel number into an int, formats it into
a small fixed string buffer, and later passes it to htons() for bind().
Out-of-range values can therefore overflow the local device-name buffer
and still get silently truncated at the socket layer.
Reject port numbers that do not fit in the 16-bit TCP/UDP port range.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
arch/um/drivers/port_user.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 3c62ae81df62..b3d393811d69 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -19,7 +19,7 @@ struct port_chan {
int raw;
struct termios tt;
void *kernel_data;
- char dev[sizeof("32768\0")];
+ char dev[sizeof("65535")];
};
static void *port_init(char *str, int device, const struct chan_opts *opts)
@@ -27,6 +27,7 @@ static void *port_init(char *str, int device, const struct chan_opts *opts)
struct port_chan *data;
void *kern_data;
char *end;
+ unsigned long parsed_port;
int port;
if (*str != ':') {
@@ -35,12 +36,13 @@ static void *port_init(char *str, int device, const struct chan_opts *opts)
return NULL;
}
str++;
- port = strtoul(str, &end, 0);
- if ((*end != '\0') || (end == str)) {
+ parsed_port = strtoul(str, &end, 0);
+ if ((*end != '\0') || end == str || parsed_port > 65535) {
printk(UM_KERN_ERR "port_init : couldn't parse port '%s'\n",
str);
return NULL;
}
+ port = parsed_port;
kern_data = port_data(port);
if (kern_data == NULL)
--
2.50.1 (Apple Git-155)