@@ -643,11 +643,14 @@ func TestProgramRejectIncorrectByteOrder(t *testing.T) {
643
643
}
644
644
}
645
645
646
+ // This uses unkeyed fields on purpose to force setting a non-zero value when
647
+ // a new field is added.
646
648
func TestProgramSpecCopy (t * testing.T ) {
647
649
a := & ProgramSpec {
648
650
"test" ,
649
651
1 ,
650
652
1 ,
653
+ 1 ,
651
654
"attach" ,
652
655
nil , // Can't copy Program
653
656
"section" ,
@@ -902,6 +905,35 @@ func TestProgramTargetsKernelModule(t *testing.T) {
902
905
qt .Assert (t , qt .IsTrue (ps .targetsKernelModule ()))
903
906
}
904
907
908
+ func TestProgramLoadBoundToDevice (t * testing.T ) {
909
+ testutils .SkipOnOldKernel (t , "6.3" , "device-bound XDP programs" )
910
+
911
+ ins := asm.Instructions {
912
+ asm .LoadImm (asm .R0 , 2 , asm .DWord ).WithSymbol ("out" ),
913
+ asm .Return (),
914
+ }
915
+
916
+ _ , err := NewProgram (& ProgramSpec {
917
+ Type : XDP ,
918
+ Ifindex : math .MaxUint32 ,
919
+ AttachType : AttachXDP ,
920
+ Instructions : ins ,
921
+ Flags : sys .BPF_F_XDP_DEV_BOUND_ONLY ,
922
+ License : "MIT" ,
923
+ })
924
+ testutils .SkipIfNotSupportedOnOS (t , err )
925
+
926
+ // Binding to loopback leads to crashes, yet is only explicitly disallowed
927
+ // since 3595599fa836 ("net: xdp: Disallow attaching device-bound programs in
928
+ // generic mode"). This only landed in 6.14 and returns EOPNOTSUPP.
929
+ //
930
+ // However, since attaching to loopback quietly succeeds on older kernels, use
931
+ // a non-existent ifindex to trigger EINVAL on all kernels. Without specifying
932
+ // ifindex, loading the program succeeds if the kernel knows the
933
+ // DEV_BOUND_ONLY flag.
934
+ qt .Assert (t , qt .ErrorIs (err , unix .EINVAL ))
935
+ }
936
+
905
937
func BenchmarkNewProgram (b * testing.B ) {
906
938
testutils .SkipOnOldKernel (b , "5.18" , "kfunc support" )
907
939
spec , err := LoadCollectionSpec (testutils .NativeFile (b , "testdata/kfunc-%s.elf" ))
0 commit comments