1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <unistd.h> 6 #include <test_progs.h> 7 8 __u32 get_map_id(struct bpf_object *obj, const char *name) 9 { 10 struct bpf_map_info map_info = {}; 11 __u32 map_info_len, duration = 0; 12 struct bpf_map *map; 13 int err; 14 15 map_info_len = sizeof(map_info); 16 17 map = bpf_object__find_map_by_name(obj, name); 18 if (CHECK(!map, "find map", "NULL map")) 19 return 0; 20 21 err = bpf_obj_get_info_by_fd(bpf_map__fd(map), 22 &map_info, &map_info_len); 23 CHECK(err, "get map info", "err %d errno %d", err, errno); 24 return map_info.id; 25 } 26 27 void test_pinning(void) 28 { 29 const char *file_invalid = "./test_pinning_invalid.o"; 30 const char *custpinpath = "/sys/fs/bpf/custom/pinmap"; 31 const char *nopinpath = "/sys/fs/bpf/nopinmap"; 32 const char *nopinpath2 = "/sys/fs/bpf/nopinmap2"; 33 const char *custpath = "/sys/fs/bpf/custom"; 34 const char *pinpath = "/sys/fs/bpf/pinmap"; 35 const char *file = "./test_pinning.o"; 36 __u32 map_id, map_id2, duration = 0; 37 struct stat statbuf = {}; 38 struct bpf_object *obj; 39 struct bpf_map *map; 40 int err, map_fd; 41 DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts, 42 .pin_root_path = custpath, 43 ); 44 45 /* check that opening fails with invalid pinning value in map def */ 46 obj = bpf_object__open_file(file_invalid, NULL); 47 err = libbpf_get_error(obj); 48 if (CHECK(err != -EINVAL, "invalid open", "err %d errno %d\n", err, errno)) { 49 obj = NULL; 50 goto out; 51 } 52 53 /* open the valid object file */ 54 obj = bpf_object__open_file(file, NULL); 55 err = libbpf_get_error(obj); 56 if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) { 57 obj = NULL; 58 goto out; 59 } 60 61 err = bpf_object__load(obj); 62 if (CHECK(err, "default load", "err %d errno %d\n", err, errno)) 63 goto out; 64 65 /* check that pinmap was pinned */ 66 err = stat(pinpath, &statbuf); 67 if (CHECK(err, "stat pinpath", "err %d errno %d\n", err, errno)) 68 goto out; 69 70 /* check that nopinmap was *not* pinned */ 71 err = stat(nopinpath, &statbuf); 72 if (CHECK(!err || errno != ENOENT, "stat nopinpath", 73 "err %d errno %d\n", err, errno)) 74 goto out; 75 76 /* check that nopinmap2 was *not* pinned */ 77 err = stat(nopinpath2, &statbuf); 78 if (CHECK(!err || errno != ENOENT, "stat nopinpath2", 79 "err %d errno %d\n", err, errno)) 80 goto out; 81 82 map_id = get_map_id(obj, "pinmap"); 83 if (!map_id) 84 goto out; 85 86 bpf_object__close(obj); 87 88 obj = bpf_object__open_file(file, NULL); 89 if (CHECK_FAIL(libbpf_get_error(obj))) { 90 obj = NULL; 91 goto out; 92 } 93 94 err = bpf_object__load(obj); 95 if (CHECK(err, "default load", "err %d errno %d\n", err, errno)) 96 goto out; 97 98 /* check that same map ID was reused for second load */ 99 map_id2 = get_map_id(obj, "pinmap"); 100 if (CHECK(map_id != map_id2, "check reuse", 101 "err %d errno %d id %d id2 %d\n", err, errno, map_id, map_id2)) 102 goto out; 103 104 /* should be no-op to re-pin same map */ 105 map = bpf_object__find_map_by_name(obj, "pinmap"); 106 if (CHECK(!map, "find map", "NULL map")) 107 goto out; 108 109 err = bpf_map__pin(map, NULL); 110 if (CHECK(err, "re-pin map", "err %d errno %d\n", err, errno)) 111 goto out; 112 113 /* but error to pin at different location */ 114 err = bpf_map__pin(map, "/sys/fs/bpf/other"); 115 if (CHECK(!err, "pin map different", "err %d errno %d\n", err, errno)) 116 goto out; 117 118 /* unpin maps with a pin_path set */ 119 err = bpf_object__unpin_maps(obj, NULL); 120 if (CHECK(err, "unpin maps", "err %d errno %d\n", err, errno)) 121 goto out; 122 123 /* and re-pin them... */ 124 err = bpf_object__pin_maps(obj, NULL); 125 if (CHECK(err, "pin maps", "err %d errno %d\n", err, errno)) 126 goto out; 127 128 /* set pinning path of other map and re-pin all */ 129 map = bpf_object__find_map_by_name(obj, "nopinmap"); 130 if (CHECK(!map, "find map", "NULL map")) 131 goto out; 132 133 err = bpf_map__set_pin_path(map, custpinpath); 134 if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno)) 135 goto out; 136 137 /* should only pin the one unpinned map */ 138 err = bpf_object__pin_maps(obj, NULL); 139 if (CHECK(err, "pin maps", "err %d errno %d\n", err, errno)) 140 goto out; 141 142 /* check that nopinmap was pinned at the custom path */ 143 err = stat(custpinpath, &statbuf); 144 if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno)) 145 goto out; 146 147 /* remove the custom pin path to re-test it with auto-pinning below */ 148 err = unlink(custpinpath); 149 if (CHECK(err, "unlink custpinpath", "err %d errno %d\n", err, errno)) 150 goto out; 151 152 err = rmdir(custpath); 153 if (CHECK(err, "rmdir custpindir", "err %d errno %d\n", err, errno)) 154 goto out; 155 156 bpf_object__close(obj); 157 158 /* open the valid object file again */ 159 obj = bpf_object__open_file(file, NULL); 160 err = libbpf_get_error(obj); 161 if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) { 162 obj = NULL; 163 goto out; 164 } 165 166 /* set pin paths so that nopinmap2 will attempt to reuse the map at 167 * pinpath (which will fail), but not before pinmap has already been 168 * reused 169 */ 170 bpf_object__for_each_map(map, obj) { 171 if (!strcmp(bpf_map__name(map), "nopinmap")) 172 err = bpf_map__set_pin_path(map, nopinpath2); 173 else if (!strcmp(bpf_map__name(map), "nopinmap2")) 174 err = bpf_map__set_pin_path(map, pinpath); 175 else 176 continue; 177 178 if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno)) 179 goto out; 180 } 181 182 /* should fail because of map parameter mismatch */ 183 err = bpf_object__load(obj); 184 if (CHECK(err != -EINVAL, "param mismatch load", "err %d errno %d\n", err, errno)) 185 goto out; 186 187 /* nopinmap2 should have been pinned and cleaned up again */ 188 err = stat(nopinpath2, &statbuf); 189 if (CHECK(!err || errno != ENOENT, "stat nopinpath2", 190 "err %d errno %d\n", err, errno)) 191 goto out; 192 193 /* pinmap should still be there */ 194 err = stat(pinpath, &statbuf); 195 if (CHECK(err, "stat pinpath", "err %d errno %d\n", err, errno)) 196 goto out; 197 198 bpf_object__close(obj); 199 200 /* test auto-pinning at custom path with open opt */ 201 obj = bpf_object__open_file(file, &opts); 202 if (CHECK_FAIL(libbpf_get_error(obj))) { 203 obj = NULL; 204 goto out; 205 } 206 207 err = bpf_object__load(obj); 208 if (CHECK(err, "custom load", "err %d errno %d\n", err, errno)) 209 goto out; 210 211 /* check that pinmap was pinned at the custom path */ 212 err = stat(custpinpath, &statbuf); 213 if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno)) 214 goto out; 215 216 /* remove the custom pin path to re-test it with reuse fd below */ 217 err = unlink(custpinpath); 218 if (CHECK(err, "unlink custpinpath", "err %d errno %d\n", err, errno)) 219 goto out; 220 221 err = rmdir(custpath); 222 if (CHECK(err, "rmdir custpindir", "err %d errno %d\n", err, errno)) 223 goto out; 224 225 bpf_object__close(obj); 226 227 /* test pinning at custom path with reuse fd */ 228 obj = bpf_object__open_file(file, NULL); 229 err = libbpf_get_error(obj); 230 if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) { 231 obj = NULL; 232 goto out; 233 } 234 235 map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(__u32), 236 sizeof(__u64), 1, 0); 237 if (CHECK(map_fd < 0, "create pinmap manually", "fd %d\n", map_fd)) 238 goto out; 239 240 map = bpf_object__find_map_by_name(obj, "pinmap"); 241 if (CHECK(!map, "find map", "NULL map")) 242 goto close_map_fd; 243 244 err = bpf_map__reuse_fd(map, map_fd); 245 if (CHECK(err, "reuse pinmap fd", "err %d errno %d\n", err, errno)) 246 goto close_map_fd; 247 248 err = bpf_map__set_pin_path(map, custpinpath); 249 if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno)) 250 goto close_map_fd; 251 252 err = bpf_object__load(obj); 253 if (CHECK(err, "custom load", "err %d errno %d\n", err, errno)) 254 goto close_map_fd; 255 256 /* check that pinmap was pinned at the custom path */ 257 err = stat(custpinpath, &statbuf); 258 if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno)) 259 goto close_map_fd; 260 261 close_map_fd: 262 close(map_fd); 263 out: 264 unlink(pinpath); 265 unlink(nopinpath); 266 unlink(nopinpath2); 267 unlink(custpinpath); 268 rmdir(custpath); 269 if (obj) 270 bpf_object__close(obj); 271 } 272