diff options
author | Luca Dariz <luca@orpolo.org> | 2023-01-16 11:58:52 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2023-01-18 02:20:37 +0100 |
commit | 8ddf8e991c0d271d2681627fab08e6730ae73ae0 (patch) | |
tree | 77890e44218b0f75d1067c61f04df8cf6ad189d5 /i386 | |
parent | cc05ed085b731232a2436efcaf03aa1e92ad20be (diff) | |
download | gnumach-8ddf8e991c0d271d2681627fab08e6730ae73ae0.tar.gz gnumach-8ddf8e991c0d271d2681627fab08e6730ae73ae0.tar.bz2 gnumach-8ddf8e991c0d271d2681627fab08e6730ae73ae0.zip |
x86_64: expand and shrink messages in copy{in, out}msg routines
* i386/i386/copy_user.h: new file to handle 32/64 bit differences
- add msg_usize() to recontruct the user-space message size
- add copyin/copyout helpers for addresses and ports
* include/mach/message.h: add msg alignment macros
* ipc/ipc_kmsg.c:
- copyin/out ports names instead of using pointer magic
* ipc/ipc_mqueue.c: use msg_usize() to check if we can actually
receive the message
* ipc/mach_msg.c: Likewise for continuations in receive path
* x86_64/Makefrag.am: add x86_64/copy_user.c
* x86_64/copy_user.c: new file to handle message expansion and
shrinking during copyinmsg/copyoutmsg for 64 bit kernels.
- port names -> port pointers on all 64-bit builds
- 32-bit pointer -> 64 bit pointer when using 32-bit userspace
* x86_64/locore.S: remove copyinmsg() and copyoutmsg()
Message-Id: <20230116105857.240210-3-luca@orpolo.org>
Diffstat (limited to 'i386')
-rw-r--r-- | i386/i386/copy_user.h | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/i386/i386/copy_user.h b/i386/i386/copy_user.h new file mode 100644 index 00000000..c7e8b4e1 --- /dev/null +++ b/i386/i386/copy_user.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2023 Free Software Foundation + * + * This program is free software ; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation ; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY ; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the program ; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef COPY_USER_H +#define COPY_USER_H + +#include <stdint.h> +#include <sys/types.h> + +#include <machine/locore.h> +#include <mach/message.h> + +/* + * The copyin_32to64() and copyout_64to32() routines are meant for data types + * that have different size in kernel and user space. They should be independent + * of endianness and hopefully can be reused in the future on other archs. + * These types are e.g.: + * - port names vs port pointers, on a 64-bit kernel + * - memory addresses, on a 64-bit kernel and 32-bit user + */ + +static inline int copyin_32to64(const uint32_t *uaddr, uint64_t *kaddr) +{ + uint32_t rkaddr; + int ret; + ret = copyin(uaddr, &rkaddr, sizeof(uint32_t)); + if (ret) + return ret; + *kaddr = rkaddr; + return 0; +} + +static inline int copyout_64to32(const uint64_t *kaddr, uint32_t *uaddr) +{ + uint32_t rkaddr=*kaddr; + return copyout(&rkaddr, uaddr, sizeof(uint32_t)); +} + +static inline int copyin_address(const rpc_vm_offset_t *uaddr, vm_offset_t *kaddr) +{ +#ifdef USER32 + return copyin_32to64(uaddr, kaddr); +#else /* USER32 */ + return copyin(uaddr, kaddr, sizeof(*uaddr)); +#endif /* USER32 */ +} + +static inline int copyout_address(const vm_offset_t *kaddr, rpc_vm_offset_t *uaddr) +{ +#ifdef USER32 + return copyout_64to32(kaddr, uaddr); +#else /* USER32 */ + return copyout(kaddr, uaddr, sizeof(*kaddr)); +#endif /* USER32 */ +} + +static inline int copyin_port(const mach_port_name_t *uaddr, mach_port_t *kaddr) +{ +#ifdef __x86_64 + return copyin_32to64(uaddr, kaddr); +#else /* __x86_64__ */ + return copyin(uaddr, kaddr, sizeof(*uaddr)); +#endif /* __x86_64__ */ +} + +static inline int copyout_port(const mach_port_t *kaddr, mach_port_name_t *uaddr) +{ +#ifdef __x86_64 + return copyout_64to32(kaddr, uaddr); +#else /* __x86_64__ */ + return copyout(kaddr, uaddr, sizeof(*kaddr)); +#endif /* __x86_64__ */ +} + +// XXX we could add another field to kmsg to store the user-side size, but then we +// should check if we can obtain it for rpc and notifications originating from +// the kernel +#ifndef __x86_64__ +static inline size_t msg_usize(const mach_msg_header_t *kmsg) +{ + return kmsg->msgh_size; +} +#else /* __x86_64__ */ +size_t msg_usize(const mach_msg_header_t *kmsg); +#endif /* __x86_64__ */ + +#endif /* COPY_USER_H */ |