Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cuse(4): COMPAT_FREEBSD64 support #2238

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 74 additions & 5 deletions sys/fs/cuse/cuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
#include <sys/ptrace.h>
#include <sys/sysent.h>

#ifdef COMPAT_FREEBSD64
#include <sys/abi_compat.h>
#include <sys/sysent.h>
#endif

#include <machine/bus.h>

#include <vm/vm.h>
Expand Down Expand Up @@ -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;

Expand All @@ -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)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this up to between lines 1129 and 1130, then you don't need to check the ABI, you can just use the ioctl to determine it. Checking the ABI should only be done when the ioctls have the same encoding for both.

pcmd64 = (struct cuse_command64 *)data;
pcmd64->dev = (uint64_t)pccmd->sub.dev;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When building a hybrid kernel, cc complains about a missing __cheri_addr qualifier here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just use a uintptr_t cast instead of a uint64_t cast and then it will DTRT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have PTROUT for this

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm although that's using uintptr_t not uintcap_t (and you want the latter, as the former will be the same as uint64_t for hybrid kernels...)

CP(pccmd->sub, *pcmd64, fflags);
CP(pccmd->sub, *pcmd64, per_file_handle);
CP(pccmd->sub, *pcmd64, data_pointer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per_file_handle and data_pointer are capabilities as well, presumably these assignments also want casts with __cheri_addr?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uintcap_t doesn't need such annotations, it's always address rather than offset

CP(pccmd->sub, *pcmd64, argument);
CP(pccmd->sub, *pcmd64, command);
} else
#endif
*pcmd = pccmd->sub;

cuse_server_unlock(pcs);

Expand Down Expand Up @@ -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);
Expand All @@ -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 */

Expand Down Expand Up @@ -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);

Expand All @@ -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);
}

/*
Expand Down
37 changes: 37 additions & 0 deletions sys/fs/cuse/cuse_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@
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;
Expand All @@ -61,6 +69,17 @@
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;
Expand All @@ -69,11 +88,29 @@
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)

Check warning on line 113 in sys/fs/cuse/cuse_ioctl.h

View workflow job for this annotation

GitHub Actions / Style Checker

Missing Signed-off-by: line
#define CUSE_IOCTL_SYNC_COMMAND _IOW('C', 3, int)
#define CUSE_IOCTL_GET_SIG _IOR('C', 4, int)
#define CUSE_IOCTL_ALLOC_MEMORY _IOW('C', 5, struct cuse_alloc_info)
Expand Down
Loading