mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-02 12:30:24 +08:00
Cygwin: AF_UNIX: improve control message handling
This includes various changes to create_cmsg_data and evaluate_cmsg_data. The most important are: - create_cmsg_data now allows only one SCM_RIGHTS message and one SCM_CREDENTIALS message. - evaluate_cmsg_data now truncates the ancillary data to the number of control messages that will fit in the supplied buffer. Previously it discarded all control messages if the buffer was too small. See https://man7.org/linux/man-pages/man7/unix.7.html.
This commit is contained in:
parent
d42acb9bc8
commit
3d37fd9cef
@ -1948,7 +1948,7 @@ fhandler_socket_unix::evaluate_cmsg_data (af_unix_pkt_hdr_t *packet,
|
|||||||
|
|
||||||
/* Massage the received control messages. */
|
/* Massage the received control messages. */
|
||||||
msg1.msg_control = tp.w_get ();
|
msg1.msg_control = tp.w_get ();
|
||||||
msg1.msg_controllen = packet->cmsg_len + CMSG_SPACE (0);
|
msg1.msg_controllen = MIN (msg->msg_controllen, packet->cmsg_len);
|
||||||
memset (msg1.msg_control, 0, msg1.msg_controllen);
|
memset (msg1.msg_control, 0, msg1.msg_controllen);
|
||||||
msg2.msg_control = AF_UNIX_PKT_CMSG (packet);
|
msg2.msg_control = AF_UNIX_PKT_CMSG (packet);
|
||||||
msg2.msg_controllen = packet->cmsg_len;
|
msg2.msg_controllen = packet->cmsg_len;
|
||||||
@ -1958,40 +1958,30 @@ fhandler_socket_unix::evaluate_cmsg_data (af_unix_pkt_hdr_t *packet,
|
|||||||
for (struct cmsghdr *q = CMSG_FIRSTHDR (&msg2); q != NULL;
|
for (struct cmsghdr *q = CMSG_FIRSTHDR (&msg2); q != NULL;
|
||||||
q = CMSG_NXTHDR (&msg2, q))
|
q = CMSG_NXTHDR (&msg2, q))
|
||||||
{
|
{
|
||||||
struct cmsghdr *p1; /* Lags behind p. */
|
|
||||||
|
|
||||||
switch (q->cmsg_type)
|
switch (q->cmsg_type)
|
||||||
{
|
{
|
||||||
case SCM_CREDENTIALS:
|
case SCM_CREDENTIALS:
|
||||||
if (so_passcred ())
|
if (!so_passcred ())
|
||||||
memcpy (p, q, q->cmsg_len);
|
|
||||||
else
|
|
||||||
continue;
|
continue;
|
||||||
break;
|
|
||||||
case SCM_RIGHTS:
|
case SCM_RIGHTS:
|
||||||
/* Deserialize, check length, copy new cmsghdr block, update
|
/* FIXME: Deserialize and change fds. */
|
||||||
len. For now, just copy without deserialization for
|
|
||||||
testing purposes. */
|
|
||||||
memcpy (p, q, q->cmsg_len);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
p1 = p;
|
if (!p || len + CMSG_ALIGN (q->cmsg_len) > (size_t) msg1.msg_controllen)
|
||||||
|
{
|
||||||
|
msg->msg_flags |= MSG_CTRUNC;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
memcpy (p, q, q->cmsg_len);
|
||||||
|
len += CMSG_ALIGN (q->cmsg_len);
|
||||||
p = CMSG_NXTHDR (&msg1, p);
|
p = CMSG_NXTHDR (&msg1, p);
|
||||||
len += (PBYTE) p - (PBYTE) p1;
|
|
||||||
}
|
}
|
||||||
if (msg->msg_controllen < (int) len)
|
out:
|
||||||
{
|
|
||||||
msg->msg_flags |= MSG_TRUNC;
|
|
||||||
msg->msg_controllen = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy (msg->msg_control, msg1.msg_control, len);
|
memcpy (msg->msg_control, msg1.msg_control, len);
|
||||||
msg->msg_controllen = len;
|
msg->msg_controllen = len;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2551,17 +2541,15 @@ bool
|
|||||||
fhandler_socket_unix::create_cmsg_data (af_unix_pkt_hdr_t *packet,
|
fhandler_socket_unix::create_cmsg_data (af_unix_pkt_hdr_t *packet,
|
||||||
const struct msghdr *msg)
|
const struct msghdr *msg)
|
||||||
{
|
{
|
||||||
bool saw_scm_cred = false;
|
bool saw_scm_cred = false, saw_scm_rights = false;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
struct msghdr msgh;
|
struct msghdr msgh;
|
||||||
tmp_pathbuf tp;
|
tmp_pathbuf tp;
|
||||||
|
|
||||||
/* Massage the specified control messages. We need to serialize any
|
/* Massage the specified control messages. */
|
||||||
SCM_RIGHTS message and, if necessary, append an SCM_CREDENTIALS
|
|
||||||
message. */
|
|
||||||
|
|
||||||
msgh.msg_control = tp.w_get ();
|
msgh.msg_control = tp.w_get ();
|
||||||
msgh.msg_controllen = 2 * NT_MAX_PATH;
|
msgh.msg_controllen = MAX_AF_PKT_LEN - packet->pckt_len;
|
||||||
memset (msgh.msg_control, 0, msgh.msg_controllen);
|
memset (msgh.msg_control, 0, msgh.msg_controllen);
|
||||||
|
|
||||||
/* Copy from msg to msgh. */
|
/* Copy from msg to msgh. */
|
||||||
@ -2569,15 +2557,20 @@ fhandler_socket_unix::create_cmsg_data (af_unix_pkt_hdr_t *packet,
|
|||||||
for (struct cmsghdr *q = CMSG_FIRSTHDR (msg); q != NULL;
|
for (struct cmsghdr *q = CMSG_FIRSTHDR (msg); q != NULL;
|
||||||
q = CMSG_NXTHDR (msg, q))
|
q = CMSG_NXTHDR (msg, q))
|
||||||
{
|
{
|
||||||
struct cmsghdr *p1; /* Lags behind p. */
|
|
||||||
struct ucred *cred = NULL;
|
struct ucred *cred = NULL;
|
||||||
bool admin = false;
|
bool admin = false;
|
||||||
|
|
||||||
switch (q->cmsg_type)
|
switch (q->cmsg_type)
|
||||||
{
|
{
|
||||||
case SCM_CREDENTIALS:
|
case SCM_CREDENTIALS:
|
||||||
|
if (saw_scm_cred)
|
||||||
|
{
|
||||||
|
set_errno (EINVAL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
saw_scm_cred = true;
|
saw_scm_cred = true;
|
||||||
if (q->cmsg_len != CMSG_LEN (sizeof (struct ucred)))
|
if (q->cmsg_len != CMSG_LEN (sizeof (struct ucred))
|
||||||
|
|| q->cmsg_level != SOL_SOCKET)
|
||||||
{
|
{
|
||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
return false;
|
return false;
|
||||||
@ -2617,31 +2610,34 @@ fhandler_socket_unix::create_cmsg_data (af_unix_pkt_hdr_t *packet,
|
|||||||
set_errno (EPERM);
|
set_errno (EPERM);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy (p, q, q->cmsg_len);
|
|
||||||
break;
|
break;
|
||||||
case SCM_RIGHTS:
|
case SCM_RIGHTS:
|
||||||
/* Serialize the fds. For now, just send the list of fds. */
|
if (saw_scm_rights)
|
||||||
memcpy (p, q, q->cmsg_len);
|
{
|
||||||
|
set_errno (EINVAL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
saw_scm_rights = true;
|
||||||
|
/* FIXME: Serialize the fds. */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
p1 = p;
|
if (!p || len + CMSG_ALIGN (q->cmsg_len) > (size_t) msgh.msg_controllen)
|
||||||
p = CMSG_NXTHDR (&msgh, p);
|
|
||||||
if (p)
|
|
||||||
len += (PBYTE) p - (PBYTE) p1;
|
|
||||||
if (!p || packet->pckt_len + len > MAX_AF_PKT_LEN)
|
|
||||||
{
|
{
|
||||||
set_errno (EMSGSIZE);
|
set_errno (EMSGSIZE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
memcpy (p, q, q->cmsg_len);
|
||||||
|
len += CMSG_ALIGN (q->cmsg_len);
|
||||||
|
p = CMSG_NXTHDR (&msgh, p);
|
||||||
}
|
}
|
||||||
if (!saw_scm_cred)
|
if (!saw_scm_cred)
|
||||||
{
|
{
|
||||||
/* Append a credentials block. */
|
/* Append a credentials block. */
|
||||||
if (packet->pckt_len + len + CMSG_SPACE (sizeof (struct ucred))
|
if (!p || len + CMSG_SPACE (sizeof (struct ucred))
|
||||||
> MAX_AF_PKT_LEN)
|
> (size_t) msgh.msg_controllen)
|
||||||
{
|
{
|
||||||
set_errno (EMSGSIZE);
|
set_errno (EMSGSIZE);
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user