xfrm: add extack to validate_tmpl

Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
Sabrina Dubroca 2022-08-30 16:23:11 +02:00 committed by Steffen Klassert
parent fb7deaba40
commit d37bed89f0

View File

@ -1616,13 +1616,16 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
} }
} }
static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
struct netlink_ext_ack *extack)
{ {
u16 prev_family; u16 prev_family;
int i; int i;
if (nr > XFRM_MAX_DEPTH) if (nr > XFRM_MAX_DEPTH) {
NL_SET_ERR_MSG(extack, "Template count must be <= XFRM_MAX_DEPTH (" __stringify(XFRM_MAX_DEPTH) ")");
return -EINVAL; return -EINVAL;
}
prev_family = family; prev_family = family;
@ -1642,12 +1645,16 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
case XFRM_MODE_BEET: case XFRM_MODE_BEET:
break; break;
default: default:
if (ut[i].family != prev_family) if (ut[i].family != prev_family) {
NL_SET_ERR_MSG(extack, "Mode in template doesn't support a family change");
return -EINVAL; return -EINVAL;
}
break; break;
} }
if (ut[i].mode >= XFRM_MODE_MAX) if (ut[i].mode >= XFRM_MODE_MAX) {
NL_SET_ERR_MSG(extack, "Mode in template must be < XFRM_MODE_MAX (" __stringify(XFRM_MODE_MAX) ")");
return -EINVAL; return -EINVAL;
}
prev_family = ut[i].family; prev_family = ut[i].family;
@ -1659,17 +1666,21 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
break; break;
#endif #endif
default: default:
NL_SET_ERR_MSG(extack, "Invalid family in template");
return -EINVAL; return -EINVAL;
} }
if (!xfrm_id_proto_valid(ut[i].id.proto)) if (!xfrm_id_proto_valid(ut[i].id.proto)) {
NL_SET_ERR_MSG(extack, "Invalid XFRM protocol in template");
return -EINVAL; return -EINVAL;
}
} }
return 0; return 0;
} }
static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs) static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
struct netlink_ext_ack *extack)
{ {
struct nlattr *rt = attrs[XFRMA_TMPL]; struct nlattr *rt = attrs[XFRMA_TMPL];
@ -1680,7 +1691,7 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs)
int nr = nla_len(rt) / sizeof(*utmpl); int nr = nla_len(rt) / sizeof(*utmpl);
int err; int err;
err = validate_tmpl(nr, utmpl, pol->family); err = validate_tmpl(nr, utmpl, pol->family, extack);
if (err) if (err)
return err; return err;
@ -1757,7 +1768,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net,
if (err) if (err)
goto error; goto error;
if (!(err = copy_from_user_tmpl(xp, attrs))) if (!(err = copy_from_user_tmpl(xp, attrs, extack)))
err = copy_from_user_sec_ctx(xp, attrs); err = copy_from_user_sec_ctx(xp, attrs);
if (err) if (err)
goto error; goto error;
@ -3306,7 +3317,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
return NULL; return NULL;
nr = ((len - sizeof(*p)) / sizeof(*ut)); nr = ((len - sizeof(*p)) / sizeof(*ut));
if (validate_tmpl(nr, ut, p->sel.family)) if (validate_tmpl(nr, ut, p->sel.family, NULL))
return NULL; return NULL;
if (p->dir > XFRM_POLICY_OUT) if (p->dir > XFRM_POLICY_OUT)