@@ -30,12 +30,13 @@ static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
3030};
3131
3232static const struct nla_policy pedit_key_ex_policy [TCA_PEDIT_KEY_EX_MAX + 1 ] = {
33- [TCA_PEDIT_KEY_EX_HTYPE ] = { .type = NLA_U16 },
34- [TCA_PEDIT_KEY_EX_CMD ] = { .type = NLA_U16 },
33+ [TCA_PEDIT_KEY_EX_HTYPE ] =
34+ NLA_POLICY_MAX (NLA_U16 , TCA_PEDIT_HDR_TYPE_MAX ),
35+ [TCA_PEDIT_KEY_EX_CMD ] = NLA_POLICY_MAX (NLA_U16 , TCA_PEDIT_CMD_MAX ),
3536};
3637
3738static struct tcf_pedit_key_ex * tcf_pedit_keys_ex_parse (struct nlattr * nla ,
38- u8 n )
39+ u8 n , struct netlink_ext_ack * extack )
3940{
4041 struct tcf_pedit_key_ex * keys_ex ;
4142 struct tcf_pedit_key_ex * k ;
@@ -56,12 +57,14 @@ static struct tcf_pedit_key_ex *tcf_pedit_keys_ex_parse(struct nlattr *nla,
5657 struct nlattr * tb [TCA_PEDIT_KEY_EX_MAX + 1 ];
5758
5859 if (!n ) {
60+ NL_SET_ERR_MSG_MOD (extack , "Can't parse more extended keys than requested" );
5961 err = - EINVAL ;
6062 goto err_out ;
6163 }
6264 n -- ;
6365
6466 if (nla_type (ka ) != TCA_PEDIT_KEY_EX ) {
67+ NL_SET_ERR_MSG_ATTR (extack , ka , "Unknown attribute, expected extended key" );
6568 err = - EINVAL ;
6669 goto err_out ;
6770 }
@@ -72,25 +75,26 @@ static struct tcf_pedit_key_ex *tcf_pedit_keys_ex_parse(struct nlattr *nla,
7275 if (err )
7376 goto err_out ;
7477
75- if (! tb [ TCA_PEDIT_KEY_EX_HTYPE ] ||
76- ! tb [ TCA_PEDIT_KEY_EX_CMD ]) {
78+ if (NL_REQ_ATTR_CHECK ( extack , nla , tb , TCA_PEDIT_KEY_EX_HTYPE )) {
79+ NL_SET_ERR_MSG ( extack , "Missing required attribute" );
7780 err = - EINVAL ;
7881 goto err_out ;
7982 }
8083
81- k -> htype = nla_get_u16 (tb [TCA_PEDIT_KEY_EX_HTYPE ]);
82- k -> cmd = nla_get_u16 (tb [TCA_PEDIT_KEY_EX_CMD ]);
83-
84- if (k -> htype > TCA_PEDIT_HDR_TYPE_MAX ||
85- k -> cmd > TCA_PEDIT_CMD_MAX ) {
84+ if (NL_REQ_ATTR_CHECK (extack , nla , tb , TCA_PEDIT_KEY_EX_CMD )) {
85+ NL_SET_ERR_MSG (extack , "Missing required attribute" );
8686 err = - EINVAL ;
8787 goto err_out ;
8888 }
8989
90+ k -> htype = nla_get_u16 (tb [TCA_PEDIT_KEY_EX_HTYPE ]);
91+ k -> cmd = nla_get_u16 (tb [TCA_PEDIT_KEY_EX_CMD ]);
92+
9093 k ++ ;
9194 }
9295
9396 if (n ) {
97+ NL_SET_ERR_MSG_MOD (extack , "Not enough extended keys to parse" );
9498 err = - EINVAL ;
9599 goto err_out ;
96100 }
@@ -222,7 +226,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
222226 }
223227
224228 nparms -> tcfp_keys_ex =
225- tcf_pedit_keys_ex_parse (tb [TCA_PEDIT_KEYS_EX ], parm -> nkeys );
229+ tcf_pedit_keys_ex_parse (tb [TCA_PEDIT_KEYS_EX ], parm -> nkeys , extack );
226230 if (IS_ERR (nparms -> tcfp_keys_ex )) {
227231 ret = PTR_ERR (nparms -> tcfp_keys_ex );
228232 goto out_free ;
@@ -247,8 +251,16 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
247251 memcpy (nparms -> tcfp_keys , parm -> keys , ksize );
248252
249253 for (i = 0 ; i < nparms -> tcfp_nkeys ; ++ i ) {
254+ u32 offmask = nparms -> tcfp_keys [i ].offmask ;
250255 u32 cur = nparms -> tcfp_keys [i ].off ;
251256
257+ /* The AT option can be added to static offsets in the datapath */
258+ if (!offmask && cur % 4 ) {
259+ NL_SET_ERR_MSG_MOD (extack , "Offsets must be on 32bit boundaries" );
260+ ret = - EINVAL ;
261+ goto put_chain ;
262+ }
263+
252264 /* sanitize the shift value for any later use */
253265 nparms -> tcfp_keys [i ].shift = min_t (size_t ,
254266 BITS_PER_TYPE (int ) - 1 ,
@@ -257,7 +269,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
257269 /* The AT option can read a single byte, we can bound the actual
258270 * value with uchar max.
259271 */
260- cur += (0xff & nparms -> tcfp_keys [ i ]. offmask ) >> nparms -> tcfp_keys [i ].shift ;
272+ cur += (0xff & offmask ) >> nparms -> tcfp_keys [i ].shift ;
261273
262274 /* Each key touches 4 bytes starting from the computed offset */
263275 nparms -> tcfp_off_max_hint =
@@ -313,37 +325,28 @@ static bool offset_valid(struct sk_buff *skb, int offset)
313325 return true;
314326}
315327
316- static int pedit_skb_hdr_offset (struct sk_buff * skb ,
317- enum pedit_header_type htype , int * hoffset )
328+ static void pedit_skb_hdr_offset (struct sk_buff * skb ,
329+ enum pedit_header_type htype , int * hoffset )
318330{
319- int ret = - EINVAL ;
320-
331+ /* 'htype' is validated in the netlink parsing */
321332 switch (htype ) {
322333 case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH :
323- if (skb_mac_header_was_set (skb )) {
334+ if (skb_mac_header_was_set (skb ))
324335 * hoffset = skb_mac_offset (skb );
325- ret = 0 ;
326- }
327336 break ;
328337 case TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK :
329338 case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 :
330339 case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 :
331340 * hoffset = skb_network_offset (skb );
332- ret = 0 ;
333341 break ;
334342 case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP :
335343 case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP :
336- if (skb_transport_header_was_set (skb )) {
344+ if (skb_transport_header_was_set (skb ))
337345 * hoffset = skb_transport_offset (skb );
338- ret = 0 ;
339- }
340346 break ;
341347 default :
342- ret = - EINVAL ;
343348 break ;
344349 }
345-
346- return ret ;
347350}
348351
349352TC_INDIRECT_SCOPE int tcf_pedit_act (struct sk_buff * skb ,
@@ -376,10 +379,9 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
376379
377380 for (i = parms -> tcfp_nkeys ; i > 0 ; i -- , tkey ++ ) {
378381 int offset = tkey -> off ;
382+ int hoffset = 0 ;
379383 u32 * ptr , hdata ;
380- int hoffset ;
381384 u32 val ;
382- int rc ;
383385
384386 if (tkey_ex ) {
385387 htype = tkey_ex -> htype ;
@@ -388,36 +390,30 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
388390 tkey_ex ++ ;
389391 }
390392
391- rc = pedit_skb_hdr_offset (skb , htype , & hoffset );
392- if (rc ) {
393- pr_info ("tc action pedit bad header type specified (0x%x)\n" ,
394- htype );
395- goto bad ;
396- }
393+ pedit_skb_hdr_offset (skb , htype , & hoffset );
397394
398395 if (tkey -> offmask ) {
399396 u8 * d , _d ;
400397
401398 if (!offset_valid (skb , hoffset + tkey -> at )) {
402- pr_info ("tc action pedit 'at' offset %d out of bounds\n" ,
403- hoffset + tkey -> at );
399+ pr_info_ratelimited ("tc action pedit 'at' offset %d out of bounds\n" ,
400+ hoffset + tkey -> at );
404401 goto bad ;
405402 }
406403 d = skb_header_pointer (skb , hoffset + tkey -> at ,
407404 sizeof (_d ), & _d );
408405 if (!d )
409406 goto bad ;
410- offset += (* d & tkey -> offmask ) >> tkey -> shift ;
411- }
412407
413- if (offset % 4 ) {
414- pr_info ("tc action pedit offset must be on 32 bit boundaries\n" );
415- goto bad ;
408+ offset += (* d & tkey -> offmask ) >> tkey -> shift ;
409+ if (offset % 4 ) {
410+ pr_info_ratelimited ("tc action pedit offset must be on 32 bit boundaries\n" );
411+ goto bad ;
412+ }
416413 }
417414
418415 if (!offset_valid (skb , hoffset + offset )) {
419- pr_info ("tc action pedit offset %d out of bounds\n" ,
420- hoffset + offset );
416+ pr_info_ratelimited ("tc action pedit offset %d out of bounds\n" , hoffset + offset );
421417 goto bad ;
422418 }
423419
@@ -434,8 +430,7 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
434430 val = (* ptr + tkey -> val ) & ~tkey -> mask ;
435431 break ;
436432 default :
437- pr_info ("tc action pedit bad command (%d)\n" ,
438- cmd );
433+ pr_info_ratelimited ("tc action pedit bad command (%d)\n" , cmd );
439434 goto bad ;
440435 }
441436
0 commit comments