Merge tag 'landlock-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux

Pull landlock fixes from Mickaël Salaün:
 "This fixes TCP handling, tests, documentation, non-audit elided code,
  and minor cosmetic changes"

* tag 'landlock-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux:
  landlock: Clarify documentation for the IOCTL access right
  selftests/landlock: Properly close a file descriptor
  landlock: Improve the comment for domain_is_scoped
  selftests/landlock: Use scoped_base_variants.h for ptrace_test
  selftests/landlock: Fix missing semicolon
  selftests/landlock: Fix typo in fs_test
  landlock: Optimize stack usage when !CONFIG_AUDIT
  landlock: Fix spelling
  landlock: Clean up hook_ptrace_access_check()
  landlock: Improve erratum documentation
  landlock: Remove useless include
  landlock: Fix wrong type usage
  selftests/landlock: NULL-terminate unix pathname addresses
  selftests/landlock: Remove invalid unix socket bind()
  selftests/landlock: Add missing connect(minimal AF_UNSPEC) test
  selftests/landlock: Fix TCP bind(AF_UNSPEC) test case
  landlock: Fix TCP handling of short AF_UNSPEC addresses
  landlock: Fix formatting
This commit is contained in:
Linus Torvalds
2026-01-18 15:15:47 -08:00
14 changed files with 170 additions and 269 deletions

View File

@@ -216,6 +216,23 @@ struct landlock_net_port_attr {
* :manpage:`ftruncate(2)`, :manpage:`creat(2)`, or :manpage:`open(2)` with
* ``O_TRUNC``. This access right is available since the third version of the
* Landlock ABI.
* - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened
* character or block device.
*
* This access right applies to all `ioctl(2)` commands implemented by device
* drivers. However, the following common IOCTL commands continue to be
* invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right:
*
* * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``),
* * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``),
* * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``,
* ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``)
* * Some IOCTL commands which do not make sense when used with devices, but
* whose implementations are safe and return the right error codes
* (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``)
*
* This access right is available since the fifth version of the Landlock
* ABI.
*
* Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used
* with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as
@@ -275,26 +292,6 @@ struct landlock_net_port_attr {
* If multiple requirements are not met, the ``EACCES`` error code takes
* precedence over ``EXDEV``.
*
* The following access right applies both to files and directories:
*
* - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened
* character or block device.
*
* This access right applies to all `ioctl(2)` commands implemented by device
* drivers. However, the following common IOCTL commands continue to be
* invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right:
*
* * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``),
* * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``),
* * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``,
* ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``)
* * Some IOCTL commands which do not make sense when used with devices, but
* whose implementations are safe and return the right error codes
* (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``)
*
* This access right is available since the fifth version of the Landlock
* ABI.
*
* .. warning::
*
* It is currently not possible to restrict some file-related actions

View File

@@ -191,7 +191,7 @@ static size_t get_denied_layer(const struct landlock_ruleset *const domain,
long youngest_layer = -1;
for_each_set_bit(access_bit, &access_req, layer_masks_size) {
const access_mask_t mask = (*layer_masks)[access_bit];
const layer_mask_t mask = (*layer_masks)[access_bit];
long layer;
if (!mask)

View File

@@ -97,7 +97,7 @@ struct landlock_hierarchy {
*/
atomic64_t num_denials;
/**
* @id: Landlock domain ID, sets once at domain creation time.
* @id: Landlock domain ID, set once at domain creation time.
*/
u64 id;
/**

View File

@@ -9,7 +9,7 @@
* This fix addresses an issue where signal scoping was overly restrictive,
* preventing sandboxed threads from signaling other threads within the same
* process if they belonged to different domains. Because threads are not
* security boundaries, user space might assume that any thread within the same
* security boundaries, user space might assume that all threads within the same
* process can send signals between themselves (see :manpage:`nptl(7)` and
* :manpage:`libpsx(3)`). Consistent with :manpage:`ptrace(2)` behavior, direct
* interaction between threads of the same process should always be allowed.

View File

@@ -939,7 +939,12 @@ jump_up:
}
path_put(&walker_path);
if (!allowed_parent1) {
/*
* Check CONFIG_AUDIT to enable elision of log_request_parent* and
* associated caller's stack variables thanks to dead code elimination.
*/
#ifdef CONFIG_AUDIT
if (!allowed_parent1 && log_request_parent1) {
log_request_parent1->type = LANDLOCK_REQUEST_FS_ACCESS;
log_request_parent1->audit.type = LSM_AUDIT_DATA_PATH;
log_request_parent1->audit.u.path = *path;
@@ -949,7 +954,7 @@ jump_up:
ARRAY_SIZE(*layer_masks_parent1);
}
if (!allowed_parent2) {
if (!allowed_parent2 && log_request_parent2) {
log_request_parent2->type = LANDLOCK_REQUEST_FS_ACCESS;
log_request_parent2->audit.type = LSM_AUDIT_DATA_PATH;
log_request_parent2->audit.u.path = *path;
@@ -958,6 +963,8 @@ jump_up:
log_request_parent2->layer_masks_size =
ARRAY_SIZE(*layer_masks_parent2);
}
#endif /* CONFIG_AUDIT */
return allowed_parent1 && allowed_parent2;
}
@@ -1314,7 +1321,8 @@ static void hook_sb_delete(struct super_block *const sb)
* second call to iput() for the same Landlock object. Also
* checks I_NEW because such inode cannot be tied to an object.
*/
if (inode_state_read(inode) & (I_FREEING | I_WILL_FREE | I_NEW)) {
if (inode_state_read(inode) &
(I_FREEING | I_WILL_FREE | I_NEW)) {
spin_unlock(&inode->i_lock);
continue;
}

View File

@@ -71,6 +71,61 @@ static int current_check_access_socket(struct socket *const sock,
switch (address->sa_family) {
case AF_UNSPEC:
if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) {
/*
* Connecting to an address with AF_UNSPEC dissolves
* the TCP association, which have the same effect as
* closing the connection while retaining the socket
* object (i.e., the file descriptor). As for dropping
* privileges, closing connections is always allowed.
*
* For a TCP access control system, this request is
* legitimate. Let the network stack handle potential
* inconsistencies and return -EINVAL if needed.
*/
return 0;
} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) {
/*
* Binding to an AF_UNSPEC address is treated
* differently by IPv4 and IPv6 sockets. The socket's
* family may change under our feet due to
* setsockopt(IPV6_ADDRFORM), but that's ok: we either
* reject entirely or require
* %LANDLOCK_ACCESS_NET_BIND_TCP for the given port, so
* it cannot be used to bypass the policy.
*
* IPv4 sockets map AF_UNSPEC to AF_INET for
* retrocompatibility for bind accesses, only if the
* address is INADDR_ANY (cf. __inet_bind). IPv6
* sockets always reject it.
*
* Checking the address is required to not wrongfully
* return -EACCES instead of -EAFNOSUPPORT or -EINVAL.
* We could return 0 and let the network stack handle
* these checks, but it is safer to return a proper
* error and test consistency thanks to kselftest.
*/
if (sock->sk->__sk_common.skc_family == AF_INET) {
const struct sockaddr_in *const sockaddr =
(struct sockaddr_in *)address;
if (addrlen < sizeof(struct sockaddr_in))
return -EINVAL;
if (sockaddr->sin_addr.s_addr !=
htonl(INADDR_ANY))
return -EAFNOSUPPORT;
} else {
if (addrlen < SIN6_LEN_RFC2133)
return -EINVAL;
else
return -EAFNOSUPPORT;
}
} else {
WARN_ON_ONCE(1);
}
/* Only for bind(AF_UNSPEC+INADDR_ANY) on IPv4 socket. */
fallthrough;
case AF_INET: {
const struct sockaddr_in *addr4;
@@ -119,45 +174,6 @@ static int current_check_access_socket(struct socket *const sock,
return 0;
}
/* Specific AF_UNSPEC handling. */
if (address->sa_family == AF_UNSPEC) {
/*
* Connecting to an address with AF_UNSPEC dissolves the TCP
* association, which have the same effect as closing the
* connection while retaining the socket object (i.e., the file
* descriptor). As for dropping privileges, closing
* connections is always allowed.
*
* For a TCP access control system, this request is legitimate.
* Let the network stack handle potential inconsistencies and
* return -EINVAL if needed.
*/
if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP)
return 0;
/*
* For compatibility reason, accept AF_UNSPEC for bind
* accesses (mapped to AF_INET) only if the address is
* INADDR_ANY (cf. __inet_bind). Checking the address is
* required to not wrongfully return -EACCES instead of
* -EAFNOSUPPORT.
*
* We could return 0 and let the network stack handle these
* checks, but it is safer to return a proper error and test
* consistency thanks to kselftest.
*/
if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) {
/* addrlen has already been checked for AF_UNSPEC. */
const struct sockaddr_in *const sockaddr =
(struct sockaddr_in *)address;
if (sock->sk->__sk_common.skc_family != AF_INET)
return -EINVAL;
if (sockaddr->sin_addr.s_addr != htonl(INADDR_ANY))
return -EAFNOSUPPORT;
}
} else {
/*
* Checks sa_family consistency to not wrongfully return
* -EACCES instead of -EINVAL. Valid sa_family changes are
@@ -167,9 +183,9 @@ static int current_check_access_socket(struct socket *const sock,
* check, but it is safer to return a proper error and test
* consistency thanks to kselftest.
*/
if (address->sa_family != sock->sk->__sk_common.skc_family)
if (address->sa_family != sock->sk->__sk_common.skc_family &&
address->sa_family != AF_UNSPEC)
return -EINVAL;
}
id.key.data = (__force uintptr_t)port;
BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data));

View File

@@ -23,7 +23,6 @@
#include <linux/workqueue.h>
#include "access.h"
#include "audit.h"
#include "domain.h"
#include "limits.h"
#include "object.h"

View File

@@ -86,7 +86,6 @@ static int hook_ptrace_access_check(struct task_struct *const child,
const unsigned int mode)
{
const struct landlock_cred_security *parent_subject;
const struct landlock_ruleset *child_dom;
int err;
/* Quick return for non-landlocked tasks. */
@@ -96,7 +95,8 @@ static int hook_ptrace_access_check(struct task_struct *const child,
scoped_guard(rcu)
{
child_dom = landlock_get_task_domain(child);
const struct landlock_ruleset *const child_dom =
landlock_get_task_domain(child);
err = domain_ptrace(parent_subject->domain, child_dom);
}
@@ -166,15 +166,15 @@ static int hook_ptrace_traceme(struct task_struct *const parent)
}
/**
* domain_is_scoped - Checks if the client domain is scoped in the same
* domain as the server.
* domain_is_scoped - Check if an interaction from a client/sender to a
* server/receiver should be restricted based on scope controls.
*
* @client: IPC sender domain.
* @server: IPC receiver domain.
* @scope: The scope restriction criteria.
*
* Returns: True if the @client domain is scoped to access the @server,
* unless the @server is also scoped in the same domain as @client.
* Returns: True if @server is in a different domain from @client, and @client
* is scoped to access @server (i.e. access should be denied).
*/
static bool domain_is_scoped(const struct landlock_ruleset *const client,
const struct landlock_ruleset *const server,

View File

@@ -237,6 +237,7 @@ struct service_fixture {
struct sockaddr_un unix_addr;
socklen_t unix_addr_len;
};
struct sockaddr_storage _largest;
};
};

View File

@@ -4362,22 +4362,24 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
{
const char *const path = file1_s1d1;
int srv_fd, cli_fd, ruleset_fd;
socklen_t size;
struct sockaddr_un srv_un, cli_un;
struct sockaddr_un srv_un = {
.sun_family = AF_UNIX,
};
struct sockaddr_un cli_un = {
.sun_family = AF_UNIX,
};
const struct landlock_ruleset_attr attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL_DEV,
};
/* Sets up a server */
srv_un.sun_family = AF_UNIX;
strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path));
ASSERT_EQ(0, unlink(path));
srv_fd = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT_LE(0, srv_fd);
size = offsetof(struct sockaddr_un, sun_path) + strlen(srv_un.sun_path);
ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, size));
strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path));
ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, sizeof(srv_un)));
ASSERT_EQ(0, listen(srv_fd, 10 /* qlen */));
/* Enables Landlock. */
@@ -4387,24 +4389,18 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
ASSERT_EQ(0, close(ruleset_fd));
/* Sets up a client connection to it */
cli_un.sun_family = AF_UNIX;
cli_fd = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT_LE(0, cli_fd);
size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path);
ASSERT_EQ(0, bind(cli_fd, (struct sockaddr *)&cli_un, size));
bzero(&cli_un, sizeof(cli_un));
cli_un.sun_family = AF_UNIX;
strncpy(cli_un.sun_path, path, sizeof(cli_un.sun_path));
size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path);
ASSERT_EQ(0, connect(cli_fd, (struct sockaddr *)&cli_un, size));
ASSERT_EQ(0,
connect(cli_fd, (struct sockaddr *)&cli_un, sizeof(cli_un)));
/* FIONREAD and other IOCTLs should not be forbidden. */
EXPECT_EQ(0, test_fionread_ioctl(cli_fd));
ASSERT_EQ(0, close(cli_fd));
EXPECT_EQ(0, close(cli_fd));
EXPECT_EQ(0, close(srv_fd));
}
/* clang-format off */
@@ -7074,8 +7070,8 @@ static int matches_log_fs_extra(struct __test_metadata *const _metadata,
return -E2BIG;
/*
* It is assume that absolute_path does not contain control characters nor
* spaces, see audit_string_contains_control().
* It is assumed that absolute_path does not contain control
* characters nor spaces, see audit_string_contains_control().
*/
absolute_path = realpath(path, NULL);
if (!absolute_path)

View File

@@ -121,6 +121,10 @@ static socklen_t get_addrlen(const struct service_fixture *const srv,
{
switch (srv->protocol.domain) {
case AF_UNSPEC:
if (minimal)
return sizeof(sa_family_t);
return sizeof(struct sockaddr_storage);
case AF_INET:
return sizeof(srv->ipv4_addr);
@@ -758,6 +762,11 @@ TEST_F(protocol, bind_unspec)
bind_fd = socket_variant(&self->srv0);
ASSERT_LE(0, bind_fd);
/* Tries to bind with too small addrlen. */
EXPECT_EQ(-EINVAL, bind_variant_addrlen(
bind_fd, &self->unspec_any0,
get_addrlen(&self->unspec_any0, true) - 1));
/* Allowed bind on AF_UNSPEC/INADDR_ANY. */
ret = bind_variant(bind_fd, &self->unspec_any0);
if (variant->prot.domain == AF_INET) {
@@ -766,6 +775,8 @@ TEST_F(protocol, bind_unspec)
TH_LOG("Failed to bind to unspec/any socket: %s",
strerror(errno));
}
} else if (variant->prot.domain == AF_INET6) {
EXPECT_EQ(-EAFNOSUPPORT, ret);
} else {
EXPECT_EQ(-EINVAL, ret);
}
@@ -792,6 +803,8 @@ TEST_F(protocol, bind_unspec)
} else {
EXPECT_EQ(0, ret);
}
} else if (variant->prot.domain == AF_INET6) {
EXPECT_EQ(-EAFNOSUPPORT, ret);
} else {
EXPECT_EQ(-EINVAL, ret);
}
@@ -801,7 +814,8 @@ TEST_F(protocol, bind_unspec)
bind_fd = socket_variant(&self->srv0);
ASSERT_LE(0, bind_fd);
ret = bind_variant(bind_fd, &self->unspec_srv0);
if (variant->prot.domain == AF_INET) {
if (variant->prot.domain == AF_INET ||
variant->prot.domain == AF_INET6) {
EXPECT_EQ(-EAFNOSUPPORT, ret);
} else {
EXPECT_EQ(-EINVAL, ret)
@@ -892,7 +906,19 @@ TEST_F(protocol, connect_unspec)
EXPECT_EQ(0, close(ruleset_fd));
}
ret = connect_variant(connect_fd, &self->unspec_any0);
/* Try to re-disconnect with a truncated address struct. */
EXPECT_EQ(-EINVAL,
connect_variant_addrlen(
connect_fd, &self->unspec_any0,
get_addrlen(&self->unspec_any0, true) - 1));
/*
* Re-disconnect, with a minimal sockaddr struct (just a
* bare af_family=AF_UNSPEC field).
*/
ret = connect_variant_addrlen(connect_fd, &self->unspec_any0,
get_addrlen(&self->unspec_any0,
true));
if (self->srv0.protocol.domain == AF_UNIX &&
self->srv0.protocol.type == SOCK_STREAM) {
EXPECT_EQ(-EINVAL, ret);

View File

@@ -86,16 +86,9 @@ static int get_yama_ptrace_scope(void)
}
/* clang-format off */
FIXTURE(hierarchy) {};
FIXTURE(scoped_domains) {};
/* clang-format on */
FIXTURE_VARIANT(hierarchy)
{
const bool domain_both;
const bool domain_parent;
const bool domain_child;
};
/*
* Test multiple tracing combinations between a parent process P1 and a child
* process P2.
@@ -104,155 +97,18 @@ FIXTURE_VARIANT(hierarchy)
* restriction is enforced in addition to any Landlock check, which means that
* all P2 requests to trace P1 would be denied.
*/
#include "scoped_base_variants.h"
/*
* No domain
*
* P1-. P1 -> P2 : allow
* \ P2 -> P1 : allow
* 'P2
*/
/* clang-format off */
FIXTURE_VARIANT_ADD(hierarchy, allow_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(hierarchy, allow_with_one_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(hierarchy, deny_with_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(hierarchy, deny_with_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(hierarchy, allow_sibling_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(hierarchy, allow_with_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(hierarchy, deny_with_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(hierarchy, deny_with_forked_domain) {
/* clang-format on */
.domain_both = true,
.domain_parent = true,
.domain_child = true,
};
FIXTURE_SETUP(hierarchy)
FIXTURE_SETUP(scoped_domains)
{
}
FIXTURE_TEARDOWN(hierarchy)
FIXTURE_TEARDOWN(scoped_domains)
{
}
/* Test PTRACE_TRACEME and PTRACE_ATTACH for parent and child. */
TEST_F(hierarchy, trace)
TEST_F(scoped_domains, trace)
{
pid_t child, parent;
int status, err_proc_read;

View File

@@ -543,7 +543,7 @@ TEST_F(scoped_vs_unscoped, unix_scoping)
ASSERT_EQ(1, write(pipe_child[1], ".", 1));
ASSERT_EQ(grand_child, waitpid(grand_child, &status, 0));
EXPECT_EQ(0, close(stream_server_child))
EXPECT_EQ(0, close(stream_server_child));
EXPECT_EQ(0, close(dgram_server_child));
return;
}
@@ -779,7 +779,6 @@ FIXTURE_TEARDOWN(various_address_sockets)
TEST_F(various_address_sockets, scoped_pathname_sockets)
{
socklen_t size_stream, size_dgram;
pid_t child;
int status;
char buf_child, buf_parent;
@@ -798,12 +797,8 @@ TEST_F(various_address_sockets, scoped_pathname_sockets)
/* Pathname address. */
snprintf(stream_pathname_addr.sun_path,
sizeof(stream_pathname_addr.sun_path), "%s", stream_path);
size_stream = offsetof(struct sockaddr_un, sun_path) +
strlen(stream_pathname_addr.sun_path);
snprintf(dgram_pathname_addr.sun_path,
sizeof(dgram_pathname_addr.sun_path), "%s", dgram_path);
size_dgram = offsetof(struct sockaddr_un, sun_path) +
strlen(dgram_pathname_addr.sun_path);
/* Abstract address. */
memset(&stream_abstract_addr, 0, sizeof(stream_abstract_addr));
@@ -841,8 +836,9 @@ TEST_F(various_address_sockets, scoped_pathname_sockets)
/* Connects with pathname sockets. */
stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT_LE(0, stream_pathname_socket);
ASSERT_EQ(0, connect(stream_pathname_socket,
&stream_pathname_addr, size_stream));
ASSERT_EQ(0,
connect(stream_pathname_socket, &stream_pathname_addr,
sizeof(stream_pathname_addr)));
ASSERT_EQ(1, write(stream_pathname_socket, "b", 1));
EXPECT_EQ(0, close(stream_pathname_socket));
@@ -850,12 +846,13 @@ TEST_F(various_address_sockets, scoped_pathname_sockets)
dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
ASSERT_LE(0, dgram_pathname_socket);
err = sendto(dgram_pathname_socket, "c", 1, 0,
&dgram_pathname_addr, size_dgram);
&dgram_pathname_addr, sizeof(dgram_pathname_addr));
EXPECT_EQ(1, err);
/* Sends with connection. */
ASSERT_EQ(0, connect(dgram_pathname_socket,
&dgram_pathname_addr, size_dgram));
ASSERT_EQ(0,
connect(dgram_pathname_socket, &dgram_pathname_addr,
sizeof(dgram_pathname_addr)));
ASSERT_EQ(1, write(dgram_pathname_socket, "d", 1));
EXPECT_EQ(0, close(dgram_pathname_socket));
@@ -910,13 +907,13 @@ TEST_F(various_address_sockets, scoped_pathname_sockets)
stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT_LE(0, stream_pathname_socket);
ASSERT_EQ(0, bind(stream_pathname_socket, &stream_pathname_addr,
size_stream));
sizeof(stream_pathname_addr)));
ASSERT_EQ(0, listen(stream_pathname_socket, backlog));
dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
ASSERT_LE(0, dgram_pathname_socket);
ASSERT_EQ(0, bind(dgram_pathname_socket, &dgram_pathname_addr,
size_dgram));
sizeof(dgram_pathname_addr)));
/* Sets up abstract servers. */
stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0);

View File

@@ -1,8 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Landlock scoped_domains variants
* Landlock scoped_domains test variant definition.
*
* See the hierarchy variants from ptrace_test.c
* This file defines a fixture variant "scoped_domains" that has all
* permutations of parent/child process being in separate or shared
* Landlock domain, or not being in a Landlock domain at all.
*
* Scoped access tests can include this file to avoid repeating these
* combinations.
*
* Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
* Copyright © 2019-2020 ANSSI