Make user supplied data checks a bit stricter.
key_msg2sp() is used for parsing data from setsockopt(IP[V6]_IPSEC_POLICY) call. This socket option is usually used to configure IPsec bypass for socket. Only privileged user can set this socket option. The message syntax is described here http://www.kame.net/newsletter/20021210/ and our libipsec is usually used to create the correct request. Add additional checks: * that sadb_x_ipsecrequest_len is not out of bounds of user supplied buffer * that src/dst's sa_len is the same * that 2*sa_len is not out of bounds of user supplied buffer * that 2*sa_len fits into bounds of sadb_x_ipsecrequest Reported by: Ilja van Sprundel MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D11796
This commit is contained in:
parent
16398a1141
commit
e54647920b
@ -1403,7 +1403,8 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
|
||||
|
||||
while (tlen > 0) {
|
||||
/* length check */
|
||||
if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
|
||||
if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr) ||
|
||||
xisr->sadb_x_ipsecrequest_len > tlen) {
|
||||
ipseclog((LOG_DEBUG, "%s: invalid ipsecrequest "
|
||||
"length.\n", __func__));
|
||||
key_freesp(&newsp);
|
||||
@ -1517,10 +1518,12 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
|
||||
if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
|
||||
struct sockaddr *paddr;
|
||||
|
||||
len = tlen - sizeof(*xisr);
|
||||
paddr = (struct sockaddr *)(xisr + 1);
|
||||
/* validity check */
|
||||
if (paddr->sa_len
|
||||
> sizeof(isr->saidx.src)) {
|
||||
if (len < sizeof(struct sockaddr) ||
|
||||
len < 2 * paddr->sa_len ||
|
||||
paddr->sa_len > sizeof(isr->saidx.src)) {
|
||||
ipseclog((LOG_DEBUG, "%s: invalid "
|
||||
"request address length.\n",
|
||||
__func__));
|
||||
@ -1528,13 +1531,26 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
|
||||
*error = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Request length should be enough to keep
|
||||
* source and destination addresses.
|
||||
*/
|
||||
if (xisr->sadb_x_ipsecrequest_len <
|
||||
sizeof(*xisr) + 2 * paddr->sa_len) {
|
||||
ipseclog((LOG_DEBUG, "%s: invalid "
|
||||
"ipsecrequest length.\n",
|
||||
__func__));
|
||||
key_freesp(&newsp);
|
||||
*error = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
bcopy(paddr, &isr->saidx.src, paddr->sa_len);
|
||||
paddr = (struct sockaddr *)((caddr_t)paddr +
|
||||
paddr->sa_len);
|
||||
|
||||
/* validity check */
|
||||
if (paddr->sa_len
|
||||
> sizeof(isr->saidx.dst)) {
|
||||
if (paddr->sa_len !=
|
||||
isr->saidx.src.sa.sa_len) {
|
||||
ipseclog((LOG_DEBUG, "%s: invalid "
|
||||
"request address length.\n",
|
||||
__func__));
|
||||
|
Loading…
Reference in New Issue
Block a user