mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
selftests/landlock: Test abstract UNIX socket scoping
Add three tests that examine different scenarios for abstract UNIX socket: 1) scoped_domains: Base tests of the abstract socket scoping mechanism for a landlocked process, same as the ptrace test. 2) scoped_vs_unscoped: Generates three processes with different domains and tests if a process with a non-scoped domain can connect to other processes. 3) outside_socket: Since the socket's creator credentials are used for scoping sockets, this test examines the cases where the socket's credentials are different from the process using it. Move protocol_variant, service_fixture, and sys_gettid() from net_test.c to common.h, and factor out code into a new set_unix_address() helper. Signed-off-by: Tahera Fahimi <fahimitahera@gmail.com> Link: https://lore.kernel.org/r/9321c3d3bcd9212ceb4b50693e29349f8d625e16.1725494372.git.fahimitahera@gmail.com [mic: Fix commit message, remove useless clang-format tags, move drop_caps() calls, move and rename variables, rename variants, use more EXPECT, improve comments, simplify the outside_socket test] Signed-off-by: Mickaël Salaün <mic@digikod.net>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
* Copyright © 2021 Microsoft Corporation
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <linux/landlock.h>
|
||||
#include <linux/securebits.h>
|
||||
@@ -14,6 +15,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -226,3 +228,38 @@ enforce_ruleset(struct __test_metadata *const _metadata, const int ruleset_fd)
|
||||
TH_LOG("Failed to enforce ruleset: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
struct protocol_variant {
|
||||
int domain;
|
||||
int type;
|
||||
};
|
||||
|
||||
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 pid_t __maybe_unused sys_gettid(void)
|
||||
{
|
||||
return syscall(__NR_gettid);
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
@@ -36,30 +36,6 @@ enum sandbox_type {
|
||||
TCP_SANDBOX,
|
||||
};
|
||||
|
||||
struct protocol_variant {
|
||||
int domain;
|
||||
int type;
|
||||
};
|
||||
|
||||
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 pid_t sys_gettid(void)
|
||||
{
|
||||
return syscall(__NR_gettid);
|
||||
}
|
||||
|
||||
static int set_service(struct service_fixture *const srv,
|
||||
const struct protocol_variant prot,
|
||||
const unsigned short index)
|
||||
@@ -92,12 +68,7 @@ static int set_service(struct service_fixture *const srv,
|
||||
return 0;
|
||||
|
||||
case AF_UNIX:
|
||||
srv->unix_addr.sun_family = prot.domain;
|
||||
sprintf(srv->unix_addr.sun_path,
|
||||
"_selftests-landlock-net-tid%d-index%d", sys_gettid(),
|
||||
index);
|
||||
srv->unix_addr_len = SUN_LEN(&srv->unix_addr);
|
||||
srv->unix_addr.sun_path[0] = '\0';
|
||||
set_unix_address(srv, index);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,156 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Landlock scoped_domains variants
|
||||
*
|
||||
* See the hierarchy variants from ptrace_test.c
|
||||
*
|
||||
* Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
|
||||
* Copyright © 2019-2020 ANSSI
|
||||
* Copyright © 2024 Tahera Fahimi <fahimitahera@gmail.com>
|
||||
*/
|
||||
|
||||
/* clang-format on */
|
||||
FIXTURE_VARIANT(scoped_domains)
|
||||
{
|
||||
bool domain_both;
|
||||
bool domain_parent;
|
||||
bool domain_child;
|
||||
};
|
||||
|
||||
/*
|
||||
* No domain
|
||||
*
|
||||
* P1-. P1 -> P2 : allow
|
||||
* \ P2 -> P1 : allow
|
||||
* 'P2
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_domains, without_domain) {
|
||||
/* clang-format on */
|
||||
.domain_both = false,
|
||||
.domain_parent = false,
|
||||
.domain_child = false,
|
||||
};
|
||||
|
||||
/*
|
||||
* Child domain
|
||||
*
|
||||
* P1--. P1 -> P2 : allow
|
||||
* \ P2 -> P1 : deny
|
||||
* .'-----.
|
||||
* | P2 |
|
||||
* '------'
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_domains, child_domain) {
|
||||
/* clang-format on */
|
||||
.domain_both = false,
|
||||
.domain_parent = false,
|
||||
.domain_child = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* Parent domain
|
||||
* .------.
|
||||
* | P1 --. P1 -> P2 : deny
|
||||
* '------' \ P2 -> P1 : allow
|
||||
* '
|
||||
* P2
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_domains, parent_domain) {
|
||||
/* clang-format on */
|
||||
.domain_both = false,
|
||||
.domain_parent = true,
|
||||
.domain_child = false,
|
||||
};
|
||||
|
||||
/*
|
||||
* Parent + child domain (siblings)
|
||||
* .------.
|
||||
* | P1 ---. P1 -> P2 : deny
|
||||
* '------' \ P2 -> P1 : deny
|
||||
* .---'--.
|
||||
* | P2 |
|
||||
* '------'
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_domains, sibling_domain) {
|
||||
/* clang-format on */
|
||||
.domain_both = false,
|
||||
.domain_parent = true,
|
||||
.domain_child = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* Same domain (inherited)
|
||||
* .-------------.
|
||||
* | P1----. | P1 -> P2 : allow
|
||||
* | \ | P2 -> P1 : allow
|
||||
* | ' |
|
||||
* | P2 |
|
||||
* '-------------'
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_domains, inherited_domain) {
|
||||
/* clang-format on */
|
||||
.domain_both = true,
|
||||
.domain_parent = false,
|
||||
.domain_child = false,
|
||||
};
|
||||
|
||||
/*
|
||||
* Inherited + child domain
|
||||
* .-----------------.
|
||||
* | P1----. | P1 -> P2 : allow
|
||||
* | \ | P2 -> P1 : deny
|
||||
* | .-'----. |
|
||||
* | | P2 | |
|
||||
* | '------' |
|
||||
* '-----------------'
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_domains, nested_domain) {
|
||||
/* clang-format on */
|
||||
.domain_both = true,
|
||||
.domain_parent = false,
|
||||
.domain_child = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* Inherited + parent domain
|
||||
* .-----------------.
|
||||
* |.------. | P1 -> P2 : deny
|
||||
* || P1 ----. | P2 -> P1 : allow
|
||||
* |'------' \ |
|
||||
* | ' |
|
||||
* | P2 |
|
||||
* '-----------------'
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_domains, nested_and_parent_domain) {
|
||||
/* clang-format on */
|
||||
.domain_both = true,
|
||||
.domain_parent = true,
|
||||
.domain_child = false,
|
||||
};
|
||||
|
||||
/*
|
||||
* Inherited + parent and child domain (siblings)
|
||||
* .-----------------.
|
||||
* | .------. | P1 -> P2 : deny
|
||||
* | | P1 . | P2 -> P1 : deny
|
||||
* | '------'\ |
|
||||
* | \ |
|
||||
* | .--'---. |
|
||||
* | | P2 | |
|
||||
* | '------' |
|
||||
* '-----------------'
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_domains, forked_domains) {
|
||||
/* clang-format on */
|
||||
.domain_both = true,
|
||||
.domain_parent = true,
|
||||
.domain_child = true,
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Landlock scope test helpers
|
||||
*
|
||||
* Copyright © 2024 Tahera Fahimi <fahimitahera@gmail.com>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
static void create_scoped_domain(struct __test_metadata *const _metadata,
|
||||
const __u16 scope)
|
||||
{
|
||||
int ruleset_fd;
|
||||
const struct landlock_ruleset_attr ruleset_attr = {
|
||||
.scoped = scope,
|
||||
};
|
||||
|
||||
ruleset_fd =
|
||||
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
|
||||
ASSERT_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));
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Landlock variants for three processes with various domains.
|
||||
*
|
||||
* Copyright © 2024 Tahera Fahimi <fahimitahera@gmail.com>
|
||||
*/
|
||||
|
||||
enum sandbox_type {
|
||||
NO_SANDBOX,
|
||||
SCOPE_SANDBOX,
|
||||
/* Any other type of sandboxing domain */
|
||||
OTHER_SANDBOX,
|
||||
};
|
||||
|
||||
/* clang-format on */
|
||||
FIXTURE_VARIANT(scoped_vs_unscoped)
|
||||
{
|
||||
const int domain_all;
|
||||
const int domain_parent;
|
||||
const int domain_children;
|
||||
const int domain_child;
|
||||
const int domain_grand_child;
|
||||
};
|
||||
|
||||
/*
|
||||
* .-----------------.
|
||||
* | ####### | P3 -> P2 : allow
|
||||
* | P1----# P2 # | P3 -> P1 : deny
|
||||
* | # | # |
|
||||
* | # P3 # |
|
||||
* | ####### |
|
||||
* '-----------------'
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_vs_unscoped, deny_scoped) {
|
||||
.domain_all = OTHER_SANDBOX,
|
||||
.domain_parent = NO_SANDBOX,
|
||||
.domain_children = SCOPE_SANDBOX,
|
||||
.domain_child = NO_SANDBOX,
|
||||
.domain_grand_child = NO_SANDBOX,
|
||||
/* clang-format on */
|
||||
};
|
||||
|
||||
/*
|
||||
* ###################
|
||||
* # ####### # P3 -> P2 : allow
|
||||
* # P1----# P2 # # P3 -> P1 : deny
|
||||
* # # | # #
|
||||
* # # P3 # #
|
||||
* # ####### #
|
||||
* ###################
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_vs_unscoped, all_scoped) {
|
||||
.domain_all = SCOPE_SANDBOX,
|
||||
.domain_parent = NO_SANDBOX,
|
||||
.domain_children = SCOPE_SANDBOX,
|
||||
.domain_child = NO_SANDBOX,
|
||||
.domain_grand_child = NO_SANDBOX,
|
||||
/* clang-format on */
|
||||
};
|
||||
|
||||
/*
|
||||
* .-----------------.
|
||||
* | .-----. | P3 -> P2 : allow
|
||||
* | P1----| P2 | | P3 -> P1 : allow
|
||||
* | | | |
|
||||
* | | P3 | |
|
||||
* | '-----' |
|
||||
* '-----------------'
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_vs_unscoped, allow_with_other_domain) {
|
||||
.domain_all = OTHER_SANDBOX,
|
||||
.domain_parent = NO_SANDBOX,
|
||||
.domain_children = OTHER_SANDBOX,
|
||||
.domain_child = NO_SANDBOX,
|
||||
.domain_grand_child = NO_SANDBOX,
|
||||
/* clang-format on */
|
||||
};
|
||||
|
||||
/*
|
||||
* .----. ###### P3 -> P2 : allow
|
||||
* | P1 |----# P2 # P3 -> P1 : allow
|
||||
* '----' ######
|
||||
* |
|
||||
* P3
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_vs_unscoped, allow_with_one_domain) {
|
||||
.domain_all = NO_SANDBOX,
|
||||
.domain_parent = OTHER_SANDBOX,
|
||||
.domain_children = NO_SANDBOX,
|
||||
.domain_child = SCOPE_SANDBOX,
|
||||
.domain_grand_child = NO_SANDBOX,
|
||||
/* clang-format on */
|
||||
};
|
||||
|
||||
/*
|
||||
* ###### .-----. P3 -> P2 : allow
|
||||
* # P1 #----| P2 | P3 -> P1 : allow
|
||||
* ###### '-----'
|
||||
* |
|
||||
* P3
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_vs_unscoped, allow_with_grand_parent_scoped) {
|
||||
.domain_all = NO_SANDBOX,
|
||||
.domain_parent = SCOPE_SANDBOX,
|
||||
.domain_children = NO_SANDBOX,
|
||||
.domain_child = OTHER_SANDBOX,
|
||||
.domain_grand_child = NO_SANDBOX,
|
||||
/* clang-format on */
|
||||
};
|
||||
|
||||
/*
|
||||
* ###### ###### P3 -> P2 : allow
|
||||
* # P1 #----# P2 # P3 -> P1 : allow
|
||||
* ###### ######
|
||||
* |
|
||||
* .----.
|
||||
* | P3 |
|
||||
* '----'
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_vs_unscoped, allow_with_parents_domain) {
|
||||
.domain_all = NO_SANDBOX,
|
||||
.domain_parent = SCOPE_SANDBOX,
|
||||
.domain_children = NO_SANDBOX,
|
||||
.domain_child = SCOPE_SANDBOX,
|
||||
.domain_grand_child = NO_SANDBOX,
|
||||
/* clang-format on */
|
||||
};
|
||||
|
||||
/*
|
||||
* ###### P3 -> P2 : deny
|
||||
* # P1 #----P2 P3 -> P1 : deny
|
||||
* ###### |
|
||||
* |
|
||||
* ######
|
||||
* # P3 #
|
||||
* ######
|
||||
*/
|
||||
/* clang-format off */
|
||||
FIXTURE_VARIANT_ADD(scoped_vs_unscoped, deny_with_self_and_grandparent_domain) {
|
||||
.domain_all = NO_SANDBOX,
|
||||
.domain_parent = SCOPE_SANDBOX,
|
||||
.domain_children = NO_SANDBOX,
|
||||
.domain_child = NO_SANDBOX,
|
||||
.domain_grand_child = SCOPE_SANDBOX,
|
||||
/* clang-format on */
|
||||
};
|
||||
Reference in New Issue
Block a user