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)