On 23/06/2023 15:33, Tudor Cretu wrote:
As the io_event struct might contain pointers as members, introduce a compat version of the struct. Also, implement functions that convert the compat version to the native version of the struct.
A subsequent patch is going to change the io_event struct to enable it to support new architectures. On such architectures, the current struct layout still needs to be supported for compat tasks.
Signed-off-by: Tudor Cretu tudor.cretu@arm.com
fs/aio.c | 112 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 20 deletions(-)
diff --git a/fs/aio.c b/fs/aio.c index c5e850c4a4d7..8a93a9c0e59b 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -65,9 +65,8 @@ struct aio_ring { unsigned incompat_features; unsigned header_length; /* size of aio_ring */
- struct io_event io_events[];
-}; /* 128 bytes + ring size */ +}; /* 32 bytes + ring size */ /*
- Plugging is meant to work with larger batches of IOs. If we don't
@@ -165,6 +164,9 @@ struct kioctx { struct file *aio_ring_file; unsigned id; +#ifdef CONFIG_COMPAT64
- bool compat;
+#endif }; /* @@ -219,6 +221,13 @@ struct aio_kiocb { struct eventfd_ctx *ki_eventfd; }; +struct compat_io_event {
- __u64 data;
- __u64 obj;
- __s64 res;
- __s64 res2;
+};
struct compat_iocb { __u64 aio_data; #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN) @@ -281,6 +290,57 @@ static struct vfsmount *aio_mnt; static const struct file_operations aio_ring_fops; static const struct address_space_operations aio_ctx_aops; +static inline bool aio_in_compat64(struct kioctx *ctx) +{
- return IS_ENABLED(CONFIG_COMPAT64) && ctx->compat;
Missed that in v2: this won't build if COMPAT64 is not selected. You need to use an actual #ifdef now.
+}
+static inline size_t io_event_size(struct kioctx *ctx) +{
- return aio_in_compat64(ctx) ? sizeof(struct compat_io_event)
: sizeof(struct io_event);
+}
+static u32 __user *aio_key_uptr(struct kioctx *ctx,
struct iocb __user *user_iocb)
+{
- return aio_in_compat64(ctx) ?
&((struct compat_iocb __user *)user_iocb)->aio_key :
&user_iocb->aio_key;
+}
+static int copy_io_events_to_user(struct kioctx *ctx,
struct io_event __user *event_array,
long offset,
long ring_head,
Nit: should be unsigned too to be consistent.
long nr)
+{
- if (aio_in_compat64(ctx))
return copy_to_user((struct compat_io_event __user *)event_array + offset,
(struct compat_io_event *)ctx->ring->io_events + ring_head,
io_event_size(ctx) * nr);
- return copy_to_user(event_array + offset,
&ctx->ring->io_events[ring_head],
Nit: a bit confusing to have two different styles of indexing the array on consecutive lines, better choose one or the other.
Kevin