xfrm: add extack support to verify_newsa_info
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
Родитель
50c448bbc1
Коммит
6999aae17a
|
@ -149,7 +149,8 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
|
|||
}
|
||||
|
||||
static int verify_newsa_info(struct xfrm_usersa_info *p,
|
||||
struct nlattr **attrs)
|
||||
struct nlattr **attrs,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -163,10 +164,12 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
|||
break;
|
||||
#else
|
||||
err = -EAFNOSUPPORT;
|
||||
NL_SET_ERR_MSG(extack, "IPv6 support disabled");
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
default:
|
||||
NL_SET_ERR_MSG(extack, "Invalid address family");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -175,65 +178,98 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
|||
break;
|
||||
|
||||
case AF_INET:
|
||||
if (p->sel.prefixlen_d > 32 || p->sel.prefixlen_s > 32)
|
||||
if (p->sel.prefixlen_d > 32 || p->sel.prefixlen_s > 32) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid prefix length in selector (must be <= 32 for IPv4)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (p->sel.prefixlen_d > 128 || p->sel.prefixlen_s > 128)
|
||||
if (p->sel.prefixlen_d > 128 || p->sel.prefixlen_s > 128) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid prefix length in selector (must be <= 128 for IPv6)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
break;
|
||||
#else
|
||||
NL_SET_ERR_MSG(extack, "IPv6 support disabled");
|
||||
err = -EAFNOSUPPORT;
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
default:
|
||||
NL_SET_ERR_MSG(extack, "Invalid address family in selector");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = -EINVAL;
|
||||
switch (p->id.proto) {
|
||||
case IPPROTO_AH:
|
||||
if ((!attrs[XFRMA_ALG_AUTH] &&
|
||||
!attrs[XFRMA_ALG_AUTH_TRUNC]) ||
|
||||
attrs[XFRMA_ALG_AEAD] ||
|
||||
if (!attrs[XFRMA_ALG_AUTH] &&
|
||||
!attrs[XFRMA_ALG_AUTH_TRUNC]) {
|
||||
NL_SET_ERR_MSG(extack, "Missing required attribute for AH: AUTH_TRUNC or AUTH");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (attrs[XFRMA_ALG_AEAD] ||
|
||||
attrs[XFRMA_ALG_CRYPT] ||
|
||||
attrs[XFRMA_ALG_COMP] ||
|
||||
attrs[XFRMA_TFCPAD])
|
||||
attrs[XFRMA_TFCPAD]) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid attributes for AH: AEAD, CRYPT, COMP, TFCPAD");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_ESP:
|
||||
if (attrs[XFRMA_ALG_COMP])
|
||||
if (attrs[XFRMA_ALG_COMP]) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid attribute for ESP: COMP");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!attrs[XFRMA_ALG_AUTH] &&
|
||||
!attrs[XFRMA_ALG_AUTH_TRUNC] &&
|
||||
!attrs[XFRMA_ALG_CRYPT] &&
|
||||
!attrs[XFRMA_ALG_AEAD])
|
||||
!attrs[XFRMA_ALG_AEAD]) {
|
||||
NL_SET_ERR_MSG(extack, "Missing required attribute for ESP: at least one of AUTH, AUTH_TRUNC, CRYPT, AEAD");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((attrs[XFRMA_ALG_AUTH] ||
|
||||
attrs[XFRMA_ALG_AUTH_TRUNC] ||
|
||||
attrs[XFRMA_ALG_CRYPT]) &&
|
||||
attrs[XFRMA_ALG_AEAD])
|
||||
attrs[XFRMA_ALG_AEAD]) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid attribute combination for ESP: AEAD can't be used with AUTH, AUTH_TRUNC, CRYPT");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (attrs[XFRMA_TFCPAD] &&
|
||||
p->mode != XFRM_MODE_TUNNEL)
|
||||
p->mode != XFRM_MODE_TUNNEL) {
|
||||
NL_SET_ERR_MSG(extack, "TFC padding can only be used in tunnel mode");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_COMP:
|
||||
if (!attrs[XFRMA_ALG_COMP] ||
|
||||
attrs[XFRMA_ALG_AEAD] ||
|
||||
if (!attrs[XFRMA_ALG_COMP]) {
|
||||
NL_SET_ERR_MSG(extack, "Missing required attribute for COMP: COMP");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (attrs[XFRMA_ALG_AEAD] ||
|
||||
attrs[XFRMA_ALG_AUTH] ||
|
||||
attrs[XFRMA_ALG_AUTH_TRUNC] ||
|
||||
attrs[XFRMA_ALG_CRYPT] ||
|
||||
attrs[XFRMA_TFCPAD] ||
|
||||
(ntohl(p->id.spi) >= 0x10000))
|
||||
attrs[XFRMA_TFCPAD]) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid attributes for COMP: AEAD, AUTH, AUTH_TRUNC, CRYPT, TFCPAD");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ntohl(p->id.spi) >= 0x10000) {
|
||||
NL_SET_ERR_MSG(extack, "SPI is too large for COMP (must be < 0x10000)");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
@ -246,13 +282,20 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
|||
attrs[XFRMA_ALG_CRYPT] ||
|
||||
attrs[XFRMA_ENCAP] ||
|
||||
attrs[XFRMA_SEC_CTX] ||
|
||||
attrs[XFRMA_TFCPAD] ||
|
||||
!attrs[XFRMA_COADDR])
|
||||
attrs[XFRMA_TFCPAD]) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid attributes for DSTOPTS/ROUTING");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!attrs[XFRMA_COADDR]) {
|
||||
NL_SET_ERR_MSG(extack, "Missing required COADDR attribute for DSTOPTS/ROUTING");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
NL_SET_ERR_MSG(extack, "Unsupported protocol");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -266,7 +309,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
|||
goto out;
|
||||
if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP)))
|
||||
goto out;
|
||||
if ((err = verify_sec_ctx_len(attrs, NULL)))
|
||||
if ((err = verify_sec_ctx_len(attrs, extack)))
|
||||
goto out;
|
||||
if ((err = verify_replay(p, attrs)))
|
||||
goto out;
|
||||
|
@ -280,14 +323,19 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
|||
break;
|
||||
|
||||
default:
|
||||
NL_SET_ERR_MSG(extack, "Unsupported mode");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
if (attrs[XFRMA_MTIMER_THRESH])
|
||||
if (!attrs[XFRMA_ENCAP])
|
||||
if (attrs[XFRMA_MTIMER_THRESH]) {
|
||||
if (!attrs[XFRMA_ENCAP]) {
|
||||
NL_SET_ERR_MSG(extack, "MTIMER_THRESH attribute can only be set on ENCAP states");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
|
@ -688,7 +736,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
int err;
|
||||
struct km_event c;
|
||||
|
||||
err = verify_newsa_info(p, attrs);
|
||||
err = verify_newsa_info(p, attrs, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче