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