Module Name: src Committed By: thorpej Date: Sun Sep 19 17:33:39 UTC 2021
Modified Files: src/sys/compat/linux/common: linux_sigevent.h linux_signal.c Log Message: - LINUX_SIGEV_PAD is incorrect for 64-bit systems, because sigval_t contains a pointer. Correct this. - Add routines to convert from Linux to native sigevent_t. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/compat/linux/common/linux_sigevent.h cvs rdiff -u -r1.84 -r1.85 src/sys/compat/linux/common/linux_signal.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/compat/linux/common/linux_sigevent.h diff -u src/sys/compat/linux/common/linux_sigevent.h:1.2 src/sys/compat/linux/common/linux_sigevent.h:1.3 --- src/sys/compat/linux/common/linux_sigevent.h:1.2 Mon Apr 28 20:23:44 2008 +++ src/sys/compat/linux/common/linux_sigevent.h Sun Sep 19 17:33:39 2021 @@ -37,13 +37,16 @@ #define LINUX_SIGEV_MAX 64 #ifndef LINUX_SIGEV_PAD -#define LINUX_SIGEV_PAD ((LINUX_SIGEV_MAX/sizeof(int)) - 3) +#define LINUX_SIGEV_PAD ((LINUX_SIGEV_MAX - \ + (sizeof(sigval_t) + (sizeof(int) * 2))) / \ + sizeof(int)) #endif typedef struct linux_sigevent { - sigval_t sigev_value; + sigval_t sigev_value; /* sizeof(pointer) */ int sigev_signo; int sigev_notify; + /* guaranteed to have natural pointer alignment */ union { int pad[LINUX_SIGEV_PAD]; int tid; @@ -54,4 +57,8 @@ typedef struct linux_sigevent { } _sigev_un; } linux_sigevent_t; +int linux_to_native_sigevent(struct sigevent *, + const struct linux_sigevent *); +int linux_sigevent_copyin(const void *, void *, size_t); + #endif /* _LINUX_SIGEVENT_H */ Index: src/sys/compat/linux/common/linux_signal.c diff -u src/sys/compat/linux/common/linux_signal.c:1.84 src/sys/compat/linux/common/linux_signal.c:1.85 --- src/sys/compat/linux/common/linux_signal.c:1.84 Tue Sep 7 11:43:04 2021 +++ src/sys/compat/linux/common/linux_signal.c Sun Sep 19 17:33:39 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_signal.c,v 1.84 2021/09/07 11:43:04 riastradh Exp $ */ +/* $NetBSD: linux_signal.c,v 1.85 2021/09/19 17:33:39 thorpej Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.84 2021/09/07 11:43:04 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.85 2021/09/19 17:33:39 thorpej Exp $"); #define COMPAT_LINUX 1 @@ -852,3 +852,50 @@ native_to_linux_si_status(int code, int return sts; } + +int +linux_to_native_sigevent(struct sigevent *nsep, + const struct linux_sigevent *lsep) +{ + memset(nsep, 0, sizeof(*nsep)); + + switch (lsep->sigev_notify) { + case LINUX_SIGEV_SIGNAL: + nsep->sigev_notify = SIGEV_SIGNAL; + break; + + case LINUX_SIGEV_NONE: + nsep->sigev_notify = SIGEV_NONE; + break; + + case LINUX_SIGEV_THREAD: + case LINUX_SIGEV_THREAD_ID: + default: + return ENOTSUP; + } + + nsep->sigev_value = lsep->sigev_value; + if (lsep->sigev_signo < 0 || lsep->sigev_signo >= LINUX__NSIG) { + return EINVAL; + } + nsep->sigev_signo = linux_to_native_signo[lsep->sigev_signo]; + + return 0; +} + +int +linux_sigevent_copyin(const void *src, void *dst, size_t size) +{ + struct linux_sigevent lse; + struct sigevent *sep = dst; + int error; + + KASSERT(size == sizeof(*sep)); + + error = copyin(src, &lse, sizeof(lse)); + if (error) { + return error; + } + + return linux_to_native_sigevent(sep, &lse); +}