From 7db784b01b6d0ce419e2a8ce119b4dd0dc2a5eca Mon Sep 17 00:00:00 2001
From: Ruslan Bukin
Date: Tue, 22 Oct 2024 13:50:51 +0100
Subject: [PATCH] COMPAT_FREEBSD64 support to cuse.ko
---
sys/fs/cuse/cuse.c | 79 +++++++++++++++++++++++++++++++++++++---
sys/fs/cuse/cuse_ioctl.h | 37 +++++++++++++++++++
2 files changed, 111 insertions(+), 5 deletions(-)
diff --git a/sys/fs/cuse/cuse.c b/sys/fs/cuse/cuse.c
index 05c4d005278b..78c664a9d846 100644
--- a/sys/fs/cuse/cuse.c
+++ b/sys/fs/cuse/cuse.c
@@ -52,6 +52,11 @@
#include
#include
+#ifdef COMPAT_FREEBSD64
+#include
+#include
+#endif
+
#include
#include
@@ -1109,8 +1114,19 @@ cuse_server_ioctl(struct cdev *dev, unsigned long cmd,
struct cuse_create_dev *pcd;
struct cuse_server_dev *pcsd;
struct cuse_data_chunk *pchk;
+#ifdef COMPAT_FREEBSD64
+ struct cuse_command64 *pcmd64;
+ struct cuse_create_dev64 *pcd64;
+ struct cuse_create_dev local_pcd;
+ struct cuse_data_chunk64 *pchk64;
+ struct cuse_data_chunk local_pchk;
+#endif
int n;
+ bool isread;
+#ifdef COMPAT_FREEBSD64
+ case CUSE_IOCTL_GET_COMMAND64:
+#endif
case CUSE_IOCTL_GET_COMMAND:
pcmd = (void *)data;
@@ -1133,7 +1149,18 @@ cuse_server_ioctl(struct cdev *dev, unsigned long cmd,
pccmd->entered = curthread;
- *pcmd = pccmd->sub;
+#ifdef COMPAT_FREEBSD64
+ if (!SV_CURPROC_FLAG(SV_CHERI)) {
+ pcmd64 = (struct cuse_command64 *)data;
+ pcmd64->dev = (uint64_t)pccmd->sub.dev;
+ CP(pccmd->sub, *pcmd64, fflags);
+ CP(pccmd->sub, *pcmd64, per_file_handle);
+ CP(pccmd->sub, *pcmd64, data_pointer);
+ CP(pccmd->sub, *pcmd64, argument);
+ CP(pccmd->sub, *pcmd64, command);
+ } else
+#endif
+ *pcmd = pccmd->sub;
cuse_server_unlock(pcs);
@@ -1247,6 +1274,9 @@ cuse_server_ioctl(struct cdev *dev, unsigned long cmd,
break;
+#ifdef COMPAT_FREEBSD64
+ case CUSE_IOCTL_SET_PFH64:
+#endif
case CUSE_IOCTL_SET_PFH:
cuse_server_lock(pcs);
@@ -1263,13 +1293,27 @@ cuse_server_ioctl(struct cdev *dev, unsigned long cmd,
cuse_server_unlock(pcs);
break;
+#ifdef COMPAT_FREEBSD64
+ case CUSE_IOCTL_CREATE_DEV64:
+#endif
case CUSE_IOCTL_CREATE_DEV:
error = priv_check(curthread, PRIV_DRIVER);
if (error)
break;
- pcd = (void *)data;
+#ifdef COMPAT_FREEBSD64
+ if (!SV_CURPROC_FLAG(SV_CHERI)) {
+ pcd64 = (struct cuse_create_dev64 *)data;
+ pcd = &local_pcd;
+ pcd->dev = __USER_CAP(pcd64->dev, sizeof(struct cdev));
+ CP(*pcd64, *pcd, user_id);
+ CP(*pcd64, *pcd, group_id);
+ CP(*pcd64, *pcd, permissions);
+ memcpy(pcd->devname, pcd64->devname, 80);
+ } else
+#endif
+ pcd = (void *)data;
/* filter input */
@@ -1335,11 +1379,36 @@ cuse_server_ioctl(struct cdev *dev, unsigned long cmd,
cuse_server_unlock(pcs);
break;
+#ifdef COMPAT_FREEBSD64
+ case CUSE_IOCTL_WRITE_DATA64:
+ case CUSE_IOCTL_READ_DATA64:
+#endif
case CUSE_IOCTL_WRITE_DATA:
case CUSE_IOCTL_READ_DATA:
+#ifdef COMPAT_FREEBSD64
+ if (cmd == CUSE_IOCTL_READ_DATA ||
+ cmd == CUSE_IOCTL_READ_DATA64)
+#else
+ if (cmd == CUSE_IOCTL_READ_DATA)
+#endif
+ isread = true;
+ else
+ isread = false;
+
cuse_server_lock(pcs);
- pchk = (struct cuse_data_chunk *)data;
+#ifdef COMPAT_FREEBSD64
+ if (!SV_CURPROC_FLAG(SV_CHERI)) {
+ pchk64 = (struct cuse_data_chunk64 *)data;
+ pchk = &local_pchk;
+ CP(*pchk64, *pchk, length);
+ pchk->local_ptr = (kuintcap_t)__USER_CAP(
+ pchk64->local_ptr, pchk64->length);
+ pchk->peer_ptr = (kuintcap_t)__USER_CAP(
+ pchk64->peer_ptr, pchk64->length);
+ } else
+#endif
+ pchk = (struct cuse_data_chunk *)data;
pccmd = cuse_server_find_command(pcs, curthread);
@@ -1351,10 +1420,10 @@ cuse_server_ioctl(struct cdev *dev, unsigned long cmd,
/* NOP */
} else if (pchk->peer_ptr < CUSE_BUF_MAX_PTR) {
error = cuse_server_ioctl_copy_locked(pcs, pccmd,
- pchk, cmd == CUSE_IOCTL_READ_DATA);
+ pchk, isread);
} else {
error = cuse_server_data_copy_optimized_locked(
- pcs, pccmd, pchk, cmd == CUSE_IOCTL_READ_DATA);
+ pcs, pccmd, pchk, isread);
}
/*
diff --git a/sys/fs/cuse/cuse_ioctl.h b/sys/fs/cuse/cuse_ioctl.h
index a7d0396eb3f0..e42dd425d63e 100644
--- a/sys/fs/cuse/cuse_ioctl.h
+++ b/sys/fs/cuse/cuse_ioctl.h
@@ -47,6 +47,14 @@ struct cuse_data_chunk {
unsigned long length;
};
+#ifdef COMPAT_FREEBSD64
+struct cuse_data_chunk64 {
+ uint64_t local_ptr;
+ uint64_t peer_ptr;
+ unsigned long length;
+};
+#endif
+
struct cuse_alloc_info {
unsigned long page_count;
unsigned long alloc_nr;
@@ -61,6 +69,17 @@ struct cuse_command {
unsigned long command; /* see CUSE_CMD_XXX */
};
+#ifdef COMPAT_FREEBSD64
+struct cuse_command64 {
+ uint64_t dev;
+ unsigned long fflags;
+ uint64_t per_file_handle;
+ uint64_t data_pointer;
+ unsigned long argument;
+ unsigned long command; /* see CUSE_CMD_XXX */
+};
+#endif
+
struct cuse_create_dev {
struct cuse_dev * __kerncap dev;
uid_t user_id;
@@ -69,8 +88,26 @@ struct cuse_create_dev {
char devname[80]; /* /dev/xxxxx */
};
+#ifdef COMPAT_FREEBSD64
+struct cuse_create_dev64 {
+ uint64_t dev;
+ uid_t user_id;
+ gid_t group_id;
+ int permissions;
+ char devname[80]; /* /dev/xxxxx */
+};
+#endif
+
/* Definition of internal IOCTLs for /dev/cuse */
+#ifdef COMPAT_FREEBSD64
+#define CUSE_IOCTL_GET_COMMAND64 _IOR('C', 0, struct cuse_command64)
+#define CUSE_IOCTL_WRITE_DATA64 _IOW('C', 1, struct cuse_data_chunk64)
+#define CUSE_IOCTL_READ_DATA64 _IOW('C', 2, struct cuse_data_chunk64)
+#define CUSE_IOCTL_CREATE_DEV64 _IOW('C', 8, struct cuse_create_dev64)
+#define CUSE_IOCTL_SET_PFH64 _IOW('C', 7, uint64_t)
+#endif
+
#define CUSE_IOCTL_GET_COMMAND _IOR('C', 0, struct cuse_command)
#define CUSE_IOCTL_WRITE_DATA _IOW('C', 1, struct cuse_data_chunk)
#define CUSE_IOCTL_READ_DATA _IOW('C', 2, struct cuse_data_chunk)