All of lore.kernel.org
 help / color / mirror / Atom feed
* Help with LANDLOCK_ACCESS_FS_EXECUTE
@ 2024-07-01 14:25 Andrea Cervesato
  2024-07-01 15:16 ` Mickaël Salaün
  0 siblings, 1 reply; 3+ messages in thread
From: Andrea Cervesato @ 2024-07-01 14:25 UTC (permalink / raw)
  To: landlock

[-- Attachment #1: Type: text/plain, Size: 835 bytes --]

Hi all,

I'm actually writing a test for LANDLOCK_ACCESS_FS_EXECUTE flag in LTP [1].
The test is really simple: it applies the EXECUTE landlock rule inside a 
folder and it verifies that a binary inside it can be executed.
A similar test applies the rule only to the specific binary and check 
again its execution.

But while I was writing the test, I encountered an issue with the 
specific rule setup, since EACCES is raised unexpectedly during binary 
execution.
So I wrote a reproducer, assuming that LTP might be the issue, but it's 
not. The reproducer actually shows that binary can't be executed after 
applying the EXECUTE rule.

I will attach the source code to this email. Can you please tell me if 
there's something wrong with it?

Best regards,
Andrea Cervesato


[1] https://linux-test-project.readthedocs.io/en/latest/

[-- Attachment #2: exec-tester.c --]
[-- Type: text/x-csrc, Size: 3207 bytes --]

/*
 * Compile with:
 *    gcc -lc exec-tester.c -o exec-tester
 *
 * Ensure that "landlock_exec" is present and it's executable via "execve".
 * Can be a compiled source like:
 *
 *    int main(void) { return 0; }
 */

#define _GNU_SOURCE

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <linux/landlock.h>

#define FILE_EXEC "landlock_exec"

static inline int landlock_create_ruleset(const struct landlock_ruleset_attr *attr,
	size_t size, uint32_t flags)
{
	return syscall(SYS_landlock_create_ruleset,
		attr, size, flags);
}

static inline int landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type,
	const void *rule_attr, uint32_t flags)
{
	return syscall(SYS_landlock_add_rule,
		ruleset_fd, rule_type, rule_attr, flags);
}

static inline int landlock_restrict_self(int ruleset_fd, int flags)
{
	return syscall(SYS_landlock_restrict_self,
		ruleset_fd, flags);
}

static void run_test(const int with_landlock)
{
	int rval;
	pid_t pid;
	int status;
	int fd = -1;
	int ruleset_fd = -1;

	if (with_landlock) {
		struct landlock_ruleset_attr ruleset_attr = {
			.handled_access_fs =
				LANDLOCK_ACCESS_FS_EXECUTE |
				LANDLOCK_ACCESS_FS_WRITE_FILE |
				LANDLOCK_ACCESS_FS_READ_FILE
		};

		ruleset_fd = landlock_create_ruleset(
			&ruleset_attr, sizeof(struct landlock_ruleset_attr), 0);
		if (ruleset_fd == -1) {
			printf("landlock_create_ruleset() error %s\n", strerror(errno));
			goto end;
		}

		fd = open(FILE_EXEC, O_PATH | O_CLOEXEC, 0744);
		if (fd == -1) {
			printf("Can't open file '%s'\n", FILE_EXEC);
			goto end;
		}

		struct landlock_path_beneath_attr path_beneath_attr = {
			.allowed_access = LANDLOCK_ACCESS_FS_EXECUTE,
			.parent_fd = fd,
		};

		rval = landlock_add_rule(
			ruleset_fd,
			LANDLOCK_RULE_PATH_BENEATH,
			&path_beneath_attr,
			0);
		if (rval == -1) {
			printf("landlock_add_rule error: %s\n", strerror(errno));
			goto end;
		}

		rval = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
		if (rval == -1) {
			printf("prctl error\n");
			goto end;
		}

		rval = landlock_restrict_self(ruleset_fd, 0);
		if (rval == -1) {
			printf("landlock_restrict_self error: %s\n", strerror(errno));
			goto end;
		}
	}

	pid = fork();
	if (pid == -1) {
		printf("execve() error: %s\n", strerror(errno));
		goto end;
	}

	if (!pid) {
		char *args[] = {(char *)FILE_EXEC, NULL};

		rval = execve(FILE_EXEC, args, NULL);
		if (rval == -1)
			printf("Failed to execute test binary: %s\n", strerror(errno));

		_exit(1);
	}

	waitpid(pid, &status, 0);
	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
		goto end;

	printf("Binary executed\n");

end:
	if (ruleset_fd != -1)
		close(ruleset_fd);

	if (fd != -1)
		close(fd);
}

int main(void)
{
	printf("\nTesting LANDLOCK_ACCESS_FS_EXECUTE functionality\n\n");
	printf("----------------------------------------\n");
	printf("\tRunning test without landlock\n");
	printf("\t");
	run_test(0);
	printf("\n");

	printf("----------------------------------------\n");
	printf("\tRunning test with landlock activated\n");
	printf("\t");
	run_test(1);
	printf("\n");

	return 0;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-07-17  8:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-01 14:25 Help with LANDLOCK_ACCESS_FS_EXECUTE Andrea Cervesato
2024-07-01 15:16 ` Mickaël Salaün
2024-07-17  8:51   ` Günther Noack

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.