| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* xfrm_user.c: User interface to configure xfrm engine. |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2002 David S. Miller (davem@redhat.com) |
|---|
| .. | .. |
|---|
| 620 | 621 | |
|---|
| 621 | 622 | xfrm_smark_init(attrs, &x->props.smark); |
|---|
| 622 | 623 | |
|---|
| 623 | | - if (attrs[XFRMA_IF_ID]) { |
|---|
| 624 | + if (attrs[XFRMA_IF_ID]) |
|---|
| 624 | 625 | x->if_id = nla_get_u32(attrs[XFRMA_IF_ID]); |
|---|
| 625 | | - if (!x->if_id) { |
|---|
| 626 | | - err = -EINVAL; |
|---|
| 627 | | - goto error; |
|---|
| 628 | | - } |
|---|
| 629 | | - } |
|---|
| 630 | 626 | |
|---|
| 631 | 627 | err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]); |
|---|
| 632 | 628 | if (err) |
|---|
| .. | .. |
|---|
| 1043 | 1039 | u8 proto = 0; |
|---|
| 1044 | 1040 | int err; |
|---|
| 1045 | 1041 | |
|---|
| 1046 | | - err = nlmsg_parse(cb->nlh, 0, attrs, XFRMA_MAX, xfrma_policy, |
|---|
| 1047 | | - NULL); |
|---|
| 1042 | + err = nlmsg_parse_deprecated(cb->nlh, 0, attrs, XFRMA_MAX, |
|---|
| 1043 | + xfrma_policy, cb->extack); |
|---|
| 1048 | 1044 | if (err < 0) |
|---|
| 1049 | 1045 | return err; |
|---|
| 1050 | 1046 | |
|---|
| .. | .. |
|---|
| 1357 | 1353 | |
|---|
| 1358 | 1354 | mark = xfrm_mark_get(attrs, &m); |
|---|
| 1359 | 1355 | |
|---|
| 1360 | | - if (attrs[XFRMA_IF_ID]) { |
|---|
| 1356 | + if (attrs[XFRMA_IF_ID]) |
|---|
| 1361 | 1357 | if_id = nla_get_u32(attrs[XFRMA_IF_ID]); |
|---|
| 1362 | | - if (!if_id) { |
|---|
| 1363 | | - err = -EINVAL; |
|---|
| 1364 | | - goto out_noput; |
|---|
| 1365 | | - } |
|---|
| 1366 | | - } |
|---|
| 1367 | 1358 | |
|---|
| 1368 | 1359 | if (p->info.seq) { |
|---|
| 1369 | 1360 | x = xfrm_find_acq_byseq(net, mark, p->info.seq); |
|---|
| .. | .. |
|---|
| 1676 | 1667 | |
|---|
| 1677 | 1668 | xfrm_mark_get(attrs, &xp->mark); |
|---|
| 1678 | 1669 | |
|---|
| 1679 | | - if (attrs[XFRMA_IF_ID]) { |
|---|
| 1670 | + if (attrs[XFRMA_IF_ID]) |
|---|
| 1680 | 1671 | xp->if_id = nla_get_u32(attrs[XFRMA_IF_ID]); |
|---|
| 1681 | | - if (!xp->if_id) { |
|---|
| 1682 | | - err = -EINVAL; |
|---|
| 1683 | | - goto error; |
|---|
| 1684 | | - } |
|---|
| 1685 | | - } |
|---|
| 1686 | 1672 | |
|---|
| 1687 | 1673 | return xp; |
|---|
| 1688 | 1674 | error: |
|---|
| .. | .. |
|---|
| 1926 | 1912 | struct km_event c; |
|---|
| 1927 | 1913 | int delete; |
|---|
| 1928 | 1914 | struct xfrm_mark m; |
|---|
| 1929 | | - u32 mark = xfrm_mark_get(attrs, &m); |
|---|
| 1930 | 1915 | u32 if_id = 0; |
|---|
| 1931 | 1916 | |
|---|
| 1932 | 1917 | p = nlmsg_data(nlh); |
|---|
| .. | .. |
|---|
| 1943 | 1928 | if (attrs[XFRMA_IF_ID]) |
|---|
| 1944 | 1929 | if_id = nla_get_u32(attrs[XFRMA_IF_ID]); |
|---|
| 1945 | 1930 | |
|---|
| 1931 | + xfrm_mark_get(attrs, &m); |
|---|
| 1932 | + |
|---|
| 1946 | 1933 | if (p->index) |
|---|
| 1947 | | - xp = xfrm_policy_byid(net, mark, if_id, type, p->dir, p->index, delete, &err); |
|---|
| 1934 | + xp = xfrm_policy_byid(net, &m, if_id, type, p->dir, |
|---|
| 1935 | + p->index, delete, &err); |
|---|
| 1948 | 1936 | else { |
|---|
| 1949 | 1937 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
|---|
| 1950 | 1938 | struct xfrm_sec_ctx *ctx; |
|---|
| .. | .. |
|---|
| 1961 | 1949 | if (err) |
|---|
| 1962 | 1950 | return err; |
|---|
| 1963 | 1951 | } |
|---|
| 1964 | | - xp = xfrm_policy_bysel_ctx(net, mark, if_id, type, p->dir, &p->sel, |
|---|
| 1965 | | - ctx, delete, &err); |
|---|
| 1952 | + xp = xfrm_policy_bysel_ctx(net, &m, if_id, type, p->dir, |
|---|
| 1953 | + &p->sel, ctx, delete, &err); |
|---|
| 1966 | 1954 | security_xfrm_policy_free(ctx); |
|---|
| 1967 | 1955 | } |
|---|
| 1968 | 1956 | if (xp == NULL) |
|---|
| .. | .. |
|---|
| 2229 | 2217 | u8 type = XFRM_POLICY_TYPE_MAIN; |
|---|
| 2230 | 2218 | int err = -ENOENT; |
|---|
| 2231 | 2219 | struct xfrm_mark m; |
|---|
| 2232 | | - u32 mark = xfrm_mark_get(attrs, &m); |
|---|
| 2233 | 2220 | u32 if_id = 0; |
|---|
| 2234 | 2221 | |
|---|
| 2235 | 2222 | err = copy_from_user_policy_type(&type, attrs); |
|---|
| .. | .. |
|---|
| 2243 | 2230 | if (attrs[XFRMA_IF_ID]) |
|---|
| 2244 | 2231 | if_id = nla_get_u32(attrs[XFRMA_IF_ID]); |
|---|
| 2245 | 2232 | |
|---|
| 2233 | + xfrm_mark_get(attrs, &m); |
|---|
| 2234 | + |
|---|
| 2246 | 2235 | if (p->index) |
|---|
| 2247 | | - xp = xfrm_policy_byid(net, mark, if_id, type, p->dir, p->index, 0, &err); |
|---|
| 2236 | + xp = xfrm_policy_byid(net, &m, if_id, type, p->dir, p->index, |
|---|
| 2237 | + 0, &err); |
|---|
| 2248 | 2238 | else { |
|---|
| 2249 | 2239 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
|---|
| 2250 | 2240 | struct xfrm_sec_ctx *ctx; |
|---|
| .. | .. |
|---|
| 2261 | 2251 | if (err) |
|---|
| 2262 | 2252 | return err; |
|---|
| 2263 | 2253 | } |
|---|
| 2264 | | - xp = xfrm_policy_bysel_ctx(net, mark, if_id, type, p->dir, |
|---|
| 2254 | + xp = xfrm_policy_bysel_ctx(net, &m, if_id, type, p->dir, |
|---|
| 2265 | 2255 | &p->sel, ctx, 0, &err); |
|---|
| 2266 | 2256 | security_xfrm_policy_free(ctx); |
|---|
| 2267 | 2257 | } |
|---|
| .. | .. |
|---|
| 2433 | 2423 | int n = 0; |
|---|
| 2434 | 2424 | struct net *net = sock_net(skb->sk); |
|---|
| 2435 | 2425 | struct xfrm_encap_tmpl *encap = NULL; |
|---|
| 2426 | + u32 if_id = 0; |
|---|
| 2436 | 2427 | |
|---|
| 2437 | 2428 | if (attrs[XFRMA_MIGRATE] == NULL) |
|---|
| 2438 | 2429 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 2457 | 2448 | return 0; |
|---|
| 2458 | 2449 | } |
|---|
| 2459 | 2450 | |
|---|
| 2460 | | - err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap); |
|---|
| 2451 | + if (attrs[XFRMA_IF_ID]) |
|---|
| 2452 | + if_id = nla_get_u32(attrs[XFRMA_IF_ID]); |
|---|
| 2453 | + |
|---|
| 2454 | + err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap, if_id); |
|---|
| 2461 | 2455 | |
|---|
| 2462 | 2456 | kfree(encap); |
|---|
| 2463 | 2457 | |
|---|
| .. | .. |
|---|
| 2751 | 2745 | goto err; |
|---|
| 2752 | 2746 | } |
|---|
| 2753 | 2747 | |
|---|
| 2754 | | - err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, |
|---|
| 2755 | | - link->nla_max ? : XFRMA_MAX, |
|---|
| 2756 | | - link->nla_pol ? : xfrma_policy, extack); |
|---|
| 2748 | + err = nlmsg_parse_deprecated(nlh, xfrm_msg_min[type], attrs, |
|---|
| 2749 | + link->nla_max ? : XFRMA_MAX, |
|---|
| 2750 | + link->nla_pol ? : xfrma_policy, extack); |
|---|
| 2757 | 2751 | if (err < 0) |
|---|
| 2758 | 2752 | goto err; |
|---|
| 2759 | 2753 | |
|---|
| .. | .. |
|---|
| 2764 | 2758 | |
|---|
| 2765 | 2759 | err = link->doit(skb, nlh, attrs); |
|---|
| 2766 | 2760 | |
|---|
| 2761 | + /* We need to free skb allocated in xfrm_alloc_compat() before |
|---|
| 2762 | + * returning from this function, because consume_skb() won't take |
|---|
| 2763 | + * care of frag_list since netlink destructor sets |
|---|
| 2764 | + * sbk->head to NULL. (see netlink_skb_destructor()) |
|---|
| 2765 | + */ |
|---|
| 2766 | + if (skb_has_frag_list(skb)) { |
|---|
| 2767 | + kfree_skb(skb_shinfo(skb)->frag_list); |
|---|
| 2768 | + skb_shinfo(skb)->frag_list = NULL; |
|---|
| 2769 | + } |
|---|
| 2770 | + |
|---|
| 2767 | 2771 | err: |
|---|
| 2768 | 2772 | kvfree(nlh64); |
|---|
| 2769 | 2773 | return err; |
|---|