xfrm: add extack to xfrm_alloc_userspi

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-11-24 15:43:43 +01:00
committed by Steffen Klassert
parent bd12240337
commit c2dad11e04
4 changed files with 26 additions and 12 deletions

View File

@@ -1681,8 +1681,9 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net,
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid); int xfrm_policy_flush(struct net *net, u8 type, bool task_valid);
void xfrm_policy_hash_rebuild(struct net *net); void xfrm_policy_hash_rebuild(struct net *net);
u32 xfrm_get_acqseq(void); u32 xfrm_get_acqseq(void);
int verify_spi_info(u8 proto, u32 min, u32 max); int verify_spi_info(u8 proto, u32 min, u32 max, struct netlink_ext_ack *extack);
int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi,
struct netlink_ext_ack *extack);
struct xfrm_state *xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, struct xfrm_state *xfrm_find_acq(struct net *net, const struct xfrm_mark *mark,
u8 mode, u32 reqid, u32 if_id, u8 proto, u8 mode, u32 reqid, u32 if_id, u8 proto,
const xfrm_address_t *daddr, const xfrm_address_t *daddr,

View File

@@ -1377,13 +1377,13 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
max_spi = range->sadb_spirange_max; max_spi = range->sadb_spirange_max;
} }
err = verify_spi_info(x->id.proto, min_spi, max_spi); err = verify_spi_info(x->id.proto, min_spi, max_spi, NULL);
if (err) { if (err) {
xfrm_state_put(x); xfrm_state_put(x);
return err; return err;
} }
err = xfrm_alloc_spi(x, min_spi, max_spi); err = xfrm_alloc_spi(x, min_spi, max_spi, NULL);
resp_skb = err ? ERR_PTR(err) : pfkey_xfrm_state2msg(x); resp_skb = err ? ERR_PTR(err) : pfkey_xfrm_state2msg(x);
if (IS_ERR(resp_skb)) { if (IS_ERR(resp_skb)) {

View File

@@ -2017,7 +2017,7 @@ u32 xfrm_get_acqseq(void)
} }
EXPORT_SYMBOL(xfrm_get_acqseq); EXPORT_SYMBOL(xfrm_get_acqseq);
int verify_spi_info(u8 proto, u32 min, u32 max) int verify_spi_info(u8 proto, u32 min, u32 max, struct netlink_ext_ack *extack)
{ {
switch (proto) { switch (proto) {
case IPPROTO_AH: case IPPROTO_AH:
@@ -2026,22 +2026,28 @@ int verify_spi_info(u8 proto, u32 min, u32 max)
case IPPROTO_COMP: case IPPROTO_COMP:
/* IPCOMP spi is 16-bits. */ /* IPCOMP spi is 16-bits. */
if (max >= 0x10000) if (max >= 0x10000) {
NL_SET_ERR_MSG(extack, "IPCOMP SPI must be <= 65535");
return -EINVAL; return -EINVAL;
}
break; break;
default: default:
NL_SET_ERR_MSG(extack, "Invalid protocol, must be one of AH, ESP, IPCOMP");
return -EINVAL; return -EINVAL;
} }
if (min > max) if (min > max) {
NL_SET_ERR_MSG(extack, "Invalid SPI range: min > max");
return -EINVAL; return -EINVAL;
}
return 0; return 0;
} }
EXPORT_SYMBOL(verify_spi_info); EXPORT_SYMBOL(verify_spi_info);
int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high,
struct netlink_ext_ack *extack)
{ {
struct net *net = xs_net(x); struct net *net = xs_net(x);
unsigned int h; unsigned int h;
@@ -2053,8 +2059,10 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
u32 mark = x->mark.v & x->mark.m; u32 mark = x->mark.v & x->mark.m;
spin_lock_bh(&x->lock); spin_lock_bh(&x->lock);
if (x->km.state == XFRM_STATE_DEAD) if (x->km.state == XFRM_STATE_DEAD) {
NL_SET_ERR_MSG(extack, "Target ACQUIRE is in DEAD state");
goto unlock; goto unlock;
}
err = 0; err = 0;
if (x->id.spi) if (x->id.spi)
@@ -2065,6 +2073,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
if (minspi == maxspi) { if (minspi == maxspi) {
x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family); x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family);
if (x0) { if (x0) {
NL_SET_ERR_MSG(extack, "Requested SPI is already in use");
xfrm_state_put(x0); xfrm_state_put(x0);
goto unlock; goto unlock;
} }
@@ -2089,6 +2098,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
spin_unlock_bh(&net->xfrm.xfrm_state_lock); spin_unlock_bh(&net->xfrm.xfrm_state_lock);
err = 0; err = 0;
} else {
NL_SET_ERR_MSG(extack, "No SPI available in the requested range");
} }
unlock: unlock:

View File

@@ -1523,7 +1523,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
u32 if_id = 0; u32 if_id = 0;
p = nlmsg_data(nlh); p = nlmsg_data(nlh);
err = verify_spi_info(p->info.id.proto, p->min, p->max); err = verify_spi_info(p->info.id.proto, p->min, p->max, extack);
if (err) if (err)
goto out_noput; goto out_noput;
@@ -1551,10 +1551,12 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
&p->info.saddr, 1, &p->info.saddr, 1,
family); family);
err = -ENOENT; err = -ENOENT;
if (!x) if (!x) {
NL_SET_ERR_MSG(extack, "Target ACQUIRE not found");
goto out_noput; goto out_noput;
}
err = xfrm_alloc_spi(x, p->min, p->max); err = xfrm_alloc_spi(x, p->min, p->max, extack);
if (err) if (err)
goto out; goto out;