1 // SPDX-License-Identifier: GPL-2.0 2 #include "util.h" 3 #include "debug.h" 4 #include "event.h" 5 #include "namespaces.h" 6 #include <api/fs/fs.h> 7 #include <sys/mman.h> 8 #include <sys/stat.h> 9 #include <sys/utsname.h> 10 #include <dirent.h> 11 #include <fcntl.h> 12 #include <inttypes.h> 13 #include <signal.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <errno.h> 18 #include <limits.h> 19 #include <linux/capability.h> 20 #include <linux/kernel.h> 21 #include <linux/log2.h> 22 #include <linux/time64.h> 23 #include <unistd.h> 24 #include "cap.h" 25 #include "strlist.h" 26 #include "string2.h" 27 28 /* 29 * XXX We need to find a better place for these things... 30 */ 31 32 bool perf_singlethreaded = true; 33 34 void perf_set_singlethreaded(void) 35 { 36 perf_singlethreaded = true; 37 } 38 39 void perf_set_multithreaded(void) 40 { 41 perf_singlethreaded = false; 42 } 43 44 unsigned int page_size; 45 46 int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; 47 int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK; 48 49 int sysctl__max_stack(void) 50 { 51 int value; 52 53 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) 54 sysctl_perf_event_max_stack = value; 55 56 if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0) 57 sysctl_perf_event_max_contexts_per_stack = value; 58 59 return sysctl_perf_event_max_stack; 60 } 61 62 bool test_attr__enabled; 63 64 bool perf_host = true; 65 bool perf_guest = false; 66 67 void event_attr_init(struct perf_event_attr *attr) 68 { 69 if (!perf_host) 70 attr->exclude_host = 1; 71 if (!perf_guest) 72 attr->exclude_guest = 1; 73 /* to capture ABI version */ 74 attr->size = sizeof(*attr); 75 } 76 77 int mkdir_p(char *path, mode_t mode) 78 { 79 struct stat st; 80 int err; 81 char *d = path; 82 83 if (*d != '/') 84 return -1; 85 86 if (stat(path, &st) == 0) 87 return 0; 88 89 while (*++d == '/'); 90 91 while ((d = strchr(d, '/'))) { 92 *d = '\0'; 93 err = stat(path, &st) && mkdir(path, mode); 94 *d++ = '/'; 95 if (err) 96 return -1; 97 while (*d == '/') 98 ++d; 99 } 100 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 101 } 102 103 static bool match_pat(char *file, const char **pat) 104 { 105 int i = 0; 106 107 if (!pat) 108 return true; 109 110 while (pat[i]) { 111 if (strglobmatch(file, pat[i])) 112 return true; 113 114 i++; 115 } 116 117 return false; 118 } 119 120 /* 121 * The depth specify how deep the removal will go. 122 * 0 - will remove only files under the 'path' directory 123 * 1 .. x - will dive in x-level deep under the 'path' directory 124 * 125 * If specified the pat is array of string patterns ended with NULL, 126 * which are checked upon every file/directory found. Only matching 127 * ones are removed. 128 * 129 * The function returns: 130 * 0 on success 131 * -1 on removal failure with errno set 132 * -2 on pattern failure 133 */ 134 static int rm_rf_depth_pat(const char *path, int depth, const char **pat) 135 { 136 DIR *dir; 137 int ret; 138 struct dirent *d; 139 char namebuf[PATH_MAX]; 140 struct stat statbuf; 141 142 /* Do not fail if there's no file. */ 143 ret = lstat(path, &statbuf); 144 if (ret) 145 return 0; 146 147 /* Try to remove any file we get. */ 148 if (!(statbuf.st_mode & S_IFDIR)) 149 return unlink(path); 150 151 /* We have directory in path. */ 152 dir = opendir(path); 153 if (dir == NULL) 154 return -1; 155 156 while ((d = readdir(dir)) != NULL && !ret) { 157 158 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) 159 continue; 160 161 if (!match_pat(d->d_name, pat)) 162 return -2; 163 164 scnprintf(namebuf, sizeof(namebuf), "%s/%s", 165 path, d->d_name); 166 167 /* We have to check symbolic link itself */ 168 ret = lstat(namebuf, &statbuf); 169 if (ret < 0) { 170 pr_debug("stat failed: %s\n", namebuf); 171 break; 172 } 173 174 if (S_ISDIR(statbuf.st_mode)) 175 ret = depth ? rm_rf_depth_pat(namebuf, depth - 1, pat) : 0; 176 else 177 ret = unlink(namebuf); 178 } 179 closedir(dir); 180 181 if (ret < 0) 182 return ret; 183 184 return rmdir(path); 185 } 186 187 int rm_rf_perf_data(const char *path) 188 { 189 const char *pat[] = { 190 "header", 191 "data.*", 192 NULL, 193 }; 194 195 return rm_rf_depth_pat(path, 0, pat); 196 } 197 198 int rm_rf(const char *path) 199 { 200 return rm_rf_depth_pat(path, INT_MAX, NULL); 201 } 202 203 /* A filter which removes dot files */ 204 bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d) 205 { 206 return d->d_name[0] != '.'; 207 } 208 209 /* lsdir reads a directory and store it in strlist */ 210 struct strlist *lsdir(const char *name, 211 bool (*filter)(const char *, struct dirent *)) 212 { 213 struct strlist *list = NULL; 214 DIR *dir; 215 struct dirent *d; 216 217 dir = opendir(name); 218 if (!dir) 219 return NULL; 220 221 list = strlist__new(NULL, NULL); 222 if (!list) { 223 errno = ENOMEM; 224 goto out; 225 } 226 227 while ((d = readdir(dir)) != NULL) { 228 if (!filter || filter(name, d)) 229 strlist__add(list, d->d_name); 230 } 231 232 out: 233 closedir(dir); 234 return list; 235 } 236 237 static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi) 238 { 239 int err = -1; 240 char *line = NULL; 241 size_t n; 242 FILE *from_fp, *to_fp; 243 struct nscookie nsc; 244 245 nsinfo__mountns_enter(nsi, &nsc); 246 from_fp = fopen(from, "r"); 247 nsinfo__mountns_exit(&nsc); 248 if (from_fp == NULL) 249 goto out; 250 251 to_fp = fopen(to, "w"); 252 if (to_fp == NULL) 253 goto out_fclose_from; 254 255 while (getline(&line, &n, from_fp) > 0) 256 if (fputs(line, to_fp) == EOF) 257 goto out_fclose_to; 258 err = 0; 259 out_fclose_to: 260 fclose(to_fp); 261 free(line); 262 out_fclose_from: 263 fclose(from_fp); 264 out: 265 return err; 266 } 267 268 int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) 269 { 270 void *ptr; 271 loff_t pgoff; 272 273 pgoff = off_in & ~(page_size - 1); 274 off_in -= pgoff; 275 276 ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff); 277 if (ptr == MAP_FAILED) 278 return -1; 279 280 while (size) { 281 ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out); 282 if (ret < 0 && errno == EINTR) 283 continue; 284 if (ret <= 0) 285 break; 286 287 size -= ret; 288 off_in += ret; 289 off_out += ret; 290 } 291 munmap(ptr, off_in + size); 292 293 return size ? -1 : 0; 294 } 295 296 static int copyfile_mode_ns(const char *from, const char *to, mode_t mode, 297 struct nsinfo *nsi) 298 { 299 int fromfd, tofd; 300 struct stat st; 301 int err; 302 char *tmp = NULL, *ptr = NULL; 303 struct nscookie nsc; 304 305 nsinfo__mountns_enter(nsi, &nsc); 306 err = stat(from, &st); 307 nsinfo__mountns_exit(&nsc); 308 if (err) 309 goto out; 310 err = -1; 311 312 /* extra 'x' at the end is to reserve space for '.' */ 313 if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) { 314 tmp = NULL; 315 goto out; 316 } 317 ptr = strrchr(tmp, '/'); 318 if (!ptr) 319 goto out; 320 ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1); 321 *ptr = '.'; 322 323 tofd = mkstemp(tmp); 324 if (tofd < 0) 325 goto out; 326 327 if (fchmod(tofd, mode)) 328 goto out_close_to; 329 330 if (st.st_size == 0) { /* /proc? do it slowly... */ 331 err = slow_copyfile(from, tmp, nsi); 332 goto out_close_to; 333 } 334 335 nsinfo__mountns_enter(nsi, &nsc); 336 fromfd = open(from, O_RDONLY); 337 nsinfo__mountns_exit(&nsc); 338 if (fromfd < 0) 339 goto out_close_to; 340 341 err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size); 342 343 close(fromfd); 344 out_close_to: 345 close(tofd); 346 if (!err) 347 err = link(tmp, to); 348 unlink(tmp); 349 out: 350 free(tmp); 351 return err; 352 } 353 354 int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi) 355 { 356 return copyfile_mode_ns(from, to, 0755, nsi); 357 } 358 359 int copyfile_mode(const char *from, const char *to, mode_t mode) 360 { 361 return copyfile_mode_ns(from, to, mode, NULL); 362 } 363 364 int copyfile(const char *from, const char *to) 365 { 366 return copyfile_mode(from, to, 0755); 367 } 368 369 size_t hex_width(u64 v) 370 { 371 size_t n = 1; 372 373 while ((v >>= 4)) 374 ++n; 375 376 return n; 377 } 378 379 int perf_event_paranoid(void) 380 { 381 int value; 382 383 if (sysctl__read_int("kernel/perf_event_paranoid", &value)) 384 return INT_MAX; 385 386 return value; 387 } 388 389 bool perf_event_paranoid_check(int max_level) 390 { 391 return perf_cap__capable(CAP_SYS_ADMIN) || 392 perf_event_paranoid() <= max_level; 393 } 394 395 static int 396 fetch_ubuntu_kernel_version(unsigned int *puint) 397 { 398 ssize_t len; 399 size_t line_len = 0; 400 char *ptr, *line = NULL; 401 int version, patchlevel, sublevel, err; 402 FILE *vsig; 403 404 if (!puint) 405 return 0; 406 407 vsig = fopen("/proc/version_signature", "r"); 408 if (!vsig) { 409 pr_debug("Open /proc/version_signature failed: %s\n", 410 strerror(errno)); 411 return -1; 412 } 413 414 len = getline(&line, &line_len, vsig); 415 fclose(vsig); 416 err = -1; 417 if (len <= 0) { 418 pr_debug("Reading from /proc/version_signature failed: %s\n", 419 strerror(errno)); 420 goto errout; 421 } 422 423 ptr = strrchr(line, ' '); 424 if (!ptr) { 425 pr_debug("Parsing /proc/version_signature failed: %s\n", line); 426 goto errout; 427 } 428 429 err = sscanf(ptr + 1, "%d.%d.%d", 430 &version, &patchlevel, &sublevel); 431 if (err != 3) { 432 pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n", 433 line); 434 goto errout; 435 } 436 437 *puint = (version << 16) + (patchlevel << 8) + sublevel; 438 err = 0; 439 errout: 440 free(line); 441 return err; 442 } 443 444 int 445 fetch_kernel_version(unsigned int *puint, char *str, 446 size_t str_size) 447 { 448 struct utsname utsname; 449 int version, patchlevel, sublevel, err; 450 bool int_ver_ready = false; 451 452 if (access("/proc/version_signature", R_OK) == 0) 453 if (!fetch_ubuntu_kernel_version(puint)) 454 int_ver_ready = true; 455 456 if (uname(&utsname)) 457 return -1; 458 459 if (str && str_size) { 460 strncpy(str, utsname.release, str_size); 461 str[str_size - 1] = '\0'; 462 } 463 464 if (!puint || int_ver_ready) 465 return 0; 466 467 err = sscanf(utsname.release, "%d.%d.%d", 468 &version, &patchlevel, &sublevel); 469 470 if (err != 3) { 471 pr_debug("Unable to get kernel version from uname '%s'\n", 472 utsname.release); 473 return -1; 474 } 475 476 *puint = (version << 16) + (patchlevel << 8) + sublevel; 477 return 0; 478 } 479 480 const char *perf_tip(const char *dirpath) 481 { 482 struct strlist *tips; 483 struct str_node *node; 484 char *tip = NULL; 485 struct strlist_config conf = { 486 .dirname = dirpath, 487 .file_only = true, 488 }; 489 490 tips = strlist__new("tips.txt", &conf); 491 if (tips == NULL) 492 return errno == ENOENT ? NULL : 493 "Tip: check path of tips.txt or get more memory! ;-p"; 494 495 if (strlist__nr_entries(tips) == 0) 496 goto out; 497 498 node = strlist__entry(tips, random() % strlist__nr_entries(tips)); 499 if (asprintf(&tip, "Tip: %s", node->s) < 0) 500 tip = (char *)"Tip: get more memory! ;-)"; 501 502 out: 503 strlist__delete(tips); 504 505 return tip; 506 } 507 508 char *perf_exe(char *buf, int len) 509 { 510 int n = readlink("/proc/self/exe", buf, len); 511 if (n > 0) { 512 buf[n] = 0; 513 return buf; 514 } 515 return strcpy(buf, "perf"); 516 } 517