110 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Author: Aleksa Sarai <cyphar@cyphar.com>4 * Copyright (C) 2018-2019 SUSE LLC.5 */6 7#define _GNU_SOURCE8#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 else84 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}110