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