Correct sysent flags for dynamically loaded syscalls.

Using the https://github.com/google/capsicum-test/ suite, the
PosixMqueue.CapModeForked test was failing due to an ECAPMODE after
calling kmq_notify(). On further inspection, the dynamically
loaded syscall entry was initialized with sy_flags zeroed out, since
SYSCALL_INIT_HELPER() left sysent.sy_flags with the default value.

Add a new helper SYSCALL{,32}_INIT_HELPER_F() which takes an
additional argument to specify the sy_flags value.

Submitted by:	Siva Mahadevan <smahadevan@freebsdfoundation.org>
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D11576
This commit is contained in:
Konstantin Belousov 2017-07-14 09:34:44 +00:00
parent 8830260128
commit 5cead59181
5 changed files with 35 additions and 18 deletions

View File

@ -79,24 +79,31 @@ SYSCALL32_MODULE(syscallname, \
& syscallname##_syscall32, & syscallname##_sysent32,\ & syscallname##_syscall32, & syscallname##_sysent32,\
NULL, NULL); NULL, NULL);
#define SYSCALL32_INIT_HELPER(syscallname) { \ #define SYSCALL32_INIT_HELPER_F(syscallname, flags) { \
.new_sysent = { \ .new_sysent = { \
.sy_narg = (sizeof(struct syscallname ## _args ) \ .sy_narg = (sizeof(struct syscallname ## _args ) \
/ sizeof(register_t)), \ / sizeof(register_t)), \
.sy_call = (sy_call_t *)& syscallname, \ .sy_call = (sy_call_t *)& syscallname, \
.sy_flags = (flags) \
}, \ }, \
.syscall_no = FREEBSD32_SYS_##syscallname \ .syscall_no = FREEBSD32_SYS_##syscallname \
} }
#define SYSCALL32_INIT_HELPER_COMPAT(syscallname) { \ #define SYSCALL32_INIT_HELPER_COMPAT_F(syscallname, flags) { \
.new_sysent = { \ .new_sysent = { \
.sy_narg = (sizeof(struct syscallname ## _args ) \ .sy_narg = (sizeof(struct syscallname ## _args ) \
/ sizeof(register_t)), \ / sizeof(register_t)), \
.sy_call = (sy_call_t *)& sys_ ## syscallname, \ .sy_call = (sy_call_t *)& sys_ ## syscallname, \
.sy_flags = (flags) \
}, \ }, \
.syscall_no = FREEBSD32_SYS_##syscallname \ .syscall_no = FREEBSD32_SYS_##syscallname \
} }
#define SYSCALL32_INIT_HELPER(syscallname) \
SYSCALL32_INIT_HELPER_F(syscallname, 0)
#define SYSCALL32_INIT_HELPER_COMPAT(syscallname) \
SYSCALL32_INIT_HELPER_COMPAT_F(syscallname, 0)
int syscall32_register(int *offset, struct sysent *new_sysent, int syscall32_register(int *offset, struct sysent *new_sysent,
struct sysent *old_sysent, int flags); struct sysent *old_sysent, int flags);
int syscall32_deregister(int *offset, struct sysent *old_sysent); int syscall32_deregister(int *offset, struct sysent *old_sysent);

View File

@ -350,6 +350,8 @@ kill
## ##
## Allow message queue operations on file descriptors, subject to capability ## Allow message queue operations on file descriptors, subject to capability
## rights. ## rights.
## NOTE: Corresponding sysents are initialized in sys/kern/uipc_mqueue.c with
## SYF_CAPENABLED.
## ##
kmq_notify kmq_notify
kmq_setattr kmq_setattr
@ -545,6 +547,8 @@ sched_yield
## ##
## Allow I/O-related file descriptors, subject to capability rights. ## Allow I/O-related file descriptors, subject to capability rights.
## NOTE: Corresponding sysents are initialized in sys/netinet/sctp_syscalls.c
## with SYF_CAPENABLED.
## ##
sctp_generic_recvmsg sctp_generic_recvmsg
sctp_generic_sendmsg sctp_generic_sendmsg

View File

@ -2708,10 +2708,10 @@ static struct vfsconf mqueuefs_vfsconf = {
static struct syscall_helper_data mq_syscalls[] = { static struct syscall_helper_data mq_syscalls[] = {
SYSCALL_INIT_HELPER(kmq_open), SYSCALL_INIT_HELPER(kmq_open),
SYSCALL_INIT_HELPER(kmq_setattr), SYSCALL_INIT_HELPER_F(kmq_setattr, SYF_CAPENABLED),
SYSCALL_INIT_HELPER(kmq_timedsend), SYSCALL_INIT_HELPER_F(kmq_timedsend, SYF_CAPENABLED),
SYSCALL_INIT_HELPER(kmq_timedreceive), SYSCALL_INIT_HELPER_F(kmq_timedreceive, SYF_CAPENABLED),
SYSCALL_INIT_HELPER(kmq_notify), SYSCALL_INIT_HELPER_F(kmq_notify, SYF_CAPENABLED),
SYSCALL_INIT_HELPER(kmq_unlink), SYSCALL_INIT_HELPER(kmq_unlink),
SYSCALL_INIT_LAST SYSCALL_INIT_LAST
}; };
@ -2870,10 +2870,10 @@ freebsd32_kmq_notify(struct thread *td, struct freebsd32_kmq_notify_args *uap)
static struct syscall_helper_data mq32_syscalls[] = { static struct syscall_helper_data mq32_syscalls[] = {
SYSCALL32_INIT_HELPER(freebsd32_kmq_open), SYSCALL32_INIT_HELPER(freebsd32_kmq_open),
SYSCALL32_INIT_HELPER(freebsd32_kmq_setattr), SYSCALL32_INIT_HELPER_F(freebsd32_kmq_setattr, SYF_CAPENABLED),
SYSCALL32_INIT_HELPER(freebsd32_kmq_timedsend), SYSCALL32_INIT_HELPER_F(freebsd32_kmq_timedsend, SYF_CAPENABLED),
SYSCALL32_INIT_HELPER(freebsd32_kmq_timedreceive), SYSCALL32_INIT_HELPER_F(freebsd32_kmq_timedreceive, SYF_CAPENABLED),
SYSCALL32_INIT_HELPER(freebsd32_kmq_notify), SYSCALL32_INIT_HELPER_F(freebsd32_kmq_notify, SYF_CAPENABLED),
SYSCALL32_INIT_HELPER_COMPAT(kmq_unlink), SYSCALL32_INIT_HELPER_COMPAT(kmq_unlink),
SYSCALL_INIT_LAST SYSCALL_INIT_LAST
}; };

View File

@ -82,10 +82,10 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_peeloff.h> #include <netinet/sctp_peeloff.h>
static struct syscall_helper_data sctp_syscalls[] = { static struct syscall_helper_data sctp_syscalls[] = {
SYSCALL_INIT_HELPER(sctp_peeloff), SYSCALL_INIT_HELPER_F(sctp_peeloff, SYF_CAPENABLED),
SYSCALL_INIT_HELPER(sctp_generic_sendmsg), SYSCALL_INIT_HELPER_F(sctp_generic_sendmsg, SYF_CAPENABLED),
SYSCALL_INIT_HELPER(sctp_generic_sendmsg_iov), SYSCALL_INIT_HELPER_F(sctp_generic_sendmsg_iov, SYF_CAPENABLED),
SYSCALL_INIT_HELPER(sctp_generic_recvmsg), SYSCALL_INIT_HELPER_F(sctp_generic_recvmsg, SYF_CAPENABLED),
SYSCALL_INIT_LAST SYSCALL_INIT_LAST
}; };

View File

@ -230,24 +230,30 @@ struct syscall_helper_data {
int syscall_no; int syscall_no;
int registered; int registered;
}; };
#define SYSCALL_INIT_HELPER(syscallname) { \ #define SYSCALL_INIT_HELPER_F(syscallname, flags) { \
.new_sysent = { \ .new_sysent = { \
.sy_narg = (sizeof(struct syscallname ## _args ) \ .sy_narg = (sizeof(struct syscallname ## _args ) \
/ sizeof(register_t)), \ / sizeof(register_t)), \
.sy_call = (sy_call_t *)& sys_ ## syscallname, \ .sy_call = (sy_call_t *)& sys_ ## syscallname, \
.sy_auevent = SYS_AUE_##syscallname \ .sy_auevent = SYS_AUE_##syscallname, \
.sy_flags = (flags) \
}, \ }, \
.syscall_no = SYS_##syscallname \ .syscall_no = SYS_##syscallname \
} }
#define SYSCALL_INIT_HELPER_COMPAT(syscallname) { \ #define SYSCALL_INIT_HELPER_COMPAT_F(syscallname, flags) { \
.new_sysent = { \ .new_sysent = { \
.sy_narg = (sizeof(struct syscallname ## _args ) \ .sy_narg = (sizeof(struct syscallname ## _args ) \
/ sizeof(register_t)), \ / sizeof(register_t)), \
.sy_call = (sy_call_t *)& syscallname, \ .sy_call = (sy_call_t *)& syscallname, \
.sy_auevent = SYS_AUE_##syscallname \ .sy_auevent = SYS_AUE_##syscallname, \
.sy_flags = (flags) \
}, \ }, \
.syscall_no = SYS_##syscallname \ .syscall_no = SYS_##syscallname \
} }
#define SYSCALL_INIT_HELPER(syscallname) \
SYSCALL_INIT_HELPER_F(syscallname, 0)
#define SYSCALL_INIT_HELPER_COMPAT(syscallname) \
SYSCALL_INIT_HELPER_COMPAT_F(syscallname, 0)
#define SYSCALL_INIT_LAST { \ #define SYSCALL_INIT_LAST { \
.syscall_no = NO_SYSCALL \ .syscall_no = NO_SYSCALL \
} }