helpers.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Author: Aleksa Sarai <cyphar@cyphar.com>
  4. * Copyright (C) 2018-2019 SUSE LLC.
  5. */
  6. #define _GNU_SOURCE
  7. #include <errno.h>
  8. #include <fcntl.h>
  9. #include <stdbool.h>
  10. #include <string.h>
  11. #include <syscall.h>
  12. #include <limits.h>
  13. #include "helpers.h"
  14. bool needs_openat2(const struct open_how *how)
  15. {
  16. return how->resolve != 0;
  17. }
  18. int raw_openat2(int dfd, const char *path, void *how, size_t size)
  19. {
  20. int ret = syscall(__NR_openat2, dfd, path, how, size);
  21. return ret >= 0 ? ret : -errno;
  22. }
  23. int sys_openat2(int dfd, const char *path, struct open_how *how)
  24. {
  25. return raw_openat2(dfd, path, how, sizeof(*how));
  26. }
  27. int sys_openat(int dfd, const char *path, struct open_how *how)
  28. {
  29. int ret = openat(dfd, path, how->flags, how->mode);
  30. return ret >= 0 ? ret : -errno;
  31. }
  32. int sys_renameat2(int olddirfd, const char *oldpath,
  33. int newdirfd, const char *newpath, unsigned int flags)
  34. {
  35. int ret = syscall(__NR_renameat2, olddirfd, oldpath,
  36. newdirfd, newpath, flags);
  37. return ret >= 0 ? ret : -errno;
  38. }
  39. int touchat(int dfd, const char *path)
  40. {
  41. int fd = openat(dfd, path, O_CREAT, 0700);
  42. if (fd >= 0)
  43. close(fd);
  44. return fd;
  45. }
  46. char *fdreadlink(int fd)
  47. {
  48. char *target, *tmp;
  49. E_asprintf(&tmp, "/proc/self/fd/%d", fd);
  50. target = malloc(PATH_MAX);
  51. if (!target)
  52. ksft_exit_fail_msg("fdreadlink: malloc failed\n");
  53. memset(target, 0, PATH_MAX);
  54. E_readlink(tmp, target, PATH_MAX);
  55. free(tmp);
  56. return target;
  57. }
  58. bool fdequal(int fd, int dfd, const char *path)
  59. {
  60. char *fdpath, *dfdpath, *other;
  61. bool cmp;
  62. fdpath = fdreadlink(fd);
  63. dfdpath = fdreadlink(dfd);
  64. if (!path)
  65. E_asprintf(&other, "%s", dfdpath);
  66. else if (*path == '/')
  67. E_asprintf(&other, "%s", path);
  68. else
  69. E_asprintf(&other, "%s/%s", dfdpath, path);
  70. cmp = !strcmp(fdpath, other);
  71. free(fdpath);
  72. free(dfdpath);
  73. free(other);
  74. return cmp;
  75. }
  76. bool openat2_supported = false;
  77. void __attribute__((constructor)) init(void)
  78. {
  79. struct open_how how = {};
  80. int fd;
  81. BUILD_BUG_ON(sizeof(struct open_how) != OPEN_HOW_SIZE_VER0);
  82. /* Check openat2(2) support. */
  83. fd = sys_openat2(AT_FDCWD, ".", &how);
  84. openat2_supported = (fd >= 0);
  85. if (fd >= 0)
  86. close(fd);
  87. }