SEC("?tc")
__failure __msg("arg#0 doesn't point to an irq flag on stack") int irq_save_bad_arg(struct __sk_buff *ctx)
{
bpf_local_irq_save(&global_flags); return 0;
}
SEC("?tc")
__failure __msg("arg#0 doesn't point to an irq flag on stack") int irq_restore_bad_arg(struct __sk_buff *ctx)
{
bpf_local_irq_restore(&global_flags); return 0;
}
SEC("?tc")
__failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region") int irq_restore_missing_2(struct __sk_buff *ctx)
{ unsignedlong flags1; unsignedlong flags2;
SEC("?tc")
__failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region") int irq_restore_missing_3(struct __sk_buff *ctx)
{ unsignedlong flags1; unsignedlong flags2; unsignedlong flags3;
SEC("?tc")
__failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region") int irq_restore_missing_3_minus_2(struct __sk_buff *ctx)
{ unsignedlong flags1; unsignedlong flags2; unsignedlong flags3;
SEC("?tc")
__failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region") int irq_restore_missing_1_subprog(struct __sk_buff *ctx)
{ unsignedlong flags;
local_irq_save(&flags); return 0;
}
SEC("?tc")
__failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region") int irq_restore_missing_2_subprog(struct __sk_buff *ctx)
{ unsignedlong flags1; unsignedlong flags2;
SEC("?tc")
__failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region") int irq_restore_missing_3_subprog(struct __sk_buff *ctx)
{ unsignedlong flags1; unsignedlong flags2; unsignedlong flags3;
SEC("?tc")
__failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region") int irq_restore_missing_3_minus_2_subprog(struct __sk_buff *ctx)
{ unsignedlong flags1; unsignedlong flags2; unsignedlong flags3;
SEC("?tc")
__failure __msg("cannot restore irq state out of order") int irq_restore_ooo(struct __sk_buff *ctx)
{ unsignedlong flags1; unsignedlong flags2;
SEC("?tc")
__failure __msg("cannot restore irq state out of order") int irq_restore_ooo_3(struct __sk_buff *ctx)
{ unsignedlong flags1; unsignedlong flags2; unsignedlong flags3;
SEC("?tc")
__failure __msg("cannot restore irq state out of order") int irq_restore_ooo_3_subprog(struct __sk_buff *ctx)
{ unsignedlong flags1; unsignedlong flags2; unsignedlong flags3;
/* Ensure same sized slot has st->ref_obj_id set, so we reject based on * slot_type != STACK_IRQ_FLAG...
*/
_Static_assert(sizeof(it) == sizeof(unsignedlong), "broken iterator size");
SEC("?tc")
__failure __msg("cannot restore irq state out of order") int irq_ooo_refs_array(struct __sk_buff *ctx)
{ unsignedlong flags[4]; struct { int i; } *p;
/* refs=1 */
bpf_local_irq_save(&flags[0]);
/* refs=1,2 */
p = bpf_obj_new(typeof(*p)); if (!p) {
bpf_local_irq_restore(&flags[0]); return 0;
}
/* refs=1,2,3 */
bpf_local_irq_save(&flags[1]);
/* refs=1,2,3,4 */
bpf_local_irq_save(&flags[2]);
/* Now when we remove ref=2, the verifier must not break the ordering in * the refs array between 1,3,4. With an older implementation, the * verifier would swap the last element with the removed element, but to * maintain the stack property we need to use memmove.
*/
bpf_obj_drop(p);
/* Save and restore to reset active_irq_id to 3, as the ordering is now * refs=1,4,3. When restoring the linear scan will find prev_id in order * as 3 instead of 4.
*/
bpf_local_irq_save(&flags[3]);
bpf_local_irq_restore(&flags[3]);
/* With the incorrect implementation, we can release flags[1], flags[2], * and flags[0], i.e. in the wrong order.
*/
bpf_local_irq_restore(&flags[1]);
bpf_local_irq_restore(&flags[2]);
bpf_local_irq_restore(&flags[0]); return 0;
}
int __noinline
global_subprog(int i)
{ if (i)
bpf_printk("%p", &i); return i;
}
int __noinline
global_sleepable_helper_subprog(int i)
{ if (i)
bpf_copy_from_user(&i, sizeof(i), NULL); return i;
}
int __noinline
global_sleepable_kfunc_subprog(int i)
{ if (i)
bpf_copy_from_user_str(&i, sizeof(i), NULL, 0);
global_subprog(i); return i;
}
int __noinline
global_subprog_calling_sleepable_global(int i)
{ if (!i)
global_sleepable_kfunc_subprog(i); return i;
}
SEC("?syscall")
__success int irq_non_sleepable_global_subprog(void *ctx)
{ unsignedlong flags;
SEC("?syscall")
__failure __msg("global functions that may sleep are not allowed in non-sleepable context") int irq_sleepable_helper_global_subprog(void *ctx)
{ unsignedlong flags;
SEC("?syscall")
__failure __msg("global functions that may sleep are not allowed in non-sleepable context") int irq_sleepable_global_subprog_indirect(void *ctx)
{ unsignedlong flags;
SEC("?tc")
__failure __msg("function calls are not allowed") int irq_wrong_kfunc_class_1(struct __sk_buff *ctx)
{ unsignedlong flags1;
if (bpf_res_spin_lock_irqsave(&lockA, &flags1)) return 0; /* For now, bpf_local_irq_restore is not allowed in critical section, * but this test ensures error will be caught with kfunc_class when it's * opened up. Tested by temporarily permitting this kfunc in critical * section.
*/
bpf_local_irq_restore(&flags1);
bpf_res_spin_unlock_irqrestore(&lockA, &flags1); return 0;
}
SEC("?tc")
__failure __msg("function calls are not allowed") int irq_wrong_kfunc_class_2(struct __sk_buff *ctx)
{ unsignedlong flags1, flags2;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.