@@ -321,12 +321,13 @@ int ing_xdp(struct xdp_md *ctx)
321321}
322322
323323/*
324- * Check that skb->data_meta..skb->data is empty if prog writes to packet
325- * _payload_ using packet pointers. Applies only to cloned skbs .
324+ * Check that, when operating on a cloned packet, skb->data_meta..skb->data is
325+ * kept intact if prog writes to packet _payload_ using packet pointers .
326326 */
327327SEC ("tc" )
328- int clone_data_meta_empty_on_data_write (struct __sk_buff * ctx )
328+ int clone_data_meta_survives_data_write (struct __sk_buff * ctx )
329329{
330+ __u8 * meta_have = ctx_ptr (ctx , data_meta );
330331 struct ethhdr * eth = ctx_ptr (ctx , data );
331332
332333 if (eth + 1 > ctx_ptr (ctx , data_end ))
@@ -335,8 +336,10 @@ int clone_data_meta_empty_on_data_write(struct __sk_buff *ctx)
335336 if (eth -> h_proto != 0 )
336337 goto out ;
337338
338- /* Expect no metadata */
339- if (ctx -> data_meta != ctx -> data )
339+ if (meta_have + META_SIZE > eth )
340+ goto out ;
341+
342+ if (!check_metadata (meta_have ))
340343 goto out ;
341344
342345 /* Packet write to trigger unclone in prologue */
@@ -348,40 +351,44 @@ int clone_data_meta_empty_on_data_write(struct __sk_buff *ctx)
348351}
349352
350353/*
351- * Check that skb->data_meta..skb->data is empty if prog writes to packet
352- * _metadata_ using packet pointers. Applies only to cloned skbs .
354+ * Check that, when operating on a cloned packet, skb->data_meta..skb->data is
355+ * kept intact if prog writes to packet _metadata_ using packet pointers .
353356 */
354357SEC ("tc" )
355- int clone_data_meta_empty_on_meta_write (struct __sk_buff * ctx )
358+ int clone_data_meta_survives_meta_write (struct __sk_buff * ctx )
356359{
360+ __u8 * meta_have = ctx_ptr (ctx , data_meta );
357361 struct ethhdr * eth = ctx_ptr (ctx , data );
358- __u8 * md = ctx_ptr (ctx , data_meta );
359362
360363 if (eth + 1 > ctx_ptr (ctx , data_end ))
361364 goto out ;
362365 /* Ignore non-test packets */
363366 if (eth -> h_proto != 0 )
364367 goto out ;
365368
366- if (md + 1 > ctx_ptr (ctx , data )) {
367- /* Expect no metadata */
368- test_pass = true;
369- } else {
370- /* Metadata write to trigger unclone in prologue */
371- * md = 42 ;
372- }
369+ if (meta_have + META_SIZE > eth )
370+ goto out ;
371+
372+ if (!check_metadata (meta_have ))
373+ goto out ;
374+
375+ /* Metadata write to trigger unclone in prologue */
376+ * meta_have = 42 ;
377+
378+ test_pass = true;
373379out :
374380 return TC_ACT_SHOT ;
375381}
376382
377383/*
378- * Check that skb_meta dynptr is writable but empty if prog writes to packet
379- * _payload_ using a dynptr slice. Applies only to cloned skbs .
384+ * Check that, when operating on a cloned packet, metadata remains intact if
385+ * prog creates a r/w slice to packet _payload_ .
380386 */
381387SEC ("tc" )
382- int clone_dynptr_empty_on_data_slice_write (struct __sk_buff * ctx )
388+ int clone_meta_dynptr_survives_data_slice_write (struct __sk_buff * ctx )
383389{
384390 struct bpf_dynptr data , meta ;
391+ __u8 meta_have [META_SIZE ];
385392 struct ethhdr * eth ;
386393
387394 bpf_dynptr_from_skb (ctx , 0 , & data );
@@ -392,29 +399,26 @@ int clone_dynptr_empty_on_data_slice_write(struct __sk_buff *ctx)
392399 if (eth -> h_proto != 0 )
393400 goto out ;
394401
395- /* Expect no metadata */
396402 bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
397- if (bpf_dynptr_is_rdonly (& meta ) || bpf_dynptr_size (& meta ) > 0 )
403+ bpf_dynptr_read (meta_have , META_SIZE , & meta , 0 , 0 );
404+ if (!check_metadata (meta_have ))
398405 goto out ;
399406
400- /* Packet write to trigger unclone in prologue */
401- eth -> h_proto = 42 ;
402-
403407 test_pass = true;
404408out :
405409 return TC_ACT_SHOT ;
406410}
407411
408412/*
409- * Check that skb_meta dynptr is writable but empty if prog writes to packet
410- * _metadata_ using a dynptr slice. Applies only to cloned skbs .
413+ * Check that, when operating on a cloned packet, metadata remains intact if
414+ * prog creates an r/w slice to packet _metadata_ .
411415 */
412416SEC ("tc" )
413- int clone_dynptr_empty_on_meta_slice_write (struct __sk_buff * ctx )
417+ int clone_meta_dynptr_survives_meta_slice_write (struct __sk_buff * ctx )
414418{
415419 struct bpf_dynptr data , meta ;
416420 const struct ethhdr * eth ;
417- __u8 * md ;
421+ __u8 * meta_have ;
418422
419423 bpf_dynptr_from_skb (ctx , 0 , & data );
420424 eth = bpf_dynptr_slice (& data , 0 , NULL , sizeof (* eth ));
@@ -424,31 +428,31 @@ int clone_dynptr_empty_on_meta_slice_write(struct __sk_buff *ctx)
424428 if (eth -> h_proto != 0 )
425429 goto out ;
426430
427- /* Expect no metadata */
428431 bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
429- if (bpf_dynptr_is_rdonly (& meta ) || bpf_dynptr_size (& meta ) > 0 )
432+ meta_have = bpf_dynptr_slice_rdwr (& meta , 0 , NULL , META_SIZE );
433+ if (!meta_have )
430434 goto out ;
431435
432- /* Metadata write to trigger unclone in prologue */
433- bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
434- md = bpf_dynptr_slice_rdwr (& meta , 0 , NULL , sizeof (* md ));
435- if (md )
436- * md = 42 ;
436+ if (!check_metadata (meta_have ))
437+ goto out ;
437438
438439 test_pass = true;
439440out :
440441 return TC_ACT_SHOT ;
441442}
442443
443444/*
444- * Check that skb_meta dynptr is read-only before prog writes to packet payload
445- * using dynptr_write helper. Applies only to cloned skbs.
445+ * Check that, when operating on a cloned packet, skb_meta dynptr is read-write
446+ * before prog writes to packet _payload_ using dynptr_write helper and metadata
447+ * remains intact before and after the write.
446448 */
447449SEC ("tc" )
448- int clone_dynptr_rdonly_before_data_dynptr_write (struct __sk_buff * ctx )
450+ int clone_meta_dynptr_rw_before_data_dynptr_write (struct __sk_buff * ctx )
449451{
450452 struct bpf_dynptr data , meta ;
453+ __u8 meta_have [META_SIZE ];
451454 const struct ethhdr * eth ;
455+ int err ;
452456
453457 bpf_dynptr_from_skb (ctx , 0 , & data );
454458 eth = bpf_dynptr_slice (& data , 0 , NULL , sizeof (* eth ));
@@ -458,17 +462,20 @@ int clone_dynptr_rdonly_before_data_dynptr_write(struct __sk_buff *ctx)
458462 if (eth -> h_proto != 0 )
459463 goto out ;
460464
461- /* Expect read-only metadata before unclone */
465+ /* Expect read-write metadata before unclone */
462466 bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
463- if (!bpf_dynptr_is_rdonly (& meta ) || bpf_dynptr_size (& meta ) != META_SIZE )
467+ if (bpf_dynptr_is_rdonly (& meta ))
468+ goto out ;
469+
470+ err = bpf_dynptr_read (meta_have , META_SIZE , & meta , 0 , 0 );
471+ if (err || !check_metadata (meta_have ))
464472 goto out ;
465473
466474 /* Helper write to payload will unclone the packet */
467475 bpf_dynptr_write (& data , offsetof(struct ethhdr , h_proto ), "x" , 1 , 0 );
468476
469- /* Expect no metadata after unclone */
470- bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
471- if (bpf_dynptr_is_rdonly (& meta ) || bpf_dynptr_size (& meta ) != 0 )
477+ err = bpf_dynptr_read (meta_have , META_SIZE , & meta , 0 , 0 );
478+ if (err || !check_metadata (meta_have ))
472479 goto out ;
473480
474481 test_pass = true;
@@ -477,14 +484,17 @@ int clone_dynptr_rdonly_before_data_dynptr_write(struct __sk_buff *ctx)
477484}
478485
479486/*
480- * Check that skb_meta dynptr is read-only if prog writes to packet
481- * metadata using dynptr_write helper. Applies only to cloned skbs.
487+ * Check that, when operating on a cloned packet, skb_meta dynptr is read-write
488+ * before prog writes to packet _metadata_ using dynptr_write helper and
489+ * metadata remains intact before and after the write.
482490 */
483491SEC ("tc" )
484- int clone_dynptr_rdonly_before_meta_dynptr_write (struct __sk_buff * ctx )
492+ int clone_meta_dynptr_rw_before_meta_dynptr_write (struct __sk_buff * ctx )
485493{
486494 struct bpf_dynptr data , meta ;
495+ __u8 meta_have [META_SIZE ];
487496 const struct ethhdr * eth ;
497+ int err ;
488498
489499 bpf_dynptr_from_skb (ctx , 0 , & data );
490500 eth = bpf_dynptr_slice (& data , 0 , NULL , sizeof (* eth ));
@@ -494,14 +504,20 @@ int clone_dynptr_rdonly_before_meta_dynptr_write(struct __sk_buff *ctx)
494504 if (eth -> h_proto != 0 )
495505 goto out ;
496506
497- /* Expect read-only metadata */
507+ /* Expect read-write metadata before unclone */
498508 bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
499- if (! bpf_dynptr_is_rdonly (& meta ) || bpf_dynptr_size ( & meta ) != META_SIZE )
509+ if (bpf_dynptr_is_rdonly (& meta ))
500510 goto out ;
501511
502- /* Metadata write. Expect failure. */
503- bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
504- if (bpf_dynptr_write (& meta , 0 , "x" , 1 , 0 ) != - EINVAL )
512+ err = bpf_dynptr_read (meta_have , META_SIZE , & meta , 0 , 0 );
513+ if (err || !check_metadata (meta_have ))
514+ goto out ;
515+
516+ /* Helper write to metadata will unclone the packet */
517+ bpf_dynptr_write (& meta , 0 , & meta_have [0 ], 1 , 0 );
518+
519+ err = bpf_dynptr_read (meta_have , META_SIZE , & meta , 0 , 0 );
520+ if (err || !check_metadata (meta_have ))
505521 goto out ;
506522
507523 test_pass = true;
0 commit comments