cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

common.h (4993B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * Landlock test helpers
      4 *
      5 * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
      6 * Copyright © 2019-2020 ANSSI
      7 * Copyright © 2021 Microsoft Corporation
      8 */
      9
     10#include <errno.h>
     11#include <linux/landlock.h>
     12#include <sys/capability.h>
     13#include <sys/syscall.h>
     14#include <sys/types.h>
     15#include <sys/wait.h>
     16#include <unistd.h>
     17
     18#include "../kselftest_harness.h"
     19
     20/*
     21 * TEST_F_FORK() is useful when a test drop privileges but the corresponding
     22 * FIXTURE_TEARDOWN() requires them (e.g. to remove files from a directory
     23 * where write actions are denied).  For convenience, FIXTURE_TEARDOWN() is
     24 * also called when the test failed, but not when FIXTURE_SETUP() failed.  For
     25 * this to be possible, we must not call abort() but instead exit smoothly
     26 * (hence the step print).
     27 */
     28/* clang-format off */
     29#define TEST_F_FORK(fixture_name, test_name) \
     30	static void fixture_name##_##test_name##_child( \
     31		struct __test_metadata *_metadata, \
     32		FIXTURE_DATA(fixture_name) *self, \
     33		const FIXTURE_VARIANT(fixture_name) *variant); \
     34	TEST_F(fixture_name, test_name) \
     35	{ \
     36		int status; \
     37		const pid_t child = fork(); \
     38		if (child < 0) \
     39			abort(); \
     40		if (child == 0) { \
     41			_metadata->no_print = 1; \
     42			fixture_name##_##test_name##_child(_metadata, self, variant); \
     43			if (_metadata->skip) \
     44				_exit(255); \
     45			if (_metadata->passed) \
     46				_exit(0); \
     47			_exit(_metadata->step); \
     48		} \
     49		if (child != waitpid(child, &status, 0)) \
     50			abort(); \
     51		if (WIFSIGNALED(status) || !WIFEXITED(status)) { \
     52			_metadata->passed = 0; \
     53			_metadata->step = 1; \
     54			return; \
     55		} \
     56		switch (WEXITSTATUS(status)) { \
     57		case 0: \
     58			_metadata->passed = 1; \
     59			break; \
     60		case 255: \
     61			_metadata->passed = 1; \
     62			_metadata->skip = 1; \
     63			break; \
     64		default: \
     65			_metadata->passed = 0; \
     66			_metadata->step = WEXITSTATUS(status); \
     67			break; \
     68		} \
     69	} \
     70	static void fixture_name##_##test_name##_child( \
     71		struct __test_metadata __attribute__((unused)) *_metadata, \
     72		FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \
     73		const FIXTURE_VARIANT(fixture_name) \
     74			__attribute__((unused)) *variant)
     75/* clang-format on */
     76
     77#ifndef landlock_create_ruleset
     78static inline int
     79landlock_create_ruleset(const struct landlock_ruleset_attr *const attr,
     80			const size_t size, const __u32 flags)
     81{
     82	return syscall(__NR_landlock_create_ruleset, attr, size, flags);
     83}
     84#endif
     85
     86#ifndef landlock_add_rule
     87static inline int landlock_add_rule(const int ruleset_fd,
     88				    const enum landlock_rule_type rule_type,
     89				    const void *const rule_attr,
     90				    const __u32 flags)
     91{
     92	return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type, rule_attr,
     93		       flags);
     94}
     95#endif
     96
     97#ifndef landlock_restrict_self
     98static inline int landlock_restrict_self(const int ruleset_fd,
     99					 const __u32 flags)
    100{
    101	return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
    102}
    103#endif
    104
    105static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
    106{
    107	cap_t cap_p;
    108	/* Only these three capabilities are useful for the tests. */
    109	const cap_value_t caps[] = {
    110		CAP_DAC_OVERRIDE,
    111		CAP_MKNOD,
    112		CAP_SYS_ADMIN,
    113		CAP_SYS_CHROOT,
    114	};
    115
    116	cap_p = cap_get_proc();
    117	EXPECT_NE(NULL, cap_p)
    118	{
    119		TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
    120	}
    121	EXPECT_NE(-1, cap_clear(cap_p))
    122	{
    123		TH_LOG("Failed to cap_clear: %s", strerror(errno));
    124	}
    125	if (!drop_all) {
    126		EXPECT_NE(-1, cap_set_flag(cap_p, CAP_PERMITTED,
    127					   ARRAY_SIZE(caps), caps, CAP_SET))
    128		{
    129			TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
    130		}
    131	}
    132	EXPECT_NE(-1, cap_set_proc(cap_p))
    133	{
    134		TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
    135	}
    136	EXPECT_NE(-1, cap_free(cap_p))
    137	{
    138		TH_LOG("Failed to cap_free: %s", strerror(errno));
    139	}
    140}
    141
    142/* We cannot put such helpers in a library because of kselftest_harness.h . */
    143__attribute__((__unused__)) static void
    144disable_caps(struct __test_metadata *const _metadata)
    145{
    146	_init_caps(_metadata, false);
    147}
    148
    149__attribute__((__unused__)) static void
    150drop_caps(struct __test_metadata *const _metadata)
    151{
    152	_init_caps(_metadata, true);
    153}
    154
    155static void _effective_cap(struct __test_metadata *const _metadata,
    156			   const cap_value_t caps, const cap_flag_value_t value)
    157{
    158	cap_t cap_p;
    159
    160	cap_p = cap_get_proc();
    161	EXPECT_NE(NULL, cap_p)
    162	{
    163		TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
    164	}
    165	EXPECT_NE(-1, cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &caps, value))
    166	{
    167		TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
    168	}
    169	EXPECT_NE(-1, cap_set_proc(cap_p))
    170	{
    171		TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
    172	}
    173	EXPECT_NE(-1, cap_free(cap_p))
    174	{
    175		TH_LOG("Failed to cap_free: %s", strerror(errno));
    176	}
    177}
    178
    179__attribute__((__unused__)) static void
    180set_cap(struct __test_metadata *const _metadata, const cap_value_t caps)
    181{
    182	_effective_cap(_metadata, caps, CAP_SET);
    183}
    184
    185__attribute__((__unused__)) static void
    186clear_cap(struct __test_metadata *const _metadata, const cap_value_t caps)
    187{
    188	_effective_cap(_metadata, caps, CAP_CLEAR);
    189}