1
0

torture.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /* Torture fixture for the C kernel walker (R7a) — exercises every c-path
  2. * branch of the checklist: fn-ptr tables, typedef enum/struct, file-scope
  3. * consts incl. multi-declarator, the macro-prototype misparse skip,
  4. * value-refs (+ shadow prune), the leading-attr-macro preParse blank, and
  5. * the C call shapes. Must parse ERROR-FREE post-preParse or the kernel arm
  6. * defers. */
  7. #include <stdio.h>
  8. #include <sys/socket.h>
  9. #include "local_ops.h"
  10. /** Retry budget for the poller. */
  11. static const int MAX_RETRIES = 3;
  12. static const int LOW_WATER = 2, HIGH_WATER = 8;
  13. static int counter = 0;
  14. static const char *BANNER = "torture";
  15. /* Bare identifier declarators are the macro-prototype misparse shape and are
  16. * skipped by design (uninit scalars are the accepted loss). */
  17. int bare_global;
  18. MYLIB_API config_handle;
  19. /* Leading attribute macro — blanked by preParseCSource (#1211), so the real
  20. * name survives on both arms. */
  21. SEC_ATTR UINT32 masked_entry(VOID) { return 0; }
  22. typedef enum { STATE_IDLE, STATE_RUNNING, STATE_DONE } run_state_t;
  23. typedef struct {
  24. int fd;
  25. void (*on_recv)(int);
  26. } conn_t;
  27. typedef struct conn_pool conn_pool_t;
  28. typedef int (*cb_t)(int);
  29. enum wire_flags { WIRE_A = 1, WIRE_B = 2 };
  30. struct packet {
  31. int len;
  32. unsigned char body[64];
  33. struct packet *next;
  34. cb_t *async_cb;
  35. };
  36. /** Sum helper (docstring). */
  37. static int add(int a, int b) { return a + b; }
  38. static int cb_a(int x) { return add(x, 1); }
  39. static int cb_b(int x) { return add(x, 2); }
  40. /* fn-ptr table at file scope — the ungated 'list' capture positions. */
  41. static cb_t DISPATCH_TABLE[] = { cb_a, cb_b };
  42. static void handle_recv(int fd);
  43. /* struct initializer — the ungated 'value' capture positions. */
  44. static const struct handler_ops OPS = { .recv = handle_recv, .flags = WIRE_A };
  45. static void handle_recv(int fd) {
  46. struct packet pkt;
  47. pkt.len = fd;
  48. printf("fd=%d retries=%d\n", fd, MAX_RETRIES);
  49. }
  50. /* Local shadow of a file-scope const — the shadow prune drops HIGH_WATER as a
  51. * value-ref target while LOW_WATER stays live. */
  52. static int shadowed_reader(void) {
  53. int HIGH_WATER = 99;
  54. return HIGH_WATER + LOW_WATER;
  55. }
  56. static int use_table(int idx, int v) {
  57. cb_t fn = DISPATCH_TABLE[idx];
  58. int r = (*fn)(v);
  59. conn_t c = { 1, 0 };
  60. c.on_recv(r);
  61. return counter + r;
  62. }
  63. static void spawn_workers(void) {
  64. register_handler(cb_a);
  65. signal_connect(&cb_b);
  66. }
  67. /* ---- deferral round 2 (the linux-idiom preParse family) --------------------
  68. * Every shape below used to drop the WHOLE file into error recovery (and
  69. * therefore defer it to wasm). Each now parses via a round-2 blank/rewrite;
  70. * this section pins kernel-vs-wasm parity on all of them at once. */
  71. /* file-scope prefixed declaration macros — whole-line blank */
  72. static DEFINE_PER_CPU(struct llist_head, rstat_backlog_list);
  73. static DECLARE_WORK(init_free_wq, do_free_init);
  74. extern DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
  75. /* initialized per-cpu declaration — the REWRITE (type + name survive) */
  76. static DEFINE_PER_CPU(struct conn, cpuhp_state) = {
  77. .fd = 1,
  78. };
  79. /* type-keyword arguments — keyword (and trailing stars) blank */
  80. static void type_args(void *head, void *map) {
  81. void *opts = kzalloc_obj(struct conn);
  82. void *entry = list_first_entry(head,
  83. struct conn, fd);
  84. void *outer = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(head)),
  85. struct conn, fd);
  86. use_ptr(outer, container_of(map, struct conn, fd));
  87. use_ptr(opts, entry);
  88. }
  89. DEFINE_PER_CPU(struct conn *, ksoftirqd);
  90. /* parameterized annotations — name+args blank whole */
  91. static void cleanup_scope(void) {
  92. struct conn *token __free(kfree) = NULL;
  93. use_ptr(token, token);
  94. }
  95. static void __printf(1, 2) log_fmt(const char *fmt, ...);
  96. struct flex_tail {
  97. int count;
  98. int owners[] __counted_by(count);
  99. };
  100. /* sandwiched lowercase annotations + C23 auto */
  101. static notrace void tick_do(int x) { use_val(x); }
  102. static nokprobe_inline void arm_probe(void) { }
  103. static void auto_user(void) {
  104. auto hb = shadowed_reader();
  105. use_val(hb);
  106. }
  107. /* va_arg with a qualified type argument */
  108. static void drain_args(va_list ap) {
  109. const char *s = va_arg(ap, const char *);
  110. int n = va_arg(ap, int);
  111. use_ptr((void *)s, (void *)(long)n);
  112. }
  113. /* multi-line statement-position iterator macro */
  114. static void walk_rcu(void *head) {
  115. hlist_for_each_entry_rcu(pos, head, hlist,
  116. lockdep_is_held(&probe_mutex)) {
  117. use_ptr(pos, head);
  118. }
  119. }
  120. /* GNU named-variadic define — dots blank, body survives */
  121. #define verbose(env, fmt, args...) log_writer(env, fmt, ##args)
  122. /* block-scope prefixed declaration macro */
  123. static void ratelimited_warn(void) {
  124. static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5);
  125. use_ptr(&ratelimit, 0);
  126. }