@@ -28,6 +28,13 @@ struct {
2828
2929bool test_pass ;
3030
31+ static const __u8 meta_want [META_SIZE ] = {
32+ 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 ,
33+ 0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x16 , 0x17 , 0x18 ,
34+ 0x21 , 0x22 , 0x23 , 0x24 , 0x25 , 0x26 , 0x27 , 0x28 ,
35+ 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 ,
36+ };
37+
3138SEC ("tc" )
3239int ing_cls (struct __sk_buff * ctx )
3340{
@@ -304,12 +311,13 @@ int ing_xdp(struct xdp_md *ctx)
304311}
305312
306313/*
307- * Check that skb->data_meta..skb->data is empty if prog writes to packet
314+ * Check that skb->data_meta..skb->data is kept in tact if prog writes to packet
308315 * _payload_ using packet pointers. Applies only to cloned skbs.
309316 */
310317SEC ("tc" )
311- int clone_data_meta_empty_on_data_write (struct __sk_buff * ctx )
318+ int clone_data_meta_kept_on_data_write (struct __sk_buff * ctx )
312319{
320+ __u8 * meta_have = ctx_ptr (ctx , data_meta );
313321 struct ethhdr * eth = ctx_ptr (ctx , data );
314322
315323 if (eth + 1 > ctx_ptr (ctx , data_end ))
@@ -318,8 +326,10 @@ int clone_data_meta_empty_on_data_write(struct __sk_buff *ctx)
318326 if (eth -> h_proto != 0 )
319327 goto out ;
320328
321- /* Expect no metadata */
322- if (ctx -> data_meta != ctx -> data )
329+ if (meta_have + META_SIZE > eth )
330+ goto out ;
331+
332+ if (__builtin_memcmp (meta_want , meta_have , META_SIZE ))
323333 goto out ;
324334
325335 /* Packet write to trigger unclone in prologue */
@@ -331,40 +341,44 @@ int clone_data_meta_empty_on_data_write(struct __sk_buff *ctx)
331341}
332342
333343/*
334- * Check that skb->data_meta..skb->data is empty if prog writes to packet
344+ * Check that skb->data_meta..skb->data is kept in tact if prog writes to packet
335345 * _metadata_ using packet pointers. Applies only to cloned skbs.
336346 */
337347SEC ("tc" )
338- int clone_data_meta_empty_on_meta_write (struct __sk_buff * ctx )
348+ int clone_data_meta_kept_on_meta_write (struct __sk_buff * ctx )
339349{
350+ __u8 * meta_have = ctx_ptr (ctx , data_meta );
340351 struct ethhdr * eth = ctx_ptr (ctx , data );
341- __u8 * md = ctx_ptr (ctx , data_meta );
342352
343353 if (eth + 1 > ctx_ptr (ctx , data_end ))
344354 goto out ;
345355 /* Ignore non-test packets */
346356 if (eth -> h_proto != 0 )
347357 goto out ;
348358
349- if (md + 1 > ctx_ptr (ctx , data )) {
350- /* Expect no metadata */
351- test_pass = true;
352- } else {
353- /* Metadata write to trigger unclone in prologue */
354- * md = 42 ;
355- }
359+ if (meta_have + META_SIZE > eth )
360+ goto out ;
361+
362+ if (__builtin_memcmp (meta_want , meta_have , META_SIZE ))
363+ goto out ;
364+
365+ /* Metadata write to trigger unclone in prologue */
366+ * meta_have = 42 ;
367+
368+ test_pass = true;
356369out :
357370 return TC_ACT_SHOT ;
358371}
359372
360373/*
361- * Check that skb_meta dynptr is writable but empty if prog writes to packet
362- * _payload_ using a dynptr slice . Applies only to cloned skbs.
374+ * Check that skb_meta dynptr is writable and was kept in tact if prog creates a
375+ * r/w slice to packet _payload_ . Applies only to cloned skbs.
363376 */
364377SEC ("tc" )
365- int clone_dynptr_empty_on_data_slice_write (struct __sk_buff * ctx )
378+ int clone_dynptr_kept_on_data_slice_write (struct __sk_buff * ctx )
366379{
367380 struct bpf_dynptr data , meta ;
381+ __u8 meta_have [META_SIZE ];
368382 struct ethhdr * eth ;
369383
370384 bpf_dynptr_from_skb (ctx , 0 , & data );
@@ -375,29 +389,26 @@ int clone_dynptr_empty_on_data_slice_write(struct __sk_buff *ctx)
375389 if (eth -> h_proto != 0 )
376390 goto out ;
377391
378- /* Expect no metadata */
379392 bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
380- if (bpf_dynptr_is_rdonly (& meta ) || bpf_dynptr_size (& meta ) > 0 )
393+ bpf_dynptr_read (meta_have , META_SIZE , & meta , 0 , 0 );
394+ if (__builtin_memcmp (meta_want , meta_have , META_SIZE ))
381395 goto out ;
382396
383- /* Packet write to trigger unclone in prologue */
384- eth -> h_proto = 42 ;
385-
386397 test_pass = true;
387398out :
388399 return TC_ACT_SHOT ;
389400}
390401
391402/*
392- * Check that skb_meta dynptr is writable but empty if prog writes to packet
393- * _metadata_ using a dynptr slice . Applies only to cloned skbs.
403+ * Check that skb_meta dynptr is writable and was kept in tact if prog creates
404+ * an r/w slice to packet _metadata_ . Applies only to cloned skbs.
394405 */
395406SEC ("tc" )
396- int clone_dynptr_empty_on_meta_slice_write (struct __sk_buff * ctx )
407+ int clone_dynptr_kept_on_meta_slice_write (struct __sk_buff * ctx )
397408{
398409 struct bpf_dynptr data , meta ;
399410 const struct ethhdr * eth ;
400- __u8 * md ;
411+ __u8 * meta_have ;
401412
402413 bpf_dynptr_from_skb (ctx , 0 , & data );
403414 eth = bpf_dynptr_slice (& data , 0 , NULL , sizeof (* eth ));
@@ -407,16 +418,13 @@ int clone_dynptr_empty_on_meta_slice_write(struct __sk_buff *ctx)
407418 if (eth -> h_proto != 0 )
408419 goto out ;
409420
410- /* Expect no metadata */
411421 bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
412- if (bpf_dynptr_is_rdonly (& meta ) || bpf_dynptr_size (& meta ) > 0 )
422+ meta_have = bpf_dynptr_slice_rdwr (& meta , 0 , NULL , META_SIZE );
423+ if (!meta_have )
413424 goto out ;
414425
415- /* Metadata write to trigger unclone in prologue */
416- bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
417- md = bpf_dynptr_slice_rdwr (& meta , 0 , NULL , sizeof (* md ));
418- if (md )
419- * md = 42 ;
426+ if (__builtin_memcmp (meta_want , meta_have , META_SIZE ))
427+ goto out ;
420428
421429 test_pass = true;
422430out :
@@ -425,12 +433,14 @@ int clone_dynptr_empty_on_meta_slice_write(struct __sk_buff *ctx)
425433
426434/*
427435 * Check that skb_meta dynptr is read-only before prog writes to packet payload
428- * using dynptr_write helper. Applies only to cloned skbs.
436+ * using dynptr_write helper, and becomes read-write afterwards. Applies only to
437+ * cloned skbs.
429438 */
430439SEC ("tc" )
431- int clone_dynptr_rdonly_before_data_dynptr_write (struct __sk_buff * ctx )
440+ int clone_dynptr_rdonly_before_data_dynptr_write_then_rw (struct __sk_buff * ctx )
432441{
433442 struct bpf_dynptr data , meta ;
443+ __u8 meta_have [META_SIZE ];
434444 const struct ethhdr * eth ;
435445
436446 bpf_dynptr_from_skb (ctx , 0 , & data );
@@ -443,15 +453,23 @@ int clone_dynptr_rdonly_before_data_dynptr_write(struct __sk_buff *ctx)
443453
444454 /* Expect read-only metadata before unclone */
445455 bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
446- if (!bpf_dynptr_is_rdonly (& meta ) || bpf_dynptr_size (& meta ) != META_SIZE )
456+ if (!bpf_dynptr_is_rdonly (& meta ))
457+ goto out ;
458+
459+ bpf_dynptr_read (meta_have , META_SIZE , & meta , 0 , 0 );
460+ if (__builtin_memcmp (meta_want , meta_have , META_SIZE ))
447461 goto out ;
448462
449463 /* Helper write to payload will unclone the packet */
450464 bpf_dynptr_write (& data , offsetof(struct ethhdr , h_proto ), "x" , 1 , 0 );
451465
452- /* Expect no metadata after unclone */
466+ /* Expect r/w metadata after unclone */
453467 bpf_dynptr_from_skb_meta (ctx , 0 , & meta );
454- if (bpf_dynptr_is_rdonly (& meta ) || bpf_dynptr_size (& meta ) != 0 )
468+ if (bpf_dynptr_is_rdonly (& meta ))
469+ goto out ;
470+
471+ bpf_dynptr_read (meta_have , META_SIZE , & meta , 0 , 0 );
472+ if (__builtin_memcmp (meta_want , meta_have , META_SIZE ))
455473 goto out ;
456474
457475 test_pass = true;
0 commit comments