title: AF_XDP: invalid indirect read from stack
body: <p>I tried to implement the mapping I talked about in this post: <a href="https://stackoverflow.com/questions/60599317/af-xdp-map-src-ip-dst-ip-dst-port-to-index-to-bpf-map-type-xskmap?noredirect=1#comment107210482_60599317">AF_XDP: map `(SRC-IP, DST-IP, DST-Port)` to index to `BPF_MAP_TYPE_XSKMAP`</a></p>
  
  <p>My Kernelprogram has this map:</p>
  
  <pre><code>struct bpf_map_def SEC("maps") xdp_packet_mapping = {
      .type = BPF_MAP_TYPE_HASH,
      .key_size = sizeof(struct pckt_raw_idntfy),
      .value_size = sizeof(int),
      .max_entries = sizeof(int)
  };
  </code></pre>
  
  <p>with</p>
  
  <pre><code>struct pckt_raw_idntfy {
      int src_ip;
      int dst_ip;
      uint16_t dst_port;
  };
  </code></pre>
  
  <p>In the AF-XDP program I create a <code>pckt_raw_idntfy</code>-struct with the corresponding values of the packet which is currently processed as a key:</p>
  
  <pre><code>const struct pckt_raw_idntfy raw = {
      .src_ip = iph-&gt;saddr,
      .dst_ip = iph-&gt;daddr,
      .dst_port = udh-&gt;dest
  };
  </code></pre>
  
  <p>I then lookup the value in <code>xdp_packet_mapping</code> and redirect the packet into user-space in case the value exists:</p>
  
  <pre><code>void *ret = bpf_map_lookup_elem(&amp;xdp_packet_mapping, &amp;raw);
  if(ret) {
      const int *idx = (int*)(ret);
      if (bpf_map_lookup_elem(&amp;xsks_map, idx)) {
          return bpf_redirect_map(&amp;xsks_map, *idx, 0);
      }
  }
  </code></pre>
  
  <p>In user-space, I populate the map like this:</p>
  
  <pre><code>int find_map_fd(struct bpf_object *bpf_obj, const char *mapname) {
      struct bpf_map *map;
      int map_fd = -1;
  
      map = bpf_object__find_map_by_name(bpf_obj, mapname);
      if (!map) {
          fprintf(stderr, "ERR: cannot find map by name: %s\n", mapname);
          exit(1);
      } else {
          map_fd = bpf_map__fd(map);
      }
      return map_fd;
  }
  
  void populate_packet_mapping(struct bpf_object *bpf_obj) {
      const int xdp_packet_map_fd = find_map_fd(bpf_obj, "xdp_packet_mapping");
  
      for(uint16_t i = 0; i &lt; ip_addrs_size; i++) {
          const struct pckt_idntfy *pck_triple = ip_addrs[i];
          struct pckt_raw_idntfy *raw;
          pckt_idntfy_to_raw(pck_triple, raw);
  
          int ret = bpf_map_update_elem(xdp_packet_map_fd, raw, &amp;i, 0);
          if(ret == 0) {
              ;
          } else {
              fprintf(stderr, "Lookup elem for key %u failed!\n", i);
          }
      }
  }
  </code></pre>
  
  <p>Compilation works fine but if I try to execute the program (which loads the AF-XDP kernel program right after program start), I get this error:</p>
  
  <pre><code>libbpf: load bpf program failed: Permission denied
  libbpf: -- BEGIN DUMP LOG ---
  libbpf: 
  0: (b7) r6 = 2
  1: (61) r2 = *(u32 *)(r1 +4)
  2: (61) r1 = *(u32 *)(r1 +0)
  3: (bf) r3 = r1
  4: (07) r3 += 196
  5: (2d) if r3 &gt; r2 goto pc+49
   R1_w=pkt(id=0,off=0,r=196,imm=0) R2_w=pkt_end(id=0,off=0,imm=0) R3_w=pkt(id=0,off=196,r=196,imm=0) R6_w=inv2 R10=fp0
  6: (71) r3 = *(u8 *)(r1 +12)
  7: (71) r4 = *(u8 *)(r1 +13)
  8: (67) r4 &lt;&lt;= 8
  9: (4f) r4 |= r3
  10: (55) if r4 != 0x8 goto pc+44
   R1_w=pkt(id=0,off=0,r=196,imm=0) R2_w=pkt_end(id=0,off=0,imm=0) R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R4_w=inv8 R6_w=inv2 R10=fp0
  11: (bf) r3 = r1
  12: (07) r3 += 414
  13: (2d) if r3 &gt; r2 goto pc+41
   R1=pkt(id=0,off=0,r=414,imm=0) R2=pkt_end(id=0,off=0,imm=0) R3=pkt(id=0,off=414,r=414,imm=0) R4=inv8 R6=inv2 R10=fp0
  14: (71) r3 = *(u8 *)(r1 +23)
  15: (55) if r3 != 0x11 goto pc+39
   R1=pkt(id=0,off=0,r=414,imm=0) R2=pkt_end(id=0,off=0,imm=0) R3_w=inv17 R4=inv8 R6=inv2 R10=fp0
  16: (bf) r3 = r1
  17: (07) r3 += 14
  18: (71) r4 = *(u8 *)(r3 +0)
  19: (67) r4 &lt;&lt;= 2
  20: (57) r4 &amp;= 60
  21: (bf) r5 = r4
  22: (27) r5 *= 20
  23: (bf) r0 = r3
  24: (0f) r0 += r5
  last_idx 24 first_idx 13
  regs=20 stack=0 before 23: (bf) r0 = r3
  regs=20 stack=0 before 22: (27) r5 *= 20
  regs=20 stack=0 before 21: (bf) r5 = r4
  regs=10 stack=0 before 20: (57) r4 &amp;= 60
  regs=10 stack=0 before 19: (67) r4 &lt;&lt;= 2
  regs=10 stack=0 before 18: (71) r4 = *(u8 *)(r3 +0)
  25: (2d) if r0 &gt; r2 goto pc+29
   R0=pkt(id=1,off=14,r=14,umax_value=1200,var_off=(0x0; 0x7f0)) R1=pkt(id=0,off=0,r=414,imm=0) R2=pkt_end(id=0,off=0,imm=0) R3=pkt(id=0,off=14,r=414,imm=0) R4=inv(id=0,umax_value=60,var_off=(0x0; 0x3c)) R5=invP(id=0,umax_value=1200,var_off=(0x0; 0x7f0)) R6=inv2 R10=fp0
  26: (0f) r3 += r4
  last_idx 26 first_idx 25
  regs=10 stack=0 before 25: (2d) if r0 &gt; r2 goto pc+29
   R0_rw=pkt(id=1,off=14,r=0,umax_value=1200,var_off=(0x0; 0x7f0)) R1=pkt(id=0,off=0,r=414,imm=0) R2_r=pkt_end(id=0,off=0,imm=0) R3_rw=pkt(id=0,off=14,r=414,imm=0) R4_rw=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R5_w=invP(id=0,umax_value=1200,var_off=(0x0; 0x7f0)) R6=inv2 R10=fp0
  parent didn't have regs=10 stack=0 marks
  last_idx 24 first_idx 13
  regs=10 stack=0 before 24: (0f) r0 += r5
  regs=10 stack=0 before 23: (bf) r0 = r3
  regs=10 stack=0 before 22: (27) r5 *= 20
  regs=10 stack=0 before 21: (bf) r5 = r4
  regs=10 stack=0 before 20: (57) r4 &amp;= 60
  regs=10 stack=0 before 19: (67) r4 &lt;&lt;= 2
  regs=10 stack=0 before 18: (71) r4 = *(u8 *)(r3 +0)
  27: (bf) r4 = r3
  28: (07) r4 += 64
  29: (2d) if r4 &gt; r2 goto pc+25
   R0=pkt(id=1,off=14,r=14,umax_value=1200,var_off=(0x0; 0x7f0)) R1=pkt(id=0,off=0,r=414,imm=0) R2=pkt_end(id=0,off=0,imm=0) R3_w=pkt(id=2,off=14,r=78,umax_value=60,var_off=(0x0; 0x3c)) R4_w=pkt(id=2,off=78,r=78,umax_value=60,var_off=(0x0; 0x3c)) R5=invP(id=0,umax_value=1200,var_off=(0x0; 0x7f0)) R6=inv2 R10=fp0
  30: (61) r2 = *(u32 *)(r1 +26)
  31: (63) *(u32 *)(r10 -16) = r2
  32: (61) r1 = *(u32 *)(r1 +30)
  33: (63) *(u32 *)(r10 -12) = r1
  34: (69) r1 = *(u16 *)(r3 +2)
  35: (6b) *(u16 *)(r10 -8) = r1
  36: (bf) r2 = r10
  37: (07) r2 += -16
  38: (18) r1 = 0xffff915728bba000
  40: (85) call bpf_map_lookup_elem#1
  invalid indirect read from stack off -16+10 size 12
  processed 40 insns (limit 1000000) max_states_per_insn 0 total_states 2 peak_states 2 mark_read 1
  
  libbpf: -- END LOG --
  </code></pre>
  
  <p>Any ideas what I did wrong?</p>
  
  <p>Edit: Thanks to Qeole, defining the struct with padding solved the problem:</p>
  
  <pre><code>struct pckt_raw_idntfy {
      int src_ip;
      int dst_ip;
      uint16_t dst_port;
      uint16_t pad;
  };
  </code></pre>