Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_tables: initial support for extended ACK reporting

Keep it simple to start with, just report attribute offsets that can be
useful to userspace when representating errors to users.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+208 -95
+208 -95
net/netfilter/nf_tables_api.c
··· 582 582 } 583 583 584 584 table = nft_table_lookup(net, nla[NFTA_TABLE_NAME], family, genmask); 585 - if (IS_ERR(table)) 585 + if (IS_ERR(table)) { 586 + NL_SET_BAD_ATTR(extack, nla[NFTA_TABLE_NAME]); 586 587 return PTR_ERR(table); 588 + } 587 589 588 590 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 589 591 if (!skb2) ··· 701 699 { 702 700 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 703 701 u8 genmask = nft_genmask_next(net); 704 - const struct nlattr *name; 705 - struct nft_table *table; 706 702 int family = nfmsg->nfgen_family; 703 + const struct nlattr *attr; 704 + struct nft_table *table; 707 705 u32 flags = 0; 708 706 struct nft_ctx ctx; 709 707 int err; 710 708 711 - name = nla[NFTA_TABLE_NAME]; 712 - table = nft_table_lookup(net, name, family, genmask); 709 + attr = nla[NFTA_TABLE_NAME]; 710 + table = nft_table_lookup(net, attr, family, genmask); 713 711 if (IS_ERR(table)) { 714 712 if (PTR_ERR(table) != -ENOENT) 715 713 return PTR_ERR(table); 716 714 } else { 717 - if (nlh->nlmsg_flags & NLM_F_EXCL) 715 + if (nlh->nlmsg_flags & NLM_F_EXCL) { 716 + NL_SET_BAD_ATTR(extack, attr); 718 717 return -EEXIST; 718 + } 719 719 if (nlh->nlmsg_flags & NLM_F_REPLACE) 720 720 return -EOPNOTSUPP; 721 721 ··· 736 732 if (table == NULL) 737 733 goto err_kzalloc; 738 734 739 - table->name = nla_strdup(name, GFP_KERNEL); 735 + table->name = nla_strdup(attr, GFP_KERNEL); 740 736 if (table->name == NULL) 741 737 goto err_strdup; 742 738 ··· 859 855 { 860 856 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 861 857 u8 genmask = nft_genmask_next(net); 862 - struct nft_table *table; 863 858 int family = nfmsg->nfgen_family; 859 + const struct nlattr *attr; 860 + struct nft_table *table; 864 861 struct nft_ctx ctx; 865 862 866 863 nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla); ··· 869 864 (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE])) 870 865 return nft_flush(&ctx, family); 871 866 872 - if (nla[NFTA_TABLE_HANDLE]) 873 - table = nft_table_lookup_byhandle(net, nla[NFTA_TABLE_HANDLE], 874 - genmask); 875 - else 876 - table = nft_table_lookup(net, nla[NFTA_TABLE_NAME], family, 877 - genmask); 867 + if (nla[NFTA_TABLE_HANDLE]) { 868 + attr = nla[NFTA_TABLE_HANDLE]; 869 + table = nft_table_lookup_byhandle(net, attr, genmask); 870 + } else { 871 + attr = nla[NFTA_TABLE_NAME]; 872 + table = nft_table_lookup(net, attr, family, genmask); 873 + } 878 874 879 - if (IS_ERR(table)) 875 + if (IS_ERR(table)) { 876 + NL_SET_BAD_ATTR(extack, attr); 880 877 return PTR_ERR(table); 878 + } 881 879 882 880 if (nlh->nlmsg_flags & NLM_F_NONREC && 883 881 table->use > 0) ··· 1172 1164 } 1173 1165 1174 1166 table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask); 1175 - if (IS_ERR(table)) 1167 + if (IS_ERR(table)) { 1168 + NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_TABLE]); 1176 1169 return PTR_ERR(table); 1170 + } 1177 1171 1178 1172 chain = nft_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); 1179 - if (IS_ERR(chain)) 1173 + if (IS_ERR(chain)) { 1174 + NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_NAME]); 1180 1175 return PTR_ERR(chain); 1176 + } 1181 1177 1182 1178 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 1183 1179 if (!skb2) ··· 1543 1531 struct netlink_ext_ack *extack) 1544 1532 { 1545 1533 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1546 - const struct nlattr * uninitialized_var(name); 1547 1534 u8 genmask = nft_genmask_next(net); 1548 1535 int family = nfmsg->nfgen_family; 1536 + const struct nlattr *attr; 1549 1537 struct nft_table *table; 1550 1538 struct nft_chain *chain; 1551 1539 u8 policy = NF_ACCEPT; ··· 1556 1544 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 1557 1545 1558 1546 table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask); 1559 - if (IS_ERR(table)) 1547 + if (IS_ERR(table)) { 1548 + NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_TABLE]); 1560 1549 return PTR_ERR(table); 1550 + } 1561 1551 1562 1552 chain = NULL; 1563 - name = nla[NFTA_CHAIN_NAME]; 1553 + attr = nla[NFTA_CHAIN_NAME]; 1564 1554 1565 1555 if (nla[NFTA_CHAIN_HANDLE]) { 1566 1556 handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); 1567 1557 chain = nft_chain_lookup_byhandle(table, handle, genmask); 1568 - if (IS_ERR(chain)) 1569 - return PTR_ERR(chain); 1570 - } else { 1571 - chain = nft_chain_lookup(table, name, genmask); 1572 1558 if (IS_ERR(chain)) { 1573 - if (PTR_ERR(chain) != -ENOENT) 1559 + NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_HANDLE]); 1560 + return PTR_ERR(chain); 1561 + } 1562 + attr = nla[NFTA_CHAIN_HANDLE]; 1563 + } else { 1564 + chain = nft_chain_lookup(table, attr, genmask); 1565 + if (IS_ERR(chain)) { 1566 + if (PTR_ERR(chain) != -ENOENT) { 1567 + NL_SET_BAD_ATTR(extack, attr); 1574 1568 return PTR_ERR(chain); 1569 + } 1575 1570 chain = NULL; 1576 1571 } 1577 1572 } 1578 1573 1579 1574 if (nla[NFTA_CHAIN_POLICY]) { 1580 1575 if (chain != NULL && 1581 - !nft_is_base_chain(chain)) 1576 + !nft_is_base_chain(chain)) { 1577 + NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_POLICY]); 1582 1578 return -EOPNOTSUPP; 1579 + } 1583 1580 1584 1581 if (chain == NULL && 1585 - nla[NFTA_CHAIN_HOOK] == NULL) 1582 + nla[NFTA_CHAIN_HOOK] == NULL) { 1583 + NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_POLICY]); 1586 1584 return -EOPNOTSUPP; 1585 + } 1587 1586 1588 1587 policy = ntohl(nla_get_be32(nla[NFTA_CHAIN_POLICY])); 1589 1588 switch (policy) { ··· 1609 1586 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); 1610 1587 1611 1588 if (chain != NULL) { 1612 - if (nlh->nlmsg_flags & NLM_F_EXCL) 1589 + if (nlh->nlmsg_flags & NLM_F_EXCL) { 1590 + NL_SET_BAD_ATTR(extack, attr); 1613 1591 return -EEXIST; 1592 + } 1614 1593 if (nlh->nlmsg_flags & NLM_F_REPLACE) 1615 1594 return -EOPNOTSUPP; 1616 1595 ··· 1629 1604 { 1630 1605 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1631 1606 u8 genmask = nft_genmask_next(net); 1607 + int family = nfmsg->nfgen_family; 1608 + const struct nlattr *attr; 1632 1609 struct nft_table *table; 1633 1610 struct nft_chain *chain; 1634 1611 struct nft_rule *rule; 1635 - int family = nfmsg->nfgen_family; 1636 1612 struct nft_ctx ctx; 1637 1613 u64 handle; 1638 1614 u32 use; 1639 1615 int err; 1640 1616 1641 1617 table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask); 1642 - if (IS_ERR(table)) 1618 + if (IS_ERR(table)) { 1619 + NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_TABLE]); 1643 1620 return PTR_ERR(table); 1621 + } 1644 1622 1645 1623 if (nla[NFTA_CHAIN_HANDLE]) { 1646 - handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); 1624 + attr = nla[NFTA_CHAIN_HANDLE]; 1625 + handle = be64_to_cpu(nla_get_be64(attr)); 1647 1626 chain = nft_chain_lookup_byhandle(table, handle, genmask); 1648 1627 } else { 1649 - chain = nft_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); 1628 + attr = nla[NFTA_CHAIN_NAME]; 1629 + chain = nft_chain_lookup(table, attr, genmask); 1650 1630 } 1651 - if (IS_ERR(chain)) 1631 + if (IS_ERR(chain)) { 1632 + NL_SET_BAD_ATTR(extack, attr); 1652 1633 return PTR_ERR(chain); 1634 + } 1653 1635 1654 1636 if (nlh->nlmsg_flags & NLM_F_NONREC && 1655 1637 chain->use > 0) ··· 1678 1646 /* There are rules and elements that are still holding references to us, 1679 1647 * we cannot do a recursive removal in this case. 1680 1648 */ 1681 - if (use > 0) 1649 + if (use > 0) { 1650 + NL_SET_BAD_ATTR(extack, attr); 1682 1651 return -EBUSY; 1652 + } 1683 1653 1684 1654 return nft_delchain(&ctx); 1685 1655 } ··· 2191 2157 } 2192 2158 2193 2159 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask); 2194 - if (IS_ERR(table)) 2160 + if (IS_ERR(table)) { 2161 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]); 2195 2162 return PTR_ERR(table); 2163 + } 2196 2164 2197 2165 chain = nft_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask); 2198 - if (IS_ERR(chain)) 2166 + if (IS_ERR(chain)) { 2167 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]); 2199 2168 return PTR_ERR(chain); 2169 + } 2200 2170 2201 2171 rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]); 2202 - if (IS_ERR(rule)) 2172 + if (IS_ERR(rule)) { 2173 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]); 2203 2174 return PTR_ERR(rule); 2175 + } 2204 2176 2205 2177 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 2206 2178 if (!skb2) ··· 2270 2230 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 2271 2231 2272 2232 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask); 2273 - if (IS_ERR(table)) 2233 + if (IS_ERR(table)) { 2234 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]); 2274 2235 return PTR_ERR(table); 2236 + } 2275 2237 2276 2238 chain = nft_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask); 2277 - if (IS_ERR(chain)) 2239 + if (IS_ERR(chain)) { 2240 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]); 2278 2241 return PTR_ERR(chain); 2242 + } 2279 2243 2280 2244 if (nla[NFTA_RULE_HANDLE]) { 2281 2245 handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_HANDLE])); 2282 2246 rule = __nft_rule_lookup(chain, handle); 2283 - if (IS_ERR(rule)) 2247 + if (IS_ERR(rule)) { 2248 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]); 2284 2249 return PTR_ERR(rule); 2250 + } 2285 2251 2286 - if (nlh->nlmsg_flags & NLM_F_EXCL) 2252 + if (nlh->nlmsg_flags & NLM_F_EXCL) { 2253 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]); 2287 2254 return -EEXIST; 2255 + } 2288 2256 if (nlh->nlmsg_flags & NLM_F_REPLACE) 2289 2257 old_rule = rule; 2290 2258 else ··· 2312 2264 2313 2265 pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION])); 2314 2266 old_rule = __nft_rule_lookup(chain, pos_handle); 2315 - if (IS_ERR(old_rule)) 2267 + if (IS_ERR(old_rule)) { 2268 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_POSITION]); 2316 2269 return PTR_ERR(old_rule); 2270 + } 2317 2271 } 2318 2272 2319 2273 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); ··· 2449 2399 struct nft_ctx ctx; 2450 2400 2451 2401 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask); 2452 - if (IS_ERR(table)) 2402 + if (IS_ERR(table)) { 2403 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]); 2453 2404 return PTR_ERR(table); 2405 + } 2454 2406 2455 2407 if (nla[NFTA_RULE_CHAIN]) { 2456 2408 chain = nft_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask); 2457 - if (IS_ERR(chain)) 2409 + if (IS_ERR(chain)) { 2410 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]); 2458 2411 return PTR_ERR(chain); 2412 + } 2459 2413 } 2460 2414 2461 2415 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); ··· 2467 2413 if (chain) { 2468 2414 if (nla[NFTA_RULE_HANDLE]) { 2469 2415 rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]); 2470 - if (IS_ERR(rule)) 2416 + if (IS_ERR(rule)) { 2417 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]); 2471 2418 return PTR_ERR(rule); 2419 + } 2472 2420 2473 2421 err = nft_delrule(&ctx, rule); 2474 2422 } else if (nla[NFTA_RULE_ID]) { 2475 2423 rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_ID]); 2476 - if (IS_ERR(rule)) 2424 + if (IS_ERR(rule)) { 2425 + NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_ID]); 2477 2426 return PTR_ERR(rule); 2427 + } 2478 2428 2479 2429 err = nft_delrule(&ctx, rule); 2480 2430 } else { ··· 2646 2588 const struct sk_buff *skb, 2647 2589 const struct nlmsghdr *nlh, 2648 2590 const struct nlattr * const nla[], 2591 + struct netlink_ext_ack *extack, 2649 2592 u8 genmask) 2650 2593 { 2651 2594 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ··· 2656 2597 if (nla[NFTA_SET_TABLE] != NULL) { 2657 2598 table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family, 2658 2599 genmask); 2659 - if (IS_ERR(table)) 2600 + if (IS_ERR(table)) { 2601 + NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]); 2660 2602 return PTR_ERR(table); 2603 + } 2661 2604 } 2662 2605 2663 2606 nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla); ··· 2971 2910 int err; 2972 2911 2973 2912 /* Verify existence before starting dump */ 2974 - err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, genmask); 2913 + err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, extack, 2914 + genmask); 2975 2915 if (err < 0) 2976 2916 return err; 2977 2917 ··· 3152 3090 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 3153 3091 3154 3092 table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family, genmask); 3155 - if (IS_ERR(table)) 3093 + if (IS_ERR(table)) { 3094 + NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]); 3156 3095 return PTR_ERR(table); 3096 + } 3157 3097 3158 3098 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 3159 3099 3160 3100 set = nft_set_lookup(table, nla[NFTA_SET_NAME], genmask); 3161 3101 if (IS_ERR(set)) { 3162 - if (PTR_ERR(set) != -ENOENT) 3102 + if (PTR_ERR(set) != -ENOENT) { 3103 + NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]); 3163 3104 return PTR_ERR(set); 3105 + } 3164 3106 } else { 3165 - if (nlh->nlmsg_flags & NLM_F_EXCL) 3107 + if (nlh->nlmsg_flags & NLM_F_EXCL) { 3108 + NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]); 3166 3109 return -EEXIST; 3110 + } 3167 3111 if (nlh->nlmsg_flags & NLM_F_REPLACE) 3168 3112 return -EOPNOTSUPP; 3113 + 3169 3114 return 0; 3170 3115 } 3171 3116 ··· 3273 3204 { 3274 3205 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 3275 3206 u8 genmask = nft_genmask_next(net); 3207 + const struct nlattr *attr; 3276 3208 struct nft_set *set; 3277 3209 struct nft_ctx ctx; 3278 3210 int err; ··· 3283 3213 if (nla[NFTA_SET_TABLE] == NULL) 3284 3214 return -EINVAL; 3285 3215 3286 - err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, genmask); 3216 + err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, extack, 3217 + genmask); 3287 3218 if (err < 0) 3288 3219 return err; 3289 3220 3290 - if (nla[NFTA_SET_HANDLE]) 3291 - set = nft_set_lookup_byhandle(ctx.table, nla[NFTA_SET_HANDLE], 3292 - genmask); 3293 - else 3294 - set = nft_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); 3295 - if (IS_ERR(set)) 3296 - return PTR_ERR(set); 3221 + if (nla[NFTA_SET_HANDLE]) { 3222 + attr = nla[NFTA_SET_HANDLE]; 3223 + set = nft_set_lookup_byhandle(ctx.table, attr, genmask); 3224 + } else { 3225 + attr = nla[NFTA_SET_NAME]; 3226 + set = nft_set_lookup(ctx.table, attr, genmask); 3227 + } 3297 3228 3229 + if (IS_ERR(set)) { 3230 + NL_SET_BAD_ATTR(extack, attr); 3231 + return PTR_ERR(set); 3232 + } 3298 3233 if (!list_empty(&set->bindings) || 3299 - (nlh->nlmsg_flags & NLM_F_NONREC && atomic_read(&set->nelems) > 0)) 3234 + (nlh->nlmsg_flags & NLM_F_NONREC && atomic_read(&set->nelems) > 0)) { 3235 + NL_SET_BAD_ATTR(extack, attr); 3300 3236 return -EBUSY; 3237 + } 3301 3238 3302 3239 return nft_delset(&ctx, set); 3303 3240 } ··· 3432 3355 const struct sk_buff *skb, 3433 3356 const struct nlmsghdr *nlh, 3434 3357 const struct nlattr * const nla[], 3358 + struct netlink_ext_ack *extack, 3435 3359 u8 genmask) 3436 3360 { 3437 3361 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ··· 3441 3363 3442 3364 table = nft_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], family, 3443 3365 genmask); 3444 - if (IS_ERR(table)) 3366 + if (IS_ERR(table)) { 3367 + NL_SET_BAD_ATTR(extack, nla[NFTA_SET_ELEM_LIST_TABLE]); 3445 3368 return PTR_ERR(table); 3369 + } 3446 3370 3447 3371 nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla); 3448 3372 return 0; ··· 3774 3694 struct nft_ctx ctx; 3775 3695 int rem, err = 0; 3776 3696 3777 - err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask); 3697 + err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack, 3698 + genmask); 3778 3699 if (err < 0) 3779 3700 return err; 3780 3701 ··· 4129 4048 if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) 4130 4049 return -EINVAL; 4131 4050 4132 - err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask); 4051 + err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack, 4052 + genmask); 4133 4053 if (err < 0) 4134 4054 return err; 4135 4055 ··· 4318 4236 struct nft_ctx ctx; 4319 4237 int rem, err = 0; 4320 4238 4321 - err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask); 4239 + err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack, 4240 + genmask); 4322 4241 if (err < 0) 4323 4242 return err; 4324 4243 ··· 4574 4491 return -EINVAL; 4575 4492 4576 4493 table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask); 4577 - if (IS_ERR(table)) 4494 + if (IS_ERR(table)) { 4495 + NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]); 4578 4496 return PTR_ERR(table); 4497 + } 4579 4498 4580 4499 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); 4581 4500 obj = nft_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); 4582 4501 if (IS_ERR(obj)) { 4583 4502 err = PTR_ERR(obj); 4584 - if (err != -ENOENT) 4503 + if (err != -ENOENT) { 4504 + NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]); 4585 4505 return err; 4586 - 4506 + } 4587 4507 } else { 4588 - if (nlh->nlmsg_flags & NLM_F_EXCL) 4508 + if (nlh->nlmsg_flags & NLM_F_EXCL) { 4509 + NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]); 4589 4510 return -EEXIST; 4590 - 4511 + } 4591 4512 return 0; 4592 4513 } 4593 4514 ··· 4803 4716 return -EINVAL; 4804 4717 4805 4718 table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask); 4806 - if (IS_ERR(table)) 4719 + if (IS_ERR(table)) { 4720 + NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]); 4807 4721 return PTR_ERR(table); 4722 + } 4808 4723 4809 4724 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); 4810 4725 obj = nft_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); 4811 - if (IS_ERR(obj)) 4726 + if (IS_ERR(obj)) { 4727 + NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]); 4812 4728 return PTR_ERR(obj); 4729 + } 4813 4730 4814 4731 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 4815 4732 if (!skb2) ··· 4852 4761 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4853 4762 u8 genmask = nft_genmask_next(net); 4854 4763 int family = nfmsg->nfgen_family; 4764 + const struct nlattr *attr; 4855 4765 struct nft_table *table; 4856 4766 struct nft_object *obj; 4857 4767 struct nft_ctx ctx; ··· 4863 4771 return -EINVAL; 4864 4772 4865 4773 table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask); 4866 - if (IS_ERR(table)) 4774 + if (IS_ERR(table)) { 4775 + NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]); 4867 4776 return PTR_ERR(table); 4777 + } 4868 4778 4869 4779 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); 4870 - if (nla[NFTA_OBJ_HANDLE]) 4871 - obj = nft_obj_lookup_byhandle(table, nla[NFTA_OBJ_HANDLE], 4872 - objtype, genmask); 4873 - else 4874 - obj = nft_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, 4875 - genmask); 4876 - if (IS_ERR(obj)) 4780 + if (nla[NFTA_OBJ_HANDLE]) { 4781 + attr = nla[NFTA_OBJ_HANDLE]; 4782 + obj = nft_obj_lookup_byhandle(table, attr, objtype, genmask); 4783 + } else { 4784 + attr = nla[NFTA_OBJ_NAME]; 4785 + obj = nft_obj_lookup(table, attr, objtype, genmask); 4786 + } 4787 + 4788 + if (IS_ERR(obj)) { 4789 + NL_SET_BAD_ATTR(extack, attr); 4877 4790 return PTR_ERR(obj); 4878 - if (obj->use > 0) 4791 + } 4792 + if (obj->use > 0) { 4793 + NL_SET_BAD_ATTR(extack, attr); 4879 4794 return -EBUSY; 4795 + } 4880 4796 4881 4797 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 4882 4798 ··· 5146 5046 5147 5047 table = nft_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], family, 5148 5048 genmask); 5149 - if (IS_ERR(table)) 5049 + if (IS_ERR(table)) { 5050 + NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_TABLE]); 5150 5051 return PTR_ERR(table); 5052 + } 5151 5053 5152 5054 flowtable = nft_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], 5153 5055 genmask); 5154 5056 if (IS_ERR(flowtable)) { 5155 5057 err = PTR_ERR(flowtable); 5156 - if (err != -ENOENT) 5058 + if (err != -ENOENT) { 5059 + NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_NAME]); 5157 5060 return err; 5061 + } 5158 5062 } else { 5159 - if (nlh->nlmsg_flags & NLM_F_EXCL) 5063 + if (nlh->nlmsg_flags & NLM_F_EXCL) { 5064 + NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_NAME]); 5160 5065 return -EEXIST; 5066 + } 5161 5067 5162 5068 return 0; 5163 5069 } ··· 5259 5153 u8 genmask = nft_genmask_next(net); 5260 5154 int family = nfmsg->nfgen_family; 5261 5155 struct nft_flowtable *flowtable; 5156 + const struct nlattr *attr; 5262 5157 struct nft_table *table; 5263 5158 struct nft_ctx ctx; 5264 5159 ··· 5270 5163 5271 5164 table = nft_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], family, 5272 5165 genmask); 5273 - if (IS_ERR(table)) 5166 + if (IS_ERR(table)) { 5167 + NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_TABLE]); 5274 5168 return PTR_ERR(table); 5169 + } 5275 5170 5276 - if (nla[NFTA_FLOWTABLE_HANDLE]) 5277 - flowtable = nft_flowtable_lookup_byhandle(table, 5278 - nla[NFTA_FLOWTABLE_HANDLE], 5279 - genmask); 5280 - else 5281 - flowtable = nft_flowtable_lookup(table, 5282 - nla[NFTA_FLOWTABLE_NAME], 5283 - genmask); 5284 - if (IS_ERR(flowtable)) 5285 - return PTR_ERR(flowtable); 5286 - if (flowtable->use > 0) 5171 + if (nla[NFTA_FLOWTABLE_HANDLE]) { 5172 + attr = nla[NFTA_FLOWTABLE_HANDLE]; 5173 + flowtable = nft_flowtable_lookup_byhandle(table, attr, genmask); 5174 + } else { 5175 + attr = nla[NFTA_FLOWTABLE_NAME]; 5176 + flowtable = nft_flowtable_lookup(table, attr, genmask); 5177 + } 5178 + 5179 + if (IS_ERR(flowtable)) { 5180 + NL_SET_BAD_ATTR(extack, attr); 5181 + return PTR_ERR(flowtable); 5182 + } 5183 + if (flowtable->use > 0) { 5184 + NL_SET_BAD_ATTR(extack, attr); 5287 5185 return -EBUSY; 5186 + } 5288 5187 5289 5188 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 5290 5189