From 9e3e032c260ce32554ee5a11b393b1a807161b62 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Fri, 4 Oct 2013 21:10:01 +0200 Subject: [PATCH] UDS: sendmsg/recvmsg fixes - sendmsg: the accumulation of multiple in-flight file descriptors was already described in the comments; now the code actually does what the comments say :) -- also, added robustness in case of a failure; - recvmsg: only create a socket rights message if there are file descriptors pending at all; - recvmsg: copy back the control message length; - recvmsg: use CMSG_SPACE instead of CMSG_LEN to compute sizes. Not sure if all of this is now working according to specification, but at least tmux seems to be happy with it. Change-Id: I8d076c14c3ff3220b7fea730e0f08f4b4254ede5 --- drivers/uds/ioc_uds.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/drivers/uds/ioc_uds.c b/drivers/uds/ioc_uds.c index b31bcd877..b9336fdfe 100644 --- a/drivers/uds/ioc_uds.c +++ b/drivers/uds/ioc_uds.c @@ -629,7 +629,7 @@ do_recvfrom(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) static int msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data, - devminor_t minor) + devminor_t minor, int *new_total) { int i, rc, nfds, totalfds; struct msghdr msghdr; @@ -669,34 +669,36 @@ msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data, } } - data->nfiledes = totalfds; + *new_total = totalfds; return OK; } static int -send_fds(devminor_t minor, struct ancillary *data) +send_fds(devminor_t minor, struct ancillary *data, int new_total) { int rc, i, j; dprintf(("UDS: send_fds(%d)\n", minor)); /* Verify the file descriptors and get their filps. */ - for (i = 0; i < data->nfiledes; i++) { + for (i = data->nfiledes; i < new_total; i++) { if ((rc = vfs_verify_fd(uds_fd_table[minor].owner, data->fds[i], &data->filps[i])) != OK) return rc; } /* Set them as in-flight. */ - for (i = 0; i < data->nfiledes; i++) { + for (i = data->nfiledes; i < new_total; i++) { if ((rc = vfs_set_filp(data->filps[i])) != OK) { - for (j = i - 1; j >= 0; j--) + for (j = i - 1; j >= data->nfiledes; j--) vfs_put_filp(data->filps[j]); /* revert */ return rc; } } + data->nfiledes = new_total; + return OK; } @@ -805,7 +807,7 @@ recv_cred(devminor_t minor, struct ancillary *data, static int do_sendmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) { - int peer, rc, i; + int peer, rc, i, new_total; struct msg_control msg_ctrl; dprintf(("UDS: do_sendmsg(%d)\n", minor)); @@ -854,10 +856,10 @@ do_sendmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) * ones. */ if ((rc = msg_control_read(&msg_ctrl, - &uds_fd_table[peer].ancillary_data, minor)) != OK) + &uds_fd_table[peer].ancillary_data, minor, &new_total)) != OK) return rc; - return send_fds(minor, &uds_fd_table[peer].ancillary_data); + return send_fds(minor, &uds_fd_table[peer].ancillary_data, new_total); } static int @@ -888,26 +890,30 @@ do_recvmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant) clen_avail = MIN(msg_ctrl.msg_controllen, MSG_CONTROL_MAX); if (uds_fd_table[minor].ancillary_data.nfiledes > 0) { - clen_needed = CMSG_LEN(sizeof(int) * + clen_needed = CMSG_SPACE(sizeof(int) * uds_fd_table[minor].ancillary_data.nfiledes); } /* if there is room we also include credentials */ - clen_desired = clen_needed + CMSG_LEN(sizeof(struct uucred)); + clen_desired = clen_needed + CMSG_SPACE(sizeof(struct uucred)); if (clen_needed > clen_avail) return EOVERFLOW; - rc = recv_fds(minor, &uds_fd_table[minor].ancillary_data, &msg_ctrl); - if (rc != OK) - return rc; + if (uds_fd_table[minor].ancillary_data.nfiledes > 0) { + if ((rc = recv_fds(minor, &uds_fd_table[minor].ancillary_data, + &msg_ctrl)) != OK) + return rc; + } if (clen_desired <= clen_avail) { rc = recv_cred(minor, &uds_fd_table[minor].ancillary_data, &msg_ctrl); if (rc != OK) return rc; - } + msg_ctrl.msg_controllen = clen_desired; + } else + msg_ctrl.msg_controllen = clen_needed; /* Send the control data to the user. */ return sys_safecopyto(endpt, grant, 0, (vir_bytes) &msg_ctrl, -- 2.44.0