helpers.c (2182B)
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 17bool needs_openat2(const struct open_how *how) 18{ 19 return how->resolve != 0; 20} 21 22int 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 28int sys_openat2(int dfd, const char *path, struct open_how *how) 29{ 30 return raw_openat2(dfd, path, how, sizeof(*how)); 31} 32 33int 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 39int 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 47int 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 55char *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 71bool 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 94bool openat2_supported = false; 95 96void __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}