Blame 0011-KCM-Do-not-use-2048-as-fixed-size-for-the-payload.patch

5e5e26a
From 9f078d2e9ec7e1803b6c7e2f8a51e0e185723e76 Mon Sep 17 00:00:00 2001
5e5e26a
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
5e5e26a
Date: Wed, 14 Mar 2018 00:57:39 +0100
5e5e26a
Subject: [PATCH 11/15] KCM: Do not use 2048 as fixed size for the payload
5e5e26a
MIME-Version: 1.0
5e5e26a
Content-Type: text/plain; charset=UTF-8
5e5e26a
Content-Transfer-Encoding: 8bit
5e5e26a
5e5e26a
The KCM code has the limit set as 2048 only inside #ifdef __APPLE__,
5e5e26a
while it should be normally set as 10 * 1024 * 1024, as seen in:
5e5e26a
https://github.com/krb5/krb5/blob/master/src/lib/krb5/ccache/cc_kcm.c#L53
5e5e26a
5e5e26a
Last but not least, doesn't make much sense to use a fixed value as the
5e5e26a
first 4 bytes received are the payload size ... so let's just allocate
5e5e26a
the needed size instead of having a fixed value.
5e5e26a
5e5e26a
Resolves:
5e5e26a
https://pagure.io/SSSD/sssd/issue/3671
5e5e26a
5e5e26a
Signed-off-by: Fabiano FidĂȘncio <fidencio@redhat.com>
5e5e26a
5e5e26a
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
5e5e26a
---
5e5e26a
 src/responder/kcm/kcmsrv_cmd.c | 103 +++++++++++++++++++++++++----------------
5e5e26a
 1 file changed, 62 insertions(+), 41 deletions(-)
5e5e26a
5e5e26a
diff --git a/src/responder/kcm/kcmsrv_cmd.c b/src/responder/kcm/kcmsrv_cmd.c
5e5e26a
index 3ecba9df2..728979da9 100644
5e5e26a
--- a/src/responder/kcm/kcmsrv_cmd.c
5e5e26a
+++ b/src/responder/kcm/kcmsrv_cmd.c
5e5e26a
@@ -38,7 +38,7 @@
5e5e26a
 /* The maximum length of a request or reply as defined by the RPC
5e5e26a
  * protocol. This is the same constant size as MIT KRB5 uses
5e5e26a
  */
5e5e26a
-#define KCM_PACKET_MAX_SIZE 2048
5e5e26a
+#define KCM_PACKET_MAX_SIZE 10*1024*1024
5e5e26a
 
5e5e26a
 /* KCM operation, its raw input and raw output and result */
5e5e26a
 struct kcm_op_io {
5e5e26a
@@ -125,7 +125,6 @@ struct kcm_reqbuf {
5e5e26a
     struct kcm_iovec v_len;
5e5e26a
 
5e5e26a
     /* Includes the major, minor versions etc */
5e5e26a
-    uint8_t msgbuf[KCM_PACKET_MAX_SIZE];
5e5e26a
     struct kcm_iovec v_msg;
5e5e26a
 };
5e5e26a
 
5e5e26a
@@ -238,7 +237,6 @@ struct kcm_repbuf {
5e5e26a
     uint8_t rcbuf[KCM_RETCODE_SIZE];
5e5e26a
     struct kcm_iovec v_rc;
5e5e26a
 
5e5e26a
-    uint8_t msgbuf[KCM_PACKET_MAX_SIZE];
5e5e26a
     struct kcm_iovec v_msg;
5e5e26a
 };
5e5e26a
 
5e5e26a
@@ -259,11 +257,13 @@ static errno_t kcm_failbuf_construct(errno_t ret,
5e5e26a
 /* retcode is 0 if the operation at least ran, non-zero if there
5e5e26a
  * was some kind of internal KCM error, like input couldn't be parsed
5e5e26a
  */
5e5e26a
-static errno_t kcm_output_construct(struct kcm_op_io *op_io,
5e5e26a
+static errno_t kcm_output_construct(TALLOC_CTX *mem_ctx,
5e5e26a
+                                    struct kcm_op_io *op_io,
5e5e26a
                                     struct kcm_repbuf *repbuf)
5e5e26a
 {
5e5e26a
-    size_t c;
5e5e26a
+    uint8_t *rep;
5e5e26a
     size_t replen;
5e5e26a
+    size_t c;
5e5e26a
 
5e5e26a
     replen = sss_iobuf_get_len(op_io->reply);
5e5e26a
     if (replen > KCM_PACKET_MAX_SIZE) {
5e5e26a
@@ -281,14 +281,22 @@ static errno_t kcm_output_construct(struct kcm_op_io *op_io,
5e5e26a
     SAFEALIGN_SETMEM_UINT32(repbuf->rcbuf, 0, &c);
5e5e26a
 
5e5e26a
     if (replen > 0) {
5e5e26a
+        rep = talloc_zero_array(mem_ctx, uint8_t, replen);
5e5e26a
+        if (rep == NULL) {
5e5e26a
+            DEBUG(SSSDBG_CRIT_FAILURE,
5e5e26a
+                  "Failed to allocate memory for the message\n");
5e5e26a
+            return ENOMEM;
5e5e26a
+        }
5e5e26a
+
5e5e26a
         c = 0;
5e5e26a
-        SAFEALIGN_MEMCPY_CHECK(repbuf->msgbuf,
5e5e26a
+        SAFEALIGN_MEMCPY_CHECK(rep,
5e5e26a
                                sss_iobuf_get_data(op_io->reply),
5e5e26a
                                replen,
5e5e26a
-                               repbuf->v_msg.kiov_len,
5e5e26a
+                               replen,
5e5e26a
                                &c);
5e5e26a
 
5e5e26a
-        /* Length of the buffer to send to KCM client */
5e5e26a
+        /* Set the buffer and its length to send to KCM client */
5e5e26a
+        repbuf->v_msg.kiov_base = rep;
5e5e26a
         repbuf->v_msg.kiov_len = replen;
5e5e26a
     }
5e5e26a
 
5e5e26a
@@ -321,24 +329,6 @@ static void kcm_reply_error(struct cli_ctx *cctx,
5e5e26a
     TEVENT_FD_WRITEABLE(cctx->cfde);
5e5e26a
 }
5e5e26a
 
5e5e26a
-static void kcm_send_reply(struct cli_ctx *cctx,
5e5e26a
-                           struct kcm_op_io *op_io,
5e5e26a
-                           struct kcm_repbuf *repbuf)
5e5e26a
-{
5e5e26a
-    errno_t ret;
5e5e26a
-
5e5e26a
-    DEBUG(SSSDBG_TRACE_INTERNAL, "Sending a reply\n");
5e5e26a
-    ret = kcm_output_construct(op_io, repbuf);
5e5e26a
-    if (ret != EOK) {
5e5e26a
-        DEBUG(SSSDBG_CRIT_FAILURE,
5e5e26a
-              "Cannot construct the reply buffer, terminating client\n");
5e5e26a
-        kcm_reply_error(cctx, ret, repbuf);
5e5e26a
-        return;
5e5e26a
-    }
5e5e26a
-
5e5e26a
-    TEVENT_FD_WRITEABLE(cctx->cfde);
5e5e26a
-}
5e5e26a
-
5e5e26a
 /**
5e5e26a
  * Request-reply dispatcher
5e5e26a
  */
5e5e26a
@@ -356,6 +346,26 @@ struct kcm_req_ctx {
5e5e26a
     struct kcm_op_io op_io;
5e5e26a
 };
5e5e26a
 
5e5e26a
+static void kcm_send_reply(struct kcm_req_ctx *req_ctx)
5e5e26a
+{
5e5e26a
+    struct cli_ctx *cctx;
5e5e26a
+    errno_t ret;
5e5e26a
+
5e5e26a
+    DEBUG(SSSDBG_TRACE_INTERNAL, "Sending a reply\n");
5e5e26a
+
5e5e26a
+    cctx = req_ctx->cctx;
5e5e26a
+
5e5e26a
+    ret = kcm_output_construct(cctx, &req_ctx->op_io, &req_ctx->repbuf);
5e5e26a
+    if (ret != EOK) {
5e5e26a
+        DEBUG(SSSDBG_CRIT_FAILURE,
5e5e26a
+              "Cannot construct the reply buffer, terminating client\n");
5e5e26a
+        kcm_reply_error(cctx, ret, &req_ctx->repbuf);
5e5e26a
+        return;
5e5e26a
+    }
5e5e26a
+
5e5e26a
+    TEVENT_FD_WRITEABLE(cctx->cfde);
5e5e26a
+}
5e5e26a
+
5e5e26a
 static void kcm_cmd_request_done(struct tevent_req *req);
5e5e26a
 
5e5e26a
 static errno_t kcm_cmd_dispatch(struct kcm_ctx *kctx,
5e5e26a
@@ -385,11 +395,9 @@ static errno_t kcm_cmd_dispatch(struct kcm_ctx *kctx,
5e5e26a
 static void kcm_cmd_request_done(struct tevent_req *req)
5e5e26a
 {
5e5e26a
     struct kcm_req_ctx *req_ctx;
5e5e26a
-    struct cli_ctx *cctx;
5e5e26a
     errno_t ret;
5e5e26a
 
5e5e26a
     req_ctx = tevent_req_callback_data(req, struct kcm_req_ctx);
5e5e26a
-    cctx = req_ctx->cctx;
5e5e26a
 
5e5e26a
     ret = kcm_cmd_recv(req_ctx, req,
5e5e26a
                        &req_ctx->op_io.reply);
5e5e26a
@@ -397,15 +405,19 @@ static void kcm_cmd_request_done(struct tevent_req *req)
5e5e26a
     if (ret != EOK) {
5e5e26a
         DEBUG(SSSDBG_OP_FAILURE,
5e5e26a
               "KCM operation failed [%d]: %s\n", ret, sss_strerror(ret));
5e5e26a
-        kcm_reply_error(cctx, ret, &req_ctx->repbuf);
5e5e26a
+        kcm_reply_error(req_ctx->cctx, ret, &req_ctx->repbuf);
5e5e26a
         return;
5e5e26a
     }
5e5e26a
 
5e5e26a
-    kcm_send_reply(cctx, &req_ctx->op_io, &req_ctx->repbuf);
5e5e26a
+    kcm_send_reply(req_ctx);
5e5e26a
 }
5e5e26a
 
5e5e26a
-static errno_t kcm_recv_data(int fd, struct kcm_reqbuf *reqbuf)
5e5e26a
+static errno_t kcm_recv_data(TALLOC_CTX *mem_ctx,
5e5e26a
+                             int fd,
5e5e26a
+                             struct kcm_reqbuf *reqbuf)
5e5e26a
 {
5e5e26a
+    uint8_t *msg;
5e5e26a
+    uint32_t msglen;
5e5e26a
     errno_t ret;
5e5e26a
 
5e5e26a
     ret = kcm_read_iovec(fd, &reqbuf->v_len);
5e5e26a
@@ -416,6 +428,24 @@ static errno_t kcm_recv_data(int fd, struct kcm_reqbuf *reqbuf)
5e5e26a
         return ret;
5e5e26a
     }
5e5e26a
 
5e5e26a
+    msglen = kcm_input_get_payload_len(&reqbuf->v_len);
5e5e26a
+    if (msglen > KCM_PACKET_MAX_SIZE) {
5e5e26a
+        DEBUG(SSSDBG_CRIT_FAILURE,
5e5e26a
+              "Request exceeds the KCM protocol limit, aborting\n");
5e5e26a
+        return E2BIG;
5e5e26a
+    }
5e5e26a
+
5e5e26a
+    msg = talloc_zero_array(mem_ctx, uint8_t, msglen);
5e5e26a
+    if (msg == NULL) {
5e5e26a
+        DEBUG(SSSDBG_CRIT_FAILURE,
5e5e26a
+              "Failed to allocate memory for the message\n");
5e5e26a
+        return ENOMEM;
5e5e26a
+    }
5e5e26a
+
5e5e26a
+    /* Set the buffer and its expected len to receive the data */
5e5e26a
+    reqbuf->v_msg.kiov_base = msg;
5e5e26a
+    reqbuf->v_msg.kiov_len = msglen;
5e5e26a
+
5e5e26a
     ret = kcm_read_iovec(fd, &reqbuf->v_msg);
5e5e26a
     if (ret != EOK) {
5e5e26a
         /* Not all errors are fatal, hence we don't print DEBUG messages
5e5e26a
@@ -443,21 +473,12 @@ static struct kcm_req_ctx *kcm_new_req(struct cli_ctx *cctx,
5e5e26a
     req->reqbuf.v_len.kiov_base = req->reqbuf.lenbuf;
5e5e26a
     req->reqbuf.v_len.kiov_len = KCM_MSG_LEN_SIZE;
5e5e26a
 
5e5e26a
-    req->reqbuf.v_msg.kiov_base = req->reqbuf.msgbuf;
5e5e26a
-    req->reqbuf.v_msg.kiov_len = KCM_PACKET_MAX_SIZE;
5e5e26a
-
5e5e26a
     req->repbuf.v_len.kiov_base = req->repbuf.lenbuf;
5e5e26a
     req->repbuf.v_len.kiov_len = KCM_MSG_LEN_SIZE;
5e5e26a
 
5e5e26a
     req->repbuf.v_rc.kiov_base = req->repbuf.rcbuf;
5e5e26a
     req->repbuf.v_rc.kiov_len = KCM_RETCODE_SIZE;
5e5e26a
 
5e5e26a
-    req->repbuf.v_msg.kiov_base = req->repbuf.msgbuf;
5e5e26a
-    /* Length of the msg iobuf will be adjusted later, so far use the full
5e5e26a
-     * length so that constructing the reply can use that capacity
5e5e26a
-     */
5e5e26a
-    req->repbuf.v_msg.kiov_len = KCM_PACKET_MAX_SIZE;
5e5e26a
-
5e5e26a
     req->cctx = cctx;
5e5e26a
     req->kctx = kctx;
5e5e26a
 
5e5e26a
@@ -485,7 +506,7 @@ static void kcm_recv(struct cli_ctx *cctx)
5e5e26a
         cctx->state_ctx = req;
5e5e26a
     }
5e5e26a
 
5e5e26a
-    ret = kcm_recv_data(cctx->cfd, &req->reqbuf);
5e5e26a
+    ret = kcm_recv_data(req, cctx->cfd, &req->reqbuf);
5e5e26a
     switch (ret) {
5e5e26a
     case ENODATA:
5e5e26a
         DEBUG(SSSDBG_TRACE_ALL, "Client closed connection.\n");
5e5e26a
-- 
5e5e26a
2.14.3
5e5e26a