mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next
Steffen Klassert says: ==================== ipsec-next 2022-11-26 1) Remove redundant variable in esp6. From Colin Ian King. 2) Update x->lastused for every packet. It was used only for outgoing mobile IPv6 packets, but showed to be usefull to check if the a SA is still in use in general. From Antony Antony. 3) Remove unused variable in xfrm_byidx_resize. From Leon Romanovsky. 4) Finalize extack support for xfrm. From Sabrina Dubroca. * 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next: xfrm: add extack to xfrm_set_spdinfo xfrm: add extack to xfrm_alloc_userspi xfrm: add extack to xfrm_do_migrate xfrm: add extack to xfrm_new_ae and xfrm_replay_verify_len xfrm: add extack to xfrm_del_sa xfrm: add extack to xfrm_add_sa_expire xfrm: a few coding style clean ups xfrm: Remove not-used total variable xfrm: update x->lastused for every packet esp6: remove redundant variable err ==================== Link: https://lore.kernel.org/r/20221126110303.1859238-1-steffen.klassert@secunet.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
5cb0c51fe3
|
@ -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);
|
||||
void xfrm_policy_hash_rebuild(struct net *net);
|
||||
u32 xfrm_get_acqseq(void);
|
||||
int verify_spi_info(u8 proto, u32 min, u32 max);
|
||||
int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
|
||||
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,
|
||||
struct netlink_ext_ack *extack);
|
||||
struct xfrm_state *xfrm_find_acq(struct net *net, const struct xfrm_mark *mark,
|
||||
u8 mode, u32 reqid, u32 if_id, u8 proto,
|
||||
const xfrm_address_t *daddr,
|
||||
|
@ -1703,7 +1704,8 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
|
|||
int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
|
||||
struct xfrm_migrate *m, int num_bundles,
|
||||
struct xfrm_kmaddress *k, struct net *net,
|
||||
struct xfrm_encap_tmpl *encap, u32 if_id);
|
||||
struct xfrm_encap_tmpl *encap, u32 if_id,
|
||||
struct netlink_ext_ack *extack);
|
||||
#endif
|
||||
|
||||
int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
|
||||
|
|
|
@ -56,12 +56,11 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head,
|
|||
__be32 seq;
|
||||
__be32 spi;
|
||||
int nhoff;
|
||||
int err;
|
||||
|
||||
if (!pskb_pull(skb, offset))
|
||||
return NULL;
|
||||
|
||||
if ((err = xfrm_parse_spi(skb, IPPROTO_ESP, &spi, &seq)) != 0)
|
||||
if (xfrm_parse_spi(skb, IPPROTO_ESP, &spi, &seq) != 0)
|
||||
goto out;
|
||||
|
||||
xo = xfrm_offload(skb);
|
||||
|
|
|
@ -1377,13 +1377,13 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
|
|||
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) {
|
||||
xfrm_state_put(x);
|
||||
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);
|
||||
|
||||
if (IS_ERR(resp_skb)) {
|
||||
|
@ -2626,7 +2626,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
|
||||
kma ? &k : NULL, net, NULL, 0);
|
||||
kma ? &k : NULL, net, NULL, 0, NULL);
|
||||
|
||||
out:
|
||||
return err;
|
||||
|
|
|
@ -671,6 +671,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
|||
|
||||
x->curlft.bytes += skb->len;
|
||||
x->curlft.packets++;
|
||||
x->lastused = ktime_get_real_seconds();
|
||||
|
||||
spin_unlock(&x->lock);
|
||||
|
||||
|
|
|
@ -209,8 +209,6 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
|
|||
__skb_pull(skb, hdr_len);
|
||||
memmove(ipv6_hdr(skb), iph, hdr_len);
|
||||
|
||||
x->lastused = ktime_get_real_seconds();
|
||||
|
||||
return 0;
|
||||
#else
|
||||
WARN_ON_ONCE(1);
|
||||
|
@ -534,6 +532,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
|
|||
|
||||
x->curlft.bytes += skb->len;
|
||||
x->curlft.packets++;
|
||||
x->lastused = ktime_get_real_seconds();
|
||||
|
||||
spin_unlock_bh(&x->lock);
|
||||
|
||||
|
|
|
@ -605,7 +605,7 @@ static void xfrm_bydst_resize(struct net *net, int dir)
|
|||
xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head));
|
||||
}
|
||||
|
||||
static void xfrm_byidx_resize(struct net *net, int total)
|
||||
static void xfrm_byidx_resize(struct net *net)
|
||||
{
|
||||
unsigned int hmask = net->xfrm.policy_idx_hmask;
|
||||
unsigned int nhashmask = xfrm_new_hash_mask(hmask);
|
||||
|
@ -683,7 +683,7 @@ static void xfrm_hash_resize(struct work_struct *work)
|
|||
xfrm_bydst_resize(net, dir);
|
||||
}
|
||||
if (xfrm_byidx_should_resize(net, total))
|
||||
xfrm_byidx_resize(net, total);
|
||||
xfrm_byidx_resize(net);
|
||||
|
||||
mutex_unlock(&hash_resize_mutex);
|
||||
}
|
||||
|
@ -4333,7 +4333,8 @@ static int migrate_tmpl_match(const struct xfrm_migrate *m, const struct xfrm_tm
|
|||
|
||||
/* update endpoint address(es) of template(s) */
|
||||
static int xfrm_policy_migrate(struct xfrm_policy *pol,
|
||||
struct xfrm_migrate *m, int num_migrate)
|
||||
struct xfrm_migrate *m, int num_migrate,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct xfrm_migrate *mp;
|
||||
int i, j, n = 0;
|
||||
|
@ -4341,6 +4342,7 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol,
|
|||
write_lock_bh(&pol->lock);
|
||||
if (unlikely(pol->walk.dead)) {
|
||||
/* target policy has been deleted */
|
||||
NL_SET_ERR_MSG(extack, "Target policy not found");
|
||||
write_unlock_bh(&pol->lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -4372,17 +4374,22 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
|
||||
static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (num_migrate < 1 || num_migrate > XFRM_MAX_DEPTH)
|
||||
if (num_migrate < 1 || num_migrate > XFRM_MAX_DEPTH) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid number of SAs to migrate, must be 0 < num <= XFRM_MAX_DEPTH (6)");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_migrate; i++) {
|
||||
if (xfrm_addr_any(&m[i].new_daddr, m[i].new_family) ||
|
||||
xfrm_addr_any(&m[i].new_saddr, m[i].new_family))
|
||||
xfrm_addr_any(&m[i].new_saddr, m[i].new_family)) {
|
||||
NL_SET_ERR_MSG(extack, "Addresses in the MIGRATE attribute's list cannot be null");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check if there is any duplicated entry */
|
||||
for (j = i + 1; j < num_migrate; j++) {
|
||||
|
@ -4393,8 +4400,10 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
|
|||
m[i].proto == m[j].proto &&
|
||||
m[i].mode == m[j].mode &&
|
||||
m[i].reqid == m[j].reqid &&
|
||||
m[i].old_family == m[j].old_family)
|
||||
m[i].old_family == m[j].old_family) {
|
||||
NL_SET_ERR_MSG(extack, "Entries in the MIGRATE attribute's list must be unique");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4404,7 +4413,8 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
|
|||
int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
|
||||
struct xfrm_migrate *m, int num_migrate,
|
||||
struct xfrm_kmaddress *k, struct net *net,
|
||||
struct xfrm_encap_tmpl *encap, u32 if_id)
|
||||
struct xfrm_encap_tmpl *encap, u32 if_id,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int i, err, nx_cur = 0, nx_new = 0;
|
||||
struct xfrm_policy *pol = NULL;
|
||||
|
@ -4414,16 +4424,20 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
|
|||
struct xfrm_migrate *mp;
|
||||
|
||||
/* Stage 0 - sanity checks */
|
||||
if ((err = xfrm_migrate_check(m, num_migrate)) < 0)
|
||||
err = xfrm_migrate_check(m, num_migrate, extack);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (dir >= XFRM_POLICY_MAX) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid policy direction");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Stage 1 - find policy */
|
||||
if ((pol = xfrm_migrate_policy_find(sel, dir, type, net, if_id)) == NULL) {
|
||||
pol = xfrm_migrate_policy_find(sel, dir, type, net, if_id);
|
||||
if (!pol) {
|
||||
NL_SET_ERR_MSG(extack, "Target policy not found");
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
@ -4445,7 +4459,8 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
|
|||
}
|
||||
|
||||
/* Stage 3 - update policy */
|
||||
if ((err = xfrm_policy_migrate(pol, m, num_migrate)) < 0)
|
||||
err = xfrm_policy_migrate(pol, m, num_migrate, extack);
|
||||
if (err < 0)
|
||||
goto restore_state;
|
||||
|
||||
/* Stage 4 - delete old state(s) */
|
||||
|
|
|
@ -2017,7 +2017,7 @@ u32 xfrm_get_acqseq(void)
|
|||
}
|
||||
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) {
|
||||
case IPPROTO_AH:
|
||||
|
@ -2026,22 +2026,28 @@ int verify_spi_info(u8 proto, u32 min, u32 max)
|
|||
|
||||
case IPPROTO_COMP:
|
||||
/* IPCOMP spi is 16-bits. */
|
||||
if (max >= 0x10000)
|
||||
if (max >= 0x10000) {
|
||||
NL_SET_ERR_MSG(extack, "IPCOMP SPI must be <= 65535");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
NL_SET_ERR_MSG(extack, "Invalid protocol, must be one of AH, ESP, IPCOMP");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (min > max)
|
||||
if (min > max) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid SPI range: min > max");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
if (x->id.spi)
|
||||
|
@ -2065,6 +2073,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
|
|||
if (minspi == maxspi) {
|
||||
x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family);
|
||||
if (x0) {
|
||||
NL_SET_ERR_MSG(extack, "Requested SPI is already in use");
|
||||
xfrm_state_put(x0);
|
||||
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);
|
||||
|
||||
err = 0;
|
||||
} else {
|
||||
NL_SET_ERR_MSG(extack, "No SPI available in the requested range");
|
||||
}
|
||||
|
||||
unlock:
|
||||
|
|
|
@ -515,7 +515,8 @@ static int attach_aead(struct xfrm_state *x, struct nlattr *rta,
|
|||
}
|
||||
|
||||
static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn,
|
||||
struct nlattr *rp)
|
||||
struct nlattr *rp,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct xfrm_replay_state_esn *up;
|
||||
unsigned int ulen;
|
||||
|
@ -528,13 +529,25 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es
|
|||
|
||||
/* Check the overall length and the internal bitmap length to avoid
|
||||
* potential overflow. */
|
||||
if (nla_len(rp) < (int)ulen ||
|
||||
xfrm_replay_state_esn_len(replay_esn) != ulen ||
|
||||
replay_esn->bmp_len != up->bmp_len)
|
||||
if (nla_len(rp) < (int)ulen) {
|
||||
NL_SET_ERR_MSG(extack, "ESN attribute is too short");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (up->replay_window > up->bmp_len * sizeof(__u32) * 8)
|
||||
if (xfrm_replay_state_esn_len(replay_esn) != ulen) {
|
||||
NL_SET_ERR_MSG(extack, "New ESN size doesn't match the existing SA's ESN size");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (replay_esn->bmp_len != up->bmp_len) {
|
||||
NL_SET_ERR_MSG(extack, "New ESN bitmap size doesn't match the existing SA's ESN bitmap");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (up->replay_window > up->bmp_len * sizeof(__u32) * 8) {
|
||||
NL_SET_ERR_MSG(extack, "ESN replay window is longer than the bitmap");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -862,12 +875,12 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
goto out;
|
||||
|
||||
if (xfrm_state_kern(x)) {
|
||||
NL_SET_ERR_MSG(extack, "SA is in use by tunnels");
|
||||
err = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = xfrm_state_delete(x);
|
||||
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -1354,20 +1367,28 @@ static int xfrm_set_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (attrs[XFRMA_SPD_IPV4_HTHRESH]) {
|
||||
struct nlattr *rta = attrs[XFRMA_SPD_IPV4_HTHRESH];
|
||||
|
||||
if (nla_len(rta) < sizeof(*thresh4))
|
||||
if (nla_len(rta) < sizeof(*thresh4)) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid SPD_IPV4_HTHRESH attribute length");
|
||||
return -EINVAL;
|
||||
}
|
||||
thresh4 = nla_data(rta);
|
||||
if (thresh4->lbits > 32 || thresh4->rbits > 32)
|
||||
if (thresh4->lbits > 32 || thresh4->rbits > 32) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid hash threshold (must be <= 32 for IPv4)");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (attrs[XFRMA_SPD_IPV6_HTHRESH]) {
|
||||
struct nlattr *rta = attrs[XFRMA_SPD_IPV6_HTHRESH];
|
||||
|
||||
if (nla_len(rta) < sizeof(*thresh6))
|
||||
if (nla_len(rta) < sizeof(*thresh6)) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid SPD_IPV6_HTHRESH attribute length");
|
||||
return -EINVAL;
|
||||
}
|
||||
thresh6 = nla_data(rta);
|
||||
if (thresh6->lbits > 128 || thresh6->rbits > 128)
|
||||
if (thresh6->lbits > 128 || thresh6->rbits > 128) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid hash threshold (must be <= 128 for IPv6)");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (thresh4 || thresh6) {
|
||||
|
@ -1510,7 +1531,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
u32 if_id = 0;
|
||||
|
||||
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)
|
||||
goto out_noput;
|
||||
|
||||
|
@ -1538,10 +1559,12 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
&p->info.saddr, 1,
|
||||
family);
|
||||
err = -ENOENT;
|
||||
if (x == NULL)
|
||||
if (!x) {
|
||||
NL_SET_ERR_MSG(extack, "Target ACQUIRE not found");
|
||||
goto out_noput;
|
||||
}
|
||||
|
||||
err = xfrm_alloc_spi(x, p->min, p->max);
|
||||
err = xfrm_alloc_spi(x, p->min, p->max, extack);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -2433,12 +2456,16 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
|
||||
struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
|
||||
|
||||
if (!lt && !rp && !re && !et && !rt)
|
||||
if (!lt && !rp && !re && !et && !rt) {
|
||||
NL_SET_ERR_MSG(extack, "Missing required attribute for AE");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* pedantic mode - thou shalt sayeth replaceth */
|
||||
if (!(nlh->nlmsg_flags&NLM_F_REPLACE))
|
||||
if (!(nlh->nlmsg_flags & NLM_F_REPLACE)) {
|
||||
NL_SET_ERR_MSG(extack, "NLM_F_REPLACE flag is required");
|
||||
return err;
|
||||
}
|
||||
|
||||
mark = xfrm_mark_get(attrs, &m);
|
||||
|
||||
|
@ -2446,10 +2473,12 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (x == NULL)
|
||||
return -ESRCH;
|
||||
|
||||
if (x->km.state != XFRM_STATE_VALID)
|
||||
if (x->km.state != XFRM_STATE_VALID) {
|
||||
NL_SET_ERR_MSG(extack, "SA must be in VALID state");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = xfrm_replay_verify_len(x->replay_esn, re);
|
||||
err = xfrm_replay_verify_len(x->replay_esn, re, extack);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -2584,8 +2613,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
|
||||
spin_lock_bh(&x->lock);
|
||||
err = -EINVAL;
|
||||
if (x->km.state != XFRM_STATE_VALID)
|
||||
if (x->km.state != XFRM_STATE_VALID) {
|
||||
NL_SET_ERR_MSG(extack, "SA must be in VALID state");
|
||||
goto out;
|
||||
}
|
||||
|
||||
km_state_expired(x, ue->hard, nlh->nlmsg_pid);
|
||||
|
||||
if (ue->hard) {
|
||||
|
@ -2665,7 +2697,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
#ifdef CONFIG_XFRM_MIGRATE
|
||||
static int copy_from_user_migrate(struct xfrm_migrate *ma,
|
||||
struct xfrm_kmaddress *k,
|
||||
struct nlattr **attrs, int *num)
|
||||
struct nlattr **attrs, int *num,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nlattr *rt = attrs[XFRMA_MIGRATE];
|
||||
struct xfrm_user_migrate *um;
|
||||
|
@ -2684,8 +2717,10 @@ static int copy_from_user_migrate(struct xfrm_migrate *ma,
|
|||
um = nla_data(rt);
|
||||
num_migrate = nla_len(rt) / sizeof(*um);
|
||||
|
||||
if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH)
|
||||
if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid number of SAs to migrate, must be 0 < num <= XFRM_MAX_DEPTH (6)");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_migrate; i++, um++, ma++) {
|
||||
memcpy(&ma->old_daddr, &um->old_daddr, sizeof(ma->old_daddr));
|
||||
|
@ -2718,8 +2753,10 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
struct xfrm_encap_tmpl *encap = NULL;
|
||||
u32 if_id = 0;
|
||||
|
||||
if (attrs[XFRMA_MIGRATE] == NULL)
|
||||
if (!attrs[XFRMA_MIGRATE]) {
|
||||
NL_SET_ERR_MSG(extack, "Missing required MIGRATE attribute");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL;
|
||||
|
||||
|
@ -2727,7 +2764,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n);
|
||||
err = copy_from_user_migrate(m, kmp, attrs, &n, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -2744,7 +2781,8 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (attrs[XFRMA_IF_ID])
|
||||
if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
|
||||
|
||||
err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap, if_id);
|
||||
err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap,
|
||||
if_id, extack);
|
||||
|
||||
kfree(encap);
|
||||
|
||||
|
|
Loading…
Reference in a new issue