Skip to content

Commit

Permalink
Add landlock08 test
Browse files Browse the repository at this point in the history
Verify the landlock support for bind() syscall under IPV4 and IPV6
sockets. In particular, check that bind() is not assigning ad address
for a specific TCP port, if landlock didn't enforce the
LANDLOCK_ACCESS_NET_BIND_TCP rule in the current sandbox.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
  • Loading branch information
acerv committed Sep 17, 2024
1 parent eab05ac commit 736343b
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
4 changes: 4 additions & 0 deletions include/lapi/capability.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
# endif
#endif

#ifndef CAP_NET_BIND_SERVICE
# define CAP_NET_BIND_SERVICE 10
#endif

#ifndef CAP_NET_RAW
# define CAP_NET_RAW 13
#endif
Expand Down
1 change: 1 addition & 0 deletions runtest/syscalls
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,7 @@ landlock04 landlock04
landlock05 landlock05
landlock06 landlock06
landlock07 landlock07
landlock08 landlock08

lchown01 lchown01
lchown01_16 lchown01_16
Expand Down
1 change: 1 addition & 0 deletions testcases/kernel/syscalls/landlock/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ landlock04
landlock05
landlock06
landlock07
landlock08
131 changes: 131 additions & 0 deletions testcases/kernel/syscalls/landlock/landlock08.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/

/*\
* [Description]
*
* Verify the landlock support for bind() syscall under IPV4 and IPV6 sockets.
* In particular, check that bind() is not assigning an address for a
* specific TCP port, if landlock didn't enforce the
* LANDLOCK_ACCESS_NET_BIND_TCP rule in the current sandbox.
*
* [Algorithm]
*
* Repeat the following procedure for IPV4 and IPV6:
*
* - create a socket on PORT1, bind() it and check if it passes
* - enforce the current sandbox with LANDLOCK_ACCESS_NET_BIND_TCP on PORT1
* - create a socket on PORT1, bind() it and check if it passes
* - create a socket on PORT2, bind() it and check if it fails
*/

#include "landlock_common.h"

#define ADDRESS_PORT 0x7c90
#define IPV4_ADDRESS "127.0.0.1"
#define IPV6_ADDRESS "::1"

static int variants[] = {
AF_INET,
AF_INET6,
};

static struct tst_landlock_ruleset_attr *ruleset_attr;
static struct landlock_net_port_attr *net_port_attr;
static struct sockaddr_in ipv4_addr;
static struct sockaddr_in6 ipv6_addr;

static void test_bind(const int addr_family, const int port, const int exp_err)
{
struct sockaddr *sock_addr;
size_t sock_addr_size;
char *addr_str;
int sock_fd;

switch (addr_family) {
case AF_INET:
tst_init_sockaddr_inet(&ipv4_addr, IPV4_ADDRESS, port);

addr_str = IPV4_ADDRESS;
sock_addr = (struct sockaddr *)&ipv4_addr;
sock_addr_size = sizeof(struct sockaddr_in);
break;
case AF_INET6:
tst_init_sockaddr_inet6(&ipv6_addr, IPV6_ADDRESS, port);

addr_str = IPV6_ADDRESS;
sock_addr = (struct sockaddr *)&ipv6_addr;
sock_addr_size = sizeof(struct sockaddr_in6);
break;
default:
tst_brk(TBROK, "Unsupported variant");
return;
};

sock_fd = SAFE_SOCKET(addr_family, SOCK_STREAM | SOCK_CLOEXEC, 0);

tst_res(TINFO, "Socket listening on %s:%d", addr_str, port);

if (exp_err) {
TST_EXP_FAIL(bind(sock_fd, sock_addr, sock_addr_size),
exp_err, "bind() access to %s:%d",
addr_str, port);
} else {
TST_EXP_PASS(bind(sock_fd, sock_addr, sock_addr_size),
"bind() access to %s:%d",
addr_str, port);
}

SAFE_CLOSE(sock_fd);
}

static void run(void)
{
int addr_family = variants[tst_variant];

tst_res(TINFO, "Using %s protocol",
addr_family == AF_INET ? "IPV4" : "IPV6");

test_bind(addr_family, ADDRESS_PORT, 0);

tst_res(TINFO, "Enable bind() access only for port %d", ADDRESS_PORT);

apply_landlock_net_layer(ruleset_attr, net_port_attr, ADDRESS_PORT,
LANDLOCK_ACCESS_NET_BIND_TCP);

test_bind(addr_family, ADDRESS_PORT, 0);
test_bind(addr_family, ADDRESS_PORT + 0x80, EACCES);
}

static void setup(void)
{
verify_landlock_is_enabled();

ruleset_attr->data.handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP;
}

static struct tst_test test = {
.test_all = run,
.setup = setup,
.needs_root = 1,
.needs_tmpdir = 1,
.test_variants = ARRAY_SIZE(variants),
.bufs = (struct tst_buffers[]) {
{&ruleset_attr, .size = sizeof(struct tst_landlock_ruleset_attr)},
{&net_port_attr, .size = sizeof(struct landlock_net_port_attr)},
{},
},
.caps = (struct tst_cap []) {
TST_CAP(TST_CAP_REQ, CAP_SYS_ADMIN),
TST_CAP(TST_CAP_REQ, CAP_NET_BIND_SERVICE),
{}
},
.needs_kconfigs = (const char *[]) {
"CONFIG_NET=y",
"CONFIG_INET=y",
"CONFIG_IPV6=y",
NULL
}
};

0 comments on commit 736343b

Please sign in to comment.