<commit_before>// +build linux
// +build cgo

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"path"
	"strconv"
	"unsafe"

	"golang.org/x/sys/unix"

	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/netutils"
	"github.com/lxc/lxd/shared/osarch"
)

/*
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <errno.h>
#include <fcntl.h>
#include <linux/seccomp.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>

#ifndef SECCOMP_RET_USER_NOTIF
#define SECCOMP_RET_USER_NOTIF 0x7fc00000U

struct seccomp_notif_sizes {
	__u16 seccomp_notif;
	__u16 seccomp_notif_resp;
	__u16 seccomp_data;
};

struct seccomp_notif {
	__u64 id;
	__u32 pid;
	__u32 flags;
	struct seccomp_data data;
};

struct seccomp_notif_resp {
	__u64 id;
	__s64 val;
	__s32 error;
	__u32 flags;
}
#endif

struct seccomp_notify_proxy_msg {
	uint32_t version;
#ifdef SECCOMP_RET_USER_NOTIF
	struct seccomp_notif req;
	struct seccomp_notif_resp resp;
#endif // SECCOMP_RET_USER_NOTIF
	pid_t monitor_pid;
	pid_t init_pid;
};

#define SECCOMP_PROXY_MSG_SIZE (sizeof(struct seccomp_notify_proxy_msg))

#ifdef SECCOMP_RET_USER_NOTIF

static int device_allowed(dev_t dev, mode_t mode)
{
	if ((dev == makedev(0, 0)) && (mode & S_IFCHR)) // whiteout
		return 0;

	if ((dev == makedev(5, 1)) && (mode & S_IFCHR)) // /dev/console
		return 0;

	if ((dev == makedev(1, 7)) && (mode & S_IFCHR)) // /dev/full
		return 0;

	if ((dev == makedev(1, 3)) && (mode & S_IFCHR)) // /dev/null
		return 0;

	if ((dev == makedev(1, 8)) && (mode & S_IFCHR)) // /dev/random
		return 0;

	if ((dev == makedev(5, 0)) && (mode & S_IFCHR)) // /dev/tty
		return 0;

	if ((dev == makedev(1, 9)) && (mode & S_IFCHR)) // /dev/urandom
		return 0;

	if ((dev == makedev(1, 5)) && (mode & S_IFCHR)) // /dev/zero
		return 0;

	return -EPERM;
}

static int seccomp_notify_mknod_set_response(int fd_mem, struct seccomp_notify_proxy_msg *msg,
					     char *buf, size_t size,
					     mode_t *mode, dev_t *dev,
					     pid_t *pid)
{
	struct seccomp_notif *req = &msg->req;
	struct seccomp_notif_resp *resp = &msg->resp;
	int ret;
	ssize_t bytes;

	resp->id = req->id;
	resp->flags = req->flags;
	resp->val = 0;

	if (req->data.nr != __NR_mknod) {
		resp->error = -ENOSYS;
		return -1;
	}

	resp->error = device_allowed(req->data.args[2], req->data.args[1]);
	if (resp->error)
		return -1;

	bytes = pread(fd_mem, buf, size, req->data.args[0]);
	if (bytes < 0)
		return -1;

	*mode = req->data.args[1];
	*dev = req->data.args[2];
	*pid = req->pid;

	return 0;
}

static void seccomp_notify_mknod_update_response(struct seccomp_notify_proxy_msg *msg,
						 int new_neg_errno)
{
	msg->resp.error = new_neg_errno;
}
#else
static int seccomp_notify_mknod_set_response(int fd_mem, struct seccomp_notify_proxy_msg *msg,
					     char *buf, size_t size,
					     mode_t *mode, dev_t *dev,
					     pid_t *pid)
{
	errno = ENOSYS;
	return -1;
}

static void seccomp_notify_mknod_update_response(struct seccomp_notify_proxy_msg *msg,
						 int new_neg_errno)
{
}
#endif // SECCOMP_RET_USER_NOTIF
*/
// #cgo CFLAGS: -std=gnu11 -Wvla
import "C"

const SECCOMP_HEADER = `2
`

const DEFAULT_SECCOMP_POLICY = `reject_force_umount  # comment this to allow umount -f;  not recommended
[all]
kexec_load errno 38
open_by_handle_at errno 38
init_module errno 38
finit_module errno 38
delete_module errno 38
`
const SECCOMP_NOTIFY_POLICY = `mknod notify`

const COMPAT_BLOCKING_POLICY = `[%s]
compat_sys_rt_sigaction errno 38
stub_x32_rt_sigreturn errno 38
compat_sys_ioctl errno 38
compat_sys_readv errno 38
compat_sys_writev errno 38
compat_sys_recvfrom errno 38
compat_sys_sendmsg errno 38
compat_sys_recvmsg errno 38
stub_x32_execve errno 38
compat_sys_ptrace errno 38
compat_sys_rt_sigpending errno 38
compat_sys_rt_sigtimedwait errno 38
compat_sys_rt_sigqueueinfo errno 38
compat_sys_sigaltstack errno 38
compat_sys_timer_create errno 38
compat_sys_mq_notify errno 38
compat_sys_kexec_load errno 38
compat_sys_waitid errno 38
compat_sys_set_robust_list errno 38
compat_sys_get_robust_list errno 38
compat_sys_vmsplice errno 38
compat_sys_move_pages errno 38
compat_sys_preadv64 errno 38
compat_sys_pwritev64 errno 38
compat_sys_rt_tgsigqueueinfo errno 38<commit_msg>seccomp: handle mknodat<commit_after>// +build linux
// +build cgo

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"path"
	"strconv"
	"unsafe"

	"golang.org/x/sys/unix"

	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/netutils"
	"github.com/lxc/lxd/shared/osarch"
)

/*
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <errno.h>
#include <fcntl.h>
#include <linux/seccomp.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>

#ifndef SECCOMP_RET_USER_NOTIF
#define SECCOMP_RET_USER_NOTIF 0x7fc00000U

struct seccomp_notif_sizes {
	__u16 seccomp_notif;
	__u16 seccomp_notif_resp;
	__u16 seccomp_data;
};

struct seccomp_notif {
	__u64 id;
	__u32 pid;
	__u32 flags;
	struct seccomp_data data;
};

struct seccomp_notif_resp {
	__u64 id;
	__s64 val;
	__s32 error;
	__u32 flags;
}
#endif

struct seccomp_notify_proxy_msg {
	uint32_t version;
#ifdef SECCOMP_RET_USER_NOTIF
	struct seccomp_notif req;
	struct seccomp_notif_resp resp;
#endif // SECCOMP_RET_USER_NOTIF
	pid_t monitor_pid;
	pid_t init_pid;
};

#define SECCOMP_PROXY_MSG_SIZE (sizeof(struct seccomp_notify_proxy_msg))

#ifdef SECCOMP_RET_USER_NOTIF

static int device_allowed(dev_t dev, mode_t mode)
{
	if ((dev == makedev(0, 0)) && (mode & S_IFCHR)) // whiteout
		return 0;

	if ((dev == makedev(5, 1)) && (mode & S_IFCHR)) // /dev/console
		return 0;

	if ((dev == makedev(1, 7)) && (mode & S_IFCHR)) // /dev/full
		return 0;

	if ((dev == makedev(1, 3)) && (mode & S_IFCHR)) // /dev/null
		return 0;

	if ((dev == makedev(1, 8)) && (mode & S_IFCHR)) // /dev/random
		return 0;

	if ((dev == makedev(5, 0)) && (mode & S_IFCHR)) // /dev/tty
		return 0;

	if ((dev == makedev(1, 9)) && (mode & S_IFCHR)) // /dev/urandom
		return 0;

	if ((dev == makedev(1, 5)) && (mode & S_IFCHR)) // /dev/zero
		return 0;

	return -EPERM;
}

static int seccomp_notify_mknod_set_response(int fd_mem, struct seccomp_notify_proxy_msg *msg,
					     char *buf, size_t size,
					     mode_t *mode, dev_t *dev,
					     pid_t *pid)
{
	struct seccomp_notif *req = &msg->req;
	struct seccomp_notif_resp *resp = &msg->resp;
	int ret;
	ssize_t bytes;

	resp->id = req->id;
	resp->flags = req->flags;
	resp->val = 0;

	switch (req->data.nr) {
	case __NR_mknod:
		resp->error = device_allowed(req->data.args[2], req->data.args[1]);
		if (resp->error) {
			errno = EPERM;
			return -1;
		}

		bytes = pread(fd_mem, buf, size, req->data.args[0]);
		if (bytes < 0)
			return -1;

		*mode = req->data.args[1];
		*dev = req->data.args[2];
		*pid = req->pid;

		break;
	case __NR_mknodat:
		if (req->data.args[0] != AT_FDCWD) {
			errno = EINVAL;
			return -1;
		}

		resp->error = device_allowed(req->data.args[3], req->data.args[2]);
		if (resp->error) {
			errno = EPERM;
			return -EPERM;
		}

		bytes = pread(fd_mem, buf, size, req->data.args[1]);
		if (bytes < 0)
			return -1;

		*mode = req->data.args[2];
		*dev = req->data.args[3];
		*pid = req->pid;

		break;
	default:
		return -1;
	}

	return 0;
}

static void seccomp_notify_mknod_update_response(struct seccomp_notify_proxy_msg *msg,
						 int new_neg_errno)
{
	msg->resp.error = new_neg_errno;
}
#else
static int seccomp_notify_mknod_set_response(int fd_mem, struct seccomp_notify_proxy_msg *msg,
					     char *buf, size_t size,
					     mode_t *mode, dev_t *dev,
					     pid_t *pid)
{
	errno = ENOSYS;
	return -1;
}

static void seccomp_notify_mknod_update_response(struct seccomp_notify_proxy_msg *msg,
						 int new_neg_errno)
{
}
#endif // SECCOMP_RET_USER_NOTIF
*/
// #cgo CFLAGS: -std=gnu11 -Wvla
import "C"

const SECCOMP_HEADER = `2
`

const DEFAULT_SECCOMP_POLICY = `reject_force_umount  # comment this to allow umount -f;  not recommended
[all]
kexec_load errno 38
open_by_handle_at errno 38
init_module errno 38
finit_module errno 38
delete_module errno 38
`
const SECCOMP_NOTIFY_POLICY = `mknod notify
mknodat notify`

const COMPAT_BLOCKING_POLICY = `[%s]
compat_sys_rt_sigaction errno 38
stub_x32_rt_sigreturn errno 38
compat_sys_ioctl errno 38
compat_sys_readv errno 38
compat_sys_writev errno 38
compat_sys_recvfrom errno 38
compat_sys_sendmsg errno 38
compat_sys_recvmsg errno 38
stub_x32_execve errno 38
compat_sys_ptrace errno 38
compat_sys_rt_sigpending errno 38
compat_sys_rt_sigtimedwait errno 38
compat_sys_rt_sigqueueinfo errno 38
compat_sys_sigaltstack errno 38
compat_sys_timer_create errno 38
compat_sys_mq_notify errno 38
compat_sys_kexec_load errno 38
compat_sys_waitid errno 38
compat_sys_set_robust_list errno 38
compat_sys_get_robust_list errno 38
compat_sys_vmsplice errno 38
compat_sys_move_pages errno 38
compat_sys_preadv64 errno 38
compat_sys_pwritev64 errno 38
compat_sys_rt_tgsigqueueinfo errno 38
{'fraction_non_alphanumeric': 0.1210292249047014, 'fraction_numerical': 0.029966116052520118, 'mean_word_length': 4.32112676056338, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7507060', 'n_tokens_mistral': 4393, 'n_tokens_neox': 3977, 'n_words': 885}