Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/testing/selftests/landlock/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  common.h   Sprache: C

 
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Landlock test helpers
 *
 * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
 * Copyright © 2019-2020 ANSSI
 * Copyright © 2021 Microsoft Corporation
 */


#include <arpa/inet.h>
#include <errno.h>
#include <linux/securebits.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>

#include "../kselftest_harness.h"
#include "wrappers.h"

#define TMP_DIR "tmp"

#ifndef __maybe_unused
#define __maybe_unused __attribute__((__unused__))
#endif

/* TEST_F_FORK() should not be used for new tests. */
#define TEST_F_FORK(fixture_name, test_name) TEST_F(fixture_name, test_name)

static const char bin_sandbox_and_launch[] = "./sandbox-and-launch";
static const char bin_wait_pipe[] = "./wait-pipe";
static const char bin_wait_pipe_sandbox[] = "./wait-pipe-sandbox";

static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
{
 cap_t cap_p;
 /* Only these three capabilities are useful for the tests. */
 const cap_value_t caps[] = {
  /* clang-format off */
  CAP_AUDIT_CONTROL,
  CAP_DAC_OVERRIDE,
  CAP_MKNOD,
  CAP_NET_ADMIN,
  CAP_NET_BIND_SERVICE,
  CAP_SETUID,
  CAP_SYS_ADMIN,
  CAP_SYS_CHROOT,
  /* clang-format on */
 };
 const unsigned int noroot = SECBIT_NOROOT | SECBIT_NOROOT_LOCKED;

 if ((cap_get_secbits() & noroot) != noroot)
  EXPECT_EQ(0, cap_set_secbits(noroot));

 cap_p = cap_get_proc();
 EXPECT_NE(NULL, cap_p);
 EXPECT_NE(-1, cap_clear(cap_p));
 if (!drop_all) {
  EXPECT_NE(-1, cap_set_flag(cap_p, CAP_PERMITTED,
        ARRAY_SIZE(caps), caps, CAP_SET));
 }

 /* Automatically resets ambient capabilities. */
 EXPECT_NE(-1, cap_set_proc(cap_p))
 {
  TH_LOG("Failed to set capabilities: %s", strerror(errno));
 }
 EXPECT_NE(-1, cap_free(cap_p));

 /* Quickly checks that ambient capabilities are cleared. */
 EXPECT_NE(-1, cap_get_ambient(caps[0]));
}

/* We cannot put such helpers in a library because of kselftest_harness.h . */
static void __maybe_unused disable_caps(struct __test_metadata *const _metadata)
{
 _init_caps(_metadata, false);
}

static void __maybe_unused drop_caps(struct __test_metadata *const _metadata)
{
 _init_caps(_metadata, true);
}

static void _change_cap(struct __test_metadata *const _metadata,
   const cap_flag_t flag, const cap_value_t cap,
   const cap_flag_value_t value)
{
 cap_t cap_p;

 cap_p = cap_get_proc();
 EXPECT_NE(NULL, cap_p);
 EXPECT_NE(-1, cap_set_flag(cap_p, flag, 1, &cap, value));
 EXPECT_NE(-1, cap_set_proc(cap_p))
 {
  TH_LOG("Failed to set capability %d: %s", cap, strerror(errno));
 }
 EXPECT_NE(-1, cap_free(cap_p));
}

static void __maybe_unused set_cap(struct __test_metadata *const _metadata,
       const cap_value_t cap)
{
 _change_cap(_metadata, CAP_EFFECTIVE, cap, CAP_SET);
}

static void __maybe_unused clear_cap(struct __test_metadata *const _metadata,
         const cap_value_t cap)
{
 _change_cap(_metadata, CAP_EFFECTIVE, cap, CAP_CLEAR);
}

static void __maybe_unused
set_ambient_cap(struct __test_metadata *const _metadata, const cap_value_t cap)
{
 _change_cap(_metadata, CAP_INHERITABLE, cap, CAP_SET);

 EXPECT_NE(-1, cap_set_ambient(cap, CAP_SET))
 {
  TH_LOG("Failed to set ambient capability %d: %s", cap,
         strerror(errno));
 }
}

static void __maybe_unused clear_ambient_cap(
 struct __test_metadata *const _metadata, const cap_value_t cap)
{
 EXPECT_EQ(1, cap_get_ambient(cap));
 _change_cap(_metadata, CAP_INHERITABLE, cap, CAP_CLEAR);
 EXPECT_EQ(0, cap_get_ambient(cap));
}

/* Receives an FD from a UNIX socket. Returns the received FD, or -errno. */
static int __maybe_unused recv_fd(int usock)
{
 int fd_rx;
 union {
  /* Aligned ancillary data buffer. */
  char buf[CMSG_SPACE(sizeof(fd_rx))];
  struct cmsghdr _align;
 } cmsg_rx = {};
 char data = '\0';
 struct iovec io = {
  .iov_base = &data,
  .iov_len = sizeof(data),
 };
 struct msghdr msg = {
  .msg_iov = &io,
  .msg_iovlen = 1,
  .msg_control = &cmsg_rx.buf,
  .msg_controllen = sizeof(cmsg_rx.buf),
 };
 struct cmsghdr *cmsg;
 int res;

 res = recvmsg(usock, &msg, MSG_CMSG_CLOEXEC);
 if (res < 0)
  return -errno;

 cmsg = CMSG_FIRSTHDR(&msg);
 if (cmsg->cmsg_len != CMSG_LEN(sizeof(fd_rx)))
  return -EIO;

 memcpy(&fd_rx, CMSG_DATA(cmsg), sizeof(fd_rx));
 return fd_rx;
}

/* Sends an FD on a UNIX socket. Returns 0 on success or -errno. */
static int __maybe_unused send_fd(int usock, int fd_tx)
{
 union {
  /* Aligned ancillary data buffer. */
  char buf[CMSG_SPACE(sizeof(fd_tx))];
  struct cmsghdr _align;
 } cmsg_tx = {};
 char data_tx = '.';
 struct iovec io = {
  .iov_base = &data_tx,
  .iov_len = sizeof(data_tx),
 };
 struct msghdr msg = {
  .msg_iov = &io,
  .msg_iovlen = 1,
  .msg_control = &cmsg_tx.buf,
  .msg_controllen = sizeof(cmsg_tx.buf),
 };
 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);

 cmsg->cmsg_len = CMSG_LEN(sizeof(fd_tx));
 cmsg->cmsg_level = SOL_SOCKET;
 cmsg->cmsg_type = SCM_RIGHTS;
 memcpy(CMSG_DATA(cmsg), &fd_tx, sizeof(fd_tx));

 if (sendmsg(usock, &msg, 0) < 0)
  return -errno;
 return 0;
}

static void __maybe_unused
enforce_ruleset(struct __test_metadata *const _metadata, const int ruleset_fd)
{
 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0))
 {
  TH_LOG("Failed to enforce ruleset: %s", strerror(errno));
 }
}

static void __maybe_unused
drop_access_rights(struct __test_metadata *const _metadata,
     const struct landlock_ruleset_attr *const ruleset_attr)
{
 int ruleset_fd;

 ruleset_fd =
  landlock_create_ruleset(ruleset_attr, sizeof(*ruleset_attr), 0);
 EXPECT_LE(0, ruleset_fd)
 {
  TH_LOG("Failed to create a ruleset: %s", strerror(errno));
 }
 enforce_ruleset(_metadata, ruleset_fd);
 EXPECT_EQ(0, close(ruleset_fd));
}

struct protocol_variant {
 int domain;
 int type;
 int protocol;
};

struct service_fixture {
 struct protocol_variant protocol;
 /* port is also stored in ipv4_addr.sin_port or ipv6_addr.sin6_port */
 unsigned short port;
 union {
  struct sockaddr_in ipv4_addr;
  struct sockaddr_in6 ipv6_addr;
  struct {
   struct sockaddr_un unix_addr;
   socklen_t unix_addr_len;
  };
 };
};

static void __maybe_unused set_unix_address(struct service_fixture *const srv,
         const unsigned short index)
{
 srv->unix_addr.sun_family = AF_UNIX;
 sprintf(srv->unix_addr.sun_path,
  "_selftests-landlock-abstract-unix-tid%d-index%d", sys_gettid(),
  index);
 srv->unix_addr_len = SUN_LEN(&srv->unix_addr);
 srv->unix_addr.sun_path[0] = '\0';
}

Messung V0.5
C=95 H=100 G=97

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.