<div dir="ltr">Applied.</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 20, 2017 at 2:39 PM, Gris Ge <span dir="ltr"><<a href="mailto:fge@redhat.com" target="_blank">fge@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Problem:<br>
<br>
mpath_recv_reply() from libmpathcmd return -EINVAL on command 'show<br>
maps json' with 2k paths. No error will be triggered for command<br>
`multipathd -k'show maps json` as multipathd is using their own<br>
implementation on recv_packet() which does not have size limitation.<br>
<br>
Root cause:<br>
<br>
Commit 174e717d351789a3cb29e1417f8e91<wbr>0baabcdb16 introduced the<br>
limitation on max bytes(65535) of reply string from multipathd.<br>
With 2k paths(1k mpaths) simulated by scsi_debug, the 'show maps json'<br>
requires 2066784 bytes which trigged the EINVAL error.<br>
<br>
Fix:<br>
* Remove the limitation of MAX_REPLY_LEN in libmpathcmd.<br>
<br>
* New functions `recv_packet_from_client()` in uxsock.h of libmultipath<br>
which enforce the limitation of buffer size to 512(_MAX_CMD_LEN).<br>
<br>
* Change multipathd socket listener to use<br>
`recv_packet_from_client()`.<br>
<br>
Signed-off-by: Gris Ge <<a href="mailto:fge@redhat.com">fge@redhat.com</a>><br>
---<br>
libmpathcmd/mpath_cmd.c | 2 --<br>
libmultipath/uxsock.c | 39 ++++++++++++++++++++++++++++++<wbr>---------<br>
libmultipath/uxsock.h | 9 +++++++++<br>
multipathd/uxlsnr.c | 8 +++++---<br>
4 files changed, 44 insertions(+), 14 deletions(-)<br>
<br>
diff --git a/libmpathcmd/mpath_cmd.c b/libmpathcmd/mpath_cmd.c<br>
index d9c5790..7fc9e98 100644<br>
--- a/libmpathcmd/mpath_cmd.c<br>
+++ b/libmpathcmd/mpath_cmd.c<br>
@@ -142,8 +142,6 @@ int mpath_recv_reply(int fd, char **reply, unsigned int timeout)<br>
len = mpath_recv_reply_len(fd, timeout);<br>
if (len <= 0)<br>
return len;<br>
- if (len > MAX_REPLY_LEN)<br>
- return -EINVAL;<br>
*reply = malloc(len);<br>
if (!*reply)<br>
return -1;<br>
diff --git a/libmultipath/uxsock.c b/libmultipath/uxsock.c<br>
index 0ca9e50..492f4b9 100644<br>
--- a/libmultipath/uxsock.c<br>
+++ b/libmultipath/uxsock.c<br>
@@ -24,6 +24,16 @@<br>
#include "memory.h"<br>
#include "uxsock.h"<br>
#include "debug.h"<br>
+<br>
+/*<br>
+ * Code is similar with mpath_recv_reply() with data size limitation<br>
+ * and debug-able malloc.<br>
+ * When limit == 0, it means no limit on data size, used for socket client<br>
+ * to receiving data from multipathd.<br>
+ */<br>
+static int _recv_packet(int fd, char **buf, unsigned int timeout,<br>
+ ssize_t limit);<br>
+<br>
/*<br>
* create a unix domain socket and start listening on it<br>
* return a file descriptor open on the socket<br>
@@ -81,26 +91,37 @@ int send_packet(int fd, const char *buf)<br>
return mpath_send_cmd(fd, buf);<br>
}<br>
<br>
-/*<br>
- * receive a packet in length prefix format<br>
- */<br>
-int recv_packet(int fd, char **buf, unsigned int timeout)<br>
+static int _recv_packet(int fd, char **buf, unsigned int timeout, ssize_t limit)<br>
{<br>
- int err;<br>
- ssize_t len;<br>
+ int err = 0;<br>
+ ssize_t len = 0;<br>
<br>
*buf = NULL;<br>
len = mpath_recv_reply_len(fd, timeout);<br>
if (len <= 0)<br>
return len;<br>
+ if ((limit > 0) && (len > limit))<br>
+ return -EINVAL;<br>
(*buf) = MALLOC(len);<br>
if (!*buf)<br>
return -ENOMEM;<br>
err = mpath_recv_reply_data(fd, *buf, len, timeout);<br>
- if (err) {<br>
+ if (err != 0) {<br>
FREE(*buf);<br>
(*buf) = NULL;<br>
- return err;<br>
}<br>
- return 0;<br>
+ return err;<br>
+}<br>
+<br>
+/*<br>
+ * receive a packet in length prefix format<br>
+ */<br>
+int recv_packet(int fd, char **buf, unsigned int timeout)<br>
+{<br>
+ return _recv_packet(fd, buf, timeout, 0 /* no limit */);<br>
+}<br>
+<br>
+int recv_packet_from_client(int fd, char **buf, unsigned int timeout)<br>
+{<br>
+ return _recv_packet(fd, buf, timeout, _MAX_CMD_LEN);<br>
}<br>
diff --git a/libmultipath/uxsock.h b/libmultipath/uxsock.h<br>
index 442b564..8e7401d 100644<br>
--- a/libmultipath/uxsock.h<br>
+++ b/libmultipath/uxsock.h<br>
@@ -2,3 +2,12 @@<br>
int ux_socket_listen(const char *name);<br>
int send_packet(int fd, const char *buf);<br>
int recv_packet(int fd, char **buf, unsigned int timeout);<br>
+<br>
+#define _MAX_CMD_LEN 512<br>
+<br>
+/*<br>
+ * Used for receiving socket command from untrusted socket client where data<br>
+ * size is restricted to 512(_MAX_CMD_LEN) at most.<br>
+ * Return -EINVAL if data length requested by client exceeded the _MAX_CMD_LEN.<br>
+ */<br>
+int recv_packet_from_client(int fd, char **buf, unsigned int timeout);<br>
diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c<br>
index dfef03e..6ca62af 100644<br>
--- a/multipathd/uxlsnr.c<br>
+++ b/multipathd/uxlsnr.c<br>
@@ -241,13 +241,15 @@ void * uxsock_listen(uxsock_trigger_<wbr>fn uxsock_trigger, void * trigger_data)<br>
if (clock_gettime(CLOCK_<wbr>MONOTONIC, &start_time)<br>
!= 0)<br>
start_time.tv_sec = 0;<br>
- if (recv_packet(c->fd, &inbuf,<br>
- uxsock_timeout) != 0) {<br>
+ if (recv_packet_from_client(c-><wbr>fd, &inbuf,<br>
+ uxsock_timeout)<br>
+ != 0) {<br>
dead_client(c);<br>
continue;<br>
}<br>
if (!inbuf) {<br>
- condlog(4, "recv_packet get null request");<br>
+ condlog(4, "recv_packet_from_client "<br>
+ "get null request");<br>
continue;<br>
}<br>
condlog(4, "cli[%d]: Got request [%s]",<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.3.1<br>
<br>
--<br>
dm-devel mailing list<br>
<a href="mailto:dm-devel@redhat.com">dm-devel@redhat.com</a><br>
<a href="https://www.redhat.com/mailman/listinfo/dm-devel" rel="noreferrer" target="_blank">https://www.redhat.com/<wbr>mailman/listinfo/dm-devel</a><br>
</font></span></blockquote></div><br></div>