Skip to content

Commit 84ae017

Browse files
Alexander Aringdavem330
authored andcommitted
net: sched: act: handle generic action errors
This patch adds extack support for generic act handling. The extack will be set deeper to each called function which is not part of netdev core api. Based on work by David Ahern <[email protected]> Cc: David Ahern <[email protected]> Signed-off-by: Alexander Aring <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent aea0d72 commit 84ae017

File tree

1 file changed

+61
-32
lines changed

1 file changed

+61
-32
lines changed

net/sched/act_api.c

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -617,31 +617,40 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
617617
int err;
618618

619619
if (name == NULL) {
620-
err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL);
620+
err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
621621
if (err < 0)
622622
goto err_out;
623623
err = -EINVAL;
624624
kind = tb[TCA_ACT_KIND];
625-
if (!kind)
625+
if (!kind) {
626+
NL_SET_ERR_MSG(extack, "TC action kind must be specified");
626627
goto err_out;
627-
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
628+
}
629+
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
630+
NL_SET_ERR_MSG(extack, "TC action name too long");
628631
goto err_out;
632+
}
629633
if (tb[TCA_ACT_COOKIE]) {
630634
int cklen = nla_len(tb[TCA_ACT_COOKIE]);
631635

632-
if (cklen > TC_COOKIE_MAX_SIZE)
636+
if (cklen > TC_COOKIE_MAX_SIZE) {
637+
NL_SET_ERR_MSG(extack, "TC cookie size above the maximum");
633638
goto err_out;
639+
}
634640

635641
cookie = nla_memdup_cookie(tb);
636642
if (!cookie) {
643+
NL_SET_ERR_MSG(extack, "No memory to generate TC cookie");
637644
err = -ENOMEM;
638645
goto err_out;
639646
}
640647
}
641648
} else {
642-
err = -EINVAL;
643-
if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
649+
if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
650+
NL_SET_ERR_MSG(extack, "TC action name too long");
651+
err = -EINVAL;
644652
goto err_out;
653+
}
645654
}
646655

647656
a_o = tc_lookup_action_n(act_name);
@@ -664,6 +673,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
664673
goto err_mod;
665674
}
666675
#endif
676+
NL_SET_ERR_MSG(extack, "Failed to load TC action module");
667677
err = -ENOENT;
668678
goto err_out;
669679
}
@@ -698,6 +708,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
698708

699709
list_add_tail(&a->list, &actions);
700710
tcf_action_destroy(&actions, bind);
711+
NL_SET_ERR_MSG(extack, "Failed to init TC action chain");
701712
return ERR_PTR(err);
702713
}
703714
}
@@ -734,7 +745,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
734745
int err;
735746
int i;
736747

737-
err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL);
748+
err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
738749
if (err < 0)
739750
return err;
740751

@@ -842,7 +853,8 @@ static int tca_get_fill(struct sk_buff *skb, struct list_head *actions,
842853

843854
static int
844855
tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
845-
struct list_head *actions, int event)
856+
struct list_head *actions, int event,
857+
struct netlink_ext_ack *extack)
846858
{
847859
struct sk_buff *skb;
848860

@@ -851,6 +863,7 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
851863
return -ENOBUFS;
852864
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
853865
0, 0) <= 0) {
866+
NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
854867
kfree_skb(skb);
855868
return -EINVAL;
856869
}
@@ -859,28 +872,33 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
859872
}
860873

861874
static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
862-
struct nlmsghdr *n, u32 portid)
875+
struct nlmsghdr *n, u32 portid,
876+
struct netlink_ext_ack *extack)
863877
{
864878
struct nlattr *tb[TCA_ACT_MAX + 1];
865879
const struct tc_action_ops *ops;
866880
struct tc_action *a;
867881
int index;
868882
int err;
869883

870-
err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL);
884+
err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
871885
if (err < 0)
872886
goto err_out;
873887

874888
err = -EINVAL;
875889
if (tb[TCA_ACT_INDEX] == NULL ||
876-
nla_len(tb[TCA_ACT_INDEX]) < sizeof(index))
890+
nla_len(tb[TCA_ACT_INDEX]) < sizeof(index)) {
891+
NL_SET_ERR_MSG(extack, "Invalid TC action index value");
877892
goto err_out;
893+
}
878894
index = nla_get_u32(tb[TCA_ACT_INDEX]);
879895

880896
err = -EINVAL;
881897
ops = tc_lookup_action(tb[TCA_ACT_KIND]);
882-
if (!ops) /* could happen in batch of actions */
898+
if (!ops) { /* could happen in batch of actions */
899+
NL_SET_ERR_MSG(extack, "Specified TC action not found");
883900
goto err_out;
901+
}
884902
err = -ENOENT;
885903
if (ops->lookup(net, &a, index) == 0)
886904
goto err_mod;
@@ -895,7 +913,8 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
895913
}
896914

897915
static int tca_action_flush(struct net *net, struct nlattr *nla,
898-
struct nlmsghdr *n, u32 portid)
916+
struct nlmsghdr *n, u32 portid,
917+
struct netlink_ext_ack *extack)
899918
{
900919
struct sk_buff *skb;
901920
unsigned char *b;
@@ -909,35 +928,39 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
909928
int err = -ENOMEM;
910929

911930
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
912-
if (!skb) {
913-
pr_debug("tca_action_flush: failed skb alloc\n");
931+
if (!skb)
914932
return err;
915-
}
916933

917934
b = skb_tail_pointer(skb);
918935

919-
err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL);
936+
err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
920937
if (err < 0)
921938
goto err_out;
922939

923940
err = -EINVAL;
924941
kind = tb[TCA_ACT_KIND];
925942
ops = tc_lookup_action(kind);
926-
if (!ops) /*some idjot trying to flush unknown action */
943+
if (!ops) { /*some idjot trying to flush unknown action */
944+
NL_SET_ERR_MSG(extack, "Cannot flush unknown TC action");
927945
goto err_out;
946+
}
928947

929948
nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION,
930949
sizeof(*t), 0);
931-
if (!nlh)
950+
if (!nlh) {
951+
NL_SET_ERR_MSG(extack, "Failed to create TC action flush notification");
932952
goto out_module_put;
953+
}
933954
t = nlmsg_data(nlh);
934955
t->tca_family = AF_UNSPEC;
935956
t->tca__pad1 = 0;
936957
t->tca__pad2 = 0;
937958

938959
nest = nla_nest_start(skb, TCA_ACT_TAB);
939-
if (!nest)
960+
if (!nest) {
961+
NL_SET_ERR_MSG(extack, "Failed to add new netlink message");
940962
goto out_module_put;
963+
}
941964

942965
err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops);
943966
if (err <= 0) {
@@ -954,6 +977,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
954977
n->nlmsg_flags & NLM_F_ECHO);
955978
if (err > 0)
956979
return 0;
980+
if (err < 0)
981+
NL_SET_ERR_MSG(extack, "Failed to send TC action flush notification");
957982

958983
return err;
959984

@@ -966,7 +991,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
966991

967992
static int
968993
tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
969-
u32 portid)
994+
u32 portid, struct netlink_ext_ack *extack)
970995
{
971996
int ret;
972997
struct sk_buff *skb;
@@ -977,13 +1002,15 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
9771002

9781003
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
9791004
0, 1) <= 0) {
1005+
NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes");
9801006
kfree_skb(skb);
9811007
return -EINVAL;
9821008
}
9831009

9841010
/* now do the delete */
9851011
ret = tcf_action_destroy(actions, 0);
9861012
if (ret < 0) {
1013+
NL_SET_ERR_MSG(extack, "Failed to delete TC action");
9871014
kfree_skb(skb);
9881015
return ret;
9891016
}
@@ -997,26 +1024,27 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
9971024

9981025
static int
9991026
tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
1000-
u32 portid, int event)
1027+
u32 portid, int event, struct netlink_ext_ack *extack)
10011028
{
10021029
int i, ret;
10031030
struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
10041031
struct tc_action *act;
10051032
LIST_HEAD(actions);
10061033

1007-
ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL);
1034+
ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
10081035
if (ret < 0)
10091036
return ret;
10101037

10111038
if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
10121039
if (tb[1])
1013-
return tca_action_flush(net, tb[1], n, portid);
1040+
return tca_action_flush(net, tb[1], n, portid, extack);
10141041

1042+
NL_SET_ERR_MSG(extack, "Invalid netlink attributes while flushing TC action");
10151043
return -EINVAL;
10161044
}
10171045

10181046
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
1019-
act = tcf_action_get_1(net, tb[i], n, portid);
1047+
act = tcf_action_get_1(net, tb[i], n, portid, extack);
10201048
if (IS_ERR(act)) {
10211049
ret = PTR_ERR(act);
10221050
goto err;
@@ -1026,9 +1054,9 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
10261054
}
10271055

10281056
if (event == RTM_GETACTION)
1029-
ret = tcf_get_notify(net, portid, n, &actions, event);
1057+
ret = tcf_get_notify(net, portid, n, &actions, event, extack);
10301058
else { /* delete */
1031-
ret = tcf_del_notify(net, n, &actions, portid);
1059+
ret = tcf_del_notify(net, n, &actions, portid, extack);
10321060
if (ret)
10331061
goto err;
10341062
return ret;
@@ -1041,7 +1069,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
10411069

10421070
static int
10431071
tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
1044-
u32 portid)
1072+
u32 portid, struct netlink_ext_ack *extack)
10451073
{
10461074
struct sk_buff *skb;
10471075
int err = 0;
@@ -1052,6 +1080,7 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions,
10521080

10531081
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
10541082
RTM_NEWACTION, 0, 0) <= 0) {
1083+
NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while deleting TC action");
10551084
kfree_skb(skb);
10561085
return -EINVAL;
10571086
}
@@ -1075,7 +1104,7 @@ static int tcf_action_add(struct net *net, struct nlattr *nla,
10751104
if (ret)
10761105
return ret;
10771106

1078-
return tcf_add_notify(net, n, &actions, portid);
1107+
return tcf_add_notify(net, n, &actions, portid, extack);
10791108
}
10801109

10811110
static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON;
@@ -1103,7 +1132,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
11031132
return ret;
11041133

11051134
if (tca[TCA_ACT_TAB] == NULL) {
1106-
pr_notice("tc_ctl_action: received NO action attribs\n");
1135+
NL_SET_ERR_MSG(extack, "Netlink action attributes missing");
11071136
return -EINVAL;
11081137
}
11091138

@@ -1126,11 +1155,11 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
11261155
break;
11271156
case RTM_DELACTION:
11281157
ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
1129-
portid, RTM_DELACTION);
1158+
portid, RTM_DELACTION, extack);
11301159
break;
11311160
case RTM_GETACTION:
11321161
ret = tca_action_gd(net, tca[TCA_ACT_TAB], n,
1133-
portid, RTM_GETACTION);
1162+
portid, RTM_GETACTION, extack);
11341163
break;
11351164
default:
11361165
BUG();

0 commit comments

Comments
 (0)