diff --git a/headers/private/kernel/syscall_restart.h b/headers/private/kernel/syscall_restart.h index 4f2eeee1ec..1735e33d59 100644 --- a/headers/private/kernel/syscall_restart.h +++ b/headers/private/kernel/syscall_restart.h @@ -90,69 +90,73 @@ syscall_restart_handle_post(status_t error) static inline bool -syscall_restart_ioctl_is_restarted() +syscall_restart_is_restarted() { struct thread* thread = thread_get_current_thread(); - return (thread->flags & THREAD_FLAGS_IOCTL_SYSCALL) != 0 + return (thread->flags & THREAD_FLAGS_SYSCALL) != 0 && (thread->flags & THREAD_FLAGS_SYSCALL_RESTARTED) != 0; } -static inline status_t -syscall_restart_ioctl_handle_post(status_t error) -{ - if (error == B_INTERRUPTED) { - // interrupted -- set flag for syscall restart - struct thread* thread = thread_get_current_thread(); - if ((thread->flags & THREAD_FLAGS_IOCTL_SYSCALL) != 0) - atomic_or(&thread->flags, THREAD_FLAGS_RESTART_SYSCALL); +struct SyscallFlagUnsetter { + SyscallFlagUnsetter() + { + fThread = thread_get_current_thread(); + fWasSyscall = (atomic_and(&fThread->flags, ~THREAD_FLAGS_SYSCALL) + & THREAD_FLAGS_SYSCALL) != 0; } - return error; -} - - -struct IoctlSyscallFlagUnsetter { - IoctlSyscallFlagUnsetter() + ~SyscallFlagUnsetter() { - struct thread *thread = thread_get_current_thread(); - fWasSyscall = (atomic_and(&thread->flags, ~THREAD_FLAGS_IOCTL_SYSCALL) - & THREAD_FLAGS_IOCTL_SYSCALL) != 0; - } - - ~IoctlSyscallFlagUnsetter() - { - struct thread *thread = thread_get_current_thread(); if (fWasSyscall) - atomic_or(&thread->flags, THREAD_FLAGS_IOCTL_SYSCALL); + atomic_or(&fThread->flags, THREAD_FLAGS_SYSCALL); } private: - bool fWasSyscall; + struct thread* fThread; + bool fWasSyscall; }; template -struct IoctlSyscallRestartWrapper { - IoctlSyscallRestartWrapper(const Type& result) - : fResult(result) +struct SyscallRestartWrapper { + SyscallRestartWrapper(Type initialValue = 0) + : fResult(initialValue) { - struct thread *thread = thread_get_current_thread(); - atomic_or(&thread->flags, THREAD_FLAGS_IOCTL_SYSCALL); + fThread = thread_get_current_thread(); + atomic_or(&fThread->flags, THREAD_FLAGS_SYSCALL); } - ~IoctlSyscallRestartWrapper() + ~SyscallRestartWrapper() { - struct thread *thread = thread_get_current_thread(); - atomic_and(&thread->flags, ~THREAD_FLAGS_IOCTL_SYSCALL); + atomic_and(&fThread->flags, ~THREAD_FLAGS_SYSCALL); - if (fResult < 0) - syscall_restart_ioctl_handle_post(fResult); + if (fResult == B_INTERRUPTED) { + // interrupted -- set flag for syscall restart + if ((fThread->flags & THREAD_FLAGS_SYSCALL) != 0) + atomic_or(&fThread->flags, THREAD_FLAGS_RESTART_SYSCALL); + } } + SyscallRestartWrapper& operator=(const Type& other) + { + fResult = other; + return *this; + } + + bool operator==(const Type& other) const { return fResult == other; } + bool operator!=(const Type& other) const { return fResult != other; } + bool operator<=(const Type& other) const { return fResult <= other; } + bool operator>=(const Type& other) const { return fResult >= other; } + bool operator<(const Type& other) const { return fResult < other; } + bool operator>(const Type& other) const { return fResult > other; } + + operator Type() const { return fResult; } + private: - const Type& fResult; + Type fResult; + struct thread* fThread; }; diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index 567b0d95e5..3ef4532423 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -311,7 +311,8 @@ struct thread_queue { #define THREAD_FLAGS_RESTART_SYSCALL 0x0040 #define THREAD_FLAGS_DONT_RESTART_SYSCALL 0x0080 #define THREAD_FLAGS_SYSCALL_RESTARTED 0x0100 -#define THREAD_FLAGS_IOCTL_SYSCALL 0x0200 +#define THREAD_FLAGS_SYSCALL 0x0200 + // Note: Set only for certain syscalls. #endif /* _KERNEL_THREAD_TYPES_H */ diff --git a/headers/private/net/net_socket.h b/headers/private/net/net_socket.h index 7231bcd900..2e7d8c23c9 100644 --- a/headers/private/net/net_socket.h +++ b/headers/private/net/net_socket.h @@ -53,7 +53,7 @@ struct net_socket_module_info { status_t (*writev)(net_socket *socket, const iovec *vecs, size_t vecCount, size_t *_length); status_t (*control)(net_socket *socket, int32 op, void *data, - size_t length, bool kernel); + size_t length); ssize_t (*read_avail)(net_socket *socket); ssize_t (*send_avail)(net_socket *socket); diff --git a/headers/private/net/net_stack.h b/headers/private/net/net_stack.h index a5a5a572c4..1ca720f95e 100644 --- a/headers/private/net/net_stack.h +++ b/headers/private/net/net_stack.h @@ -135,6 +135,7 @@ struct net_stack_module_info { bool (*is_timer_active)(struct net_timer *timer); // syscall restart + bool (*is_syscall)(void); bool (*is_restarted_syscall)(void); void (*store_syscall_restart_timeout)(bigtime_t timeout); bigtime_t (*restore_syscall_restart_timeout)(void); diff --git a/headers/private/net/net_stack_interface.h b/headers/private/net/net_stack_interface.h index 34f3f7b32e..b641bc82e8 100644 --- a/headers/private/net/net_stack_interface.h +++ b/headers/private/net/net_stack_interface.h @@ -29,29 +29,27 @@ struct net_stack_interface_module_info { status_t (*free)(net_socket* socket); status_t (*bind)(net_socket* socket, const struct sockaddr* address, - socklen_t addressLength, bool kernel); + socklen_t addressLength); status_t (*shutdown)(net_socket* socket, int how); status_t (*connect)(net_socket* socket, const struct sockaddr* address, - socklen_t addressLength, bool kernel); + socklen_t addressLength); status_t (*listen)(net_socket* socket, int backlog); status_t (*accept)(net_socket* socket, struct sockaddr* address, socklen_t* _addressLength, net_socket** _acceptedSocket); - ssize_t (*recv)(net_socket* socket, void* data, size_t length, int flags, - bool kernel); + ssize_t (*recv)(net_socket* socket, void* data, size_t length, int flags); ssize_t (*recvfrom)(net_socket* socket, void* data, size_t length, int flags, struct sockaddr* address, - socklen_t* _addressLength, bool kernel); - ssize_t (*recvmsg)(net_socket* socket, struct msghdr* message, int flags, - bool kernel); + socklen_t* _addressLength); + ssize_t (*recvmsg)(net_socket* socket, struct msghdr* message, int flags); ssize_t (*send)(net_socket* socket, const void* data, size_t length, - int flags, bool kernel); + int flags); ssize_t (*sendto)(net_socket* socket, const void* data, size_t length, int flags, const struct sockaddr* address, - socklen_t addressLength, bool kernel); + socklen_t addressLength); ssize_t (*sendmsg)(net_socket* socket, const struct msghdr* message, - int flags, bool kernel); + int flags); status_t (*getsockopt)(net_socket* socket, int level, int option, void* value, socklen_t* _length); @@ -69,7 +67,7 @@ struct net_stack_interface_module_info { net_socket* _sockets[2]); status_t (*ioctl)(net_socket* socket, uint32 op, void *buffer, - size_t length, bool kernel); + size_t length); status_t (*select)(net_socket* socket, uint8 event, struct selectsync *sync); status_t (*deselect)(net_socket* socket, uint8 event, diff --git a/src/add-ons/kernel/network/stack/net_socket.cpp b/src/add-ons/kernel/network/stack/net_socket.cpp index c838d68539..9cdff52758 100644 --- a/src/add-ons/kernel/network/stack/net_socket.cpp +++ b/src/add-ons/kernel/network/stack/net_socket.cpp @@ -30,6 +30,8 @@ #include #include +#include "utility.h" + struct net_socket_private : net_socket { struct list_link link; @@ -243,8 +245,7 @@ socket_writev(net_socket *socket, const iovec *vecs, size_t vecCount, status_t -socket_control(net_socket *socket, int32 op, void *data, size_t length, - bool kernel) +socket_control(net_socket *socket, int32 op, void *data, size_t length) { switch (op) { case FIONBIO: @@ -253,14 +254,14 @@ socket_control(net_socket *socket, int32 op, void *data, size_t length, return B_BAD_VALUE; int value; - if (kernel) { - value = *(int*)data; - } else { + if (is_syscall()) { if (!IS_USER_ADDRESS(data) || user_memcpy(&value, data, sizeof(int)) != B_OK) { return B_BAD_ADDRESS; } - } + } else + value = *(int*)data; + return socket_setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &value, sizeof(int)); } diff --git a/src/add-ons/kernel/network/stack/stack.cpp b/src/add-ons/kernel/network/stack/stack.cpp index 1363f02183..7cf6be04f2 100644 --- a/src/add-ons/kernel/network/stack/stack.cpp +++ b/src/add-ons/kernel/network/stack/stack.cpp @@ -918,6 +918,7 @@ net_stack_module_info gNetStackModule = { cancel_timer, is_timer_active, + is_syscall, is_restarted_syscall, store_syscall_restart_timeout, restore_syscall_restart_timeout, diff --git a/src/add-ons/kernel/network/stack/stack_interface.cpp b/src/add-ons/kernel/network/stack/stack_interface.cpp index 4d62487ad6..67ec0c5e7a 100644 --- a/src/add-ons/kernel/network/stack/stack_interface.cpp +++ b/src/add-ons/kernel/network/stack/stack_interface.cpp @@ -1,5 +1,7 @@ - - +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ #include "stack_private.h" @@ -31,9 +33,8 @@ stack_interface_free(net_socket* socket) static status_t stack_interface_bind(net_socket* socket, const struct sockaddr* address, - socklen_t addressLength, bool kernel) + socklen_t addressLength) { -// TODO: Pass kernel flag! return gNetSocketModule.bind(socket, address, addressLength); } @@ -47,9 +48,8 @@ stack_interface_shutdown(net_socket* socket, int how) static status_t stack_interface_connect(net_socket* socket, const struct sockaddr* address, - socklen_t addressLength, bool kernel) + socklen_t addressLength) { -// TODO: Pass kernel flag! return gNetSocketModule.connect(socket, address, addressLength); } @@ -71,17 +71,15 @@ stack_interface_accept(net_socket* socket, struct sockaddr* address, static ssize_t -stack_interface_recv(net_socket* socket, void* data, size_t length, int flags, - bool kernel) +stack_interface_recv(net_socket* socket, void* data, size_t length, int flags) { -// TODO: Pass kernel flag! return gNetSocketModule.receive(socket, NULL, data, length, flags); } static ssize_t stack_interface_recvfrom(net_socket* socket, void* data, size_t length, - int flags, struct sockaddr* address, socklen_t* _addressLength, bool kernel) + int flags, struct sockaddr* address, socklen_t* _addressLength) { msghdr message; iovec vecs[1] = { { data, length } }; @@ -93,7 +91,6 @@ stack_interface_recvfrom(net_socket* socket, void* data, size_t length, message.msg_controllen = 0; message.msg_flags = 0; -// TODO: Pass kernel flag! status_t error = gNetSocketModule.receive(socket, &message, data, length, flags); if (error != B_OK) @@ -105,8 +102,7 @@ stack_interface_recvfrom(net_socket* socket, void* data, size_t length, static ssize_t -stack_interface_recvmsg(net_socket* socket, struct msghdr* message, int flags, - bool kernel) +stack_interface_recvmsg(net_socket* socket, struct msghdr* message, int flags) { void* buffer = NULL; size_t len = 0; @@ -115,24 +111,21 @@ stack_interface_recvmsg(net_socket* socket, struct msghdr* message, int flags, len = message->msg_iov[0].iov_len; } -// TODO: Pass kernel flag! return gNetSocketModule.receive(socket, message, buffer, len, flags); } static ssize_t stack_interface_send(net_socket* socket, const void* data, size_t length, - int flags, bool kernel) + int flags) { -// TODO: Pass kernel flag! return gNetSocketModule.send(socket, NULL, data, length, flags); } static ssize_t stack_interface_sendto(net_socket* socket, const void* data, size_t length, - int flags, const struct sockaddr* address, socklen_t addressLength, - bool kernel) + int flags, const struct sockaddr* address, socklen_t addressLength) { msghdr message; iovec vecs[1] = { { (void*)data, length } }; @@ -144,14 +137,13 @@ stack_interface_sendto(net_socket* socket, const void* data, size_t length, message.msg_controllen = 0; message.msg_flags = 0; -// TODO: Pass kernel flag! return gNetSocketModule.send(socket, &message, data, length, flags); } static ssize_t stack_interface_sendmsg(net_socket* socket, const struct msghdr* message, - int flags, bool kernel) + int flags) { void* buffer = NULL; size_t len = 0; @@ -160,7 +152,6 @@ stack_interface_sendmsg(net_socket* socket, const struct msghdr* message, len = message->msg_iov[0].iov_len; } -// TODO: Pass kernel flag! return gNetSocketModule.send(socket, (msghdr*)message, buffer, len, flags); } @@ -219,9 +210,9 @@ stack_interface_socketpair(int family, int type, int protocol, static status_t stack_interface_ioctl(net_socket* socket, uint32 op, void *buffer, - size_t length, bool kernel) + size_t length) { - return gNetSocketModule.control(socket, op, buffer, length, kernel); + return gNetSocketModule.control(socket, op, buffer, length); } diff --git a/src/add-ons/kernel/network/stack/utility.cpp b/src/add-ons/kernel/network/stack/utility.cpp index caacfaba9d..6bcd68c2ea 100644 --- a/src/add-ons/kernel/network/stack/utility.cpp +++ b/src/add-ons/kernel/network/stack/utility.cpp @@ -575,10 +575,18 @@ uninit_timers(void) // #pragma mark - Syscall restart +bool +is_syscall(void) +{ + struct thread* thread = thread_get_current_thread(); + return (thread->flags & THREAD_FLAGS_SYSCALL) != 0; +} + + bool is_restarted_syscall(void) { - return syscall_restart_ioctl_is_restarted(); + return syscall_restart_is_restarted(); } @@ -586,7 +594,7 @@ void store_syscall_restart_timeout(bigtime_t timeout) { struct thread* thread = thread_get_current_thread(); - if ((thread->flags & THREAD_FLAGS_IOCTL_SYSCALL) != 0) + if ((thread->flags & THREAD_FLAGS_SYSCALL) != 0) *(bigtime_t*)thread->syscall_restart.parameters = timeout; } diff --git a/src/add-ons/kernel/network/stack/utility.h b/src/add-ons/kernel/network/stack/utility.h index c27afce92e..fa542ba5e2 100644 --- a/src/add-ons/kernel/network/stack/utility.h +++ b/src/add-ons/kernel/network/stack/utility.h @@ -102,6 +102,7 @@ status_t init_timers(void); void uninit_timers(void); // syscall restart +bool is_syscall(void); bool is_restarted_syscall(void); void store_syscall_restart_timeout(bigtime_t timeout); bigtime_t restore_syscall_restart_timeout(void); diff --git a/src/system/kernel/fs/fd.cpp b/src/system/kernel/fs/fd.cpp index 9e4dd03bb5..a0d64bd5e4 100644 --- a/src/system/kernel/fs/fd.cpp +++ b/src/system/kernel/fs/fd.cpp @@ -651,14 +651,15 @@ common_user_io(int fd, off_t pos, void *buffer, size_t length, bool write) return B_BAD_VALUE; } - status_t status; + SyscallRestartWrapper status; + if (write) status = descriptor->ops->fd_write(descriptor, pos, buffer, &length); else status = descriptor->ops->fd_read(descriptor, pos, buffer, &length); if (status < B_OK) - return syscall_restart_handle_post(status); + return status; if (movePosition) descriptor->pos = pos + length; @@ -710,10 +711,11 @@ common_user_vector_io(int fd, off_t pos, const iovec *userVecs, size_t count, return B_BAD_VALUE; } + SyscallRestartWrapper status; + ssize_t bytesTransferred = 0; for (uint32 i = 0; i < count; i++) { size_t length = vecs[i].iov_len; - status_t status; if (write) { status = descriptor->ops->fd_write(descriptor, pos, vecs[i].iov_base, &length); @@ -724,7 +726,8 @@ common_user_vector_io(int fd, off_t pos, const iovec *userVecs, size_t count, if (status < B_OK) { if (bytesTransferred == 0) - return syscall_restart_handle_post(status); + return status; + status = B_OK; break; } @@ -819,13 +822,9 @@ _user_ioctl(int fd, ulong op, void *buffer, size_t length) TRACE(("user_ioctl: fd %d\n", fd)); - struct thread *thread = thread_get_current_thread(); - atomic_or(&thread->flags, THREAD_FLAGS_IOCTL_SYSCALL); + SyscallRestartWrapper status; - status_t status = fd_ioctl(false, fd, op, buffer, length); - - atomic_and(&thread->flags, ~THREAD_FLAGS_IOCTL_SYSCALL); - return status; + return status = fd_ioctl(false, fd, op, buffer, length); } @@ -908,19 +907,16 @@ _user_dup2(int ofd, int nfd) ssize_t _kern_read(int fd, off_t pos, void *buffer, size_t length) { - struct file_descriptor *descriptor; - ssize_t bytesRead; - if (pos < -1) return B_BAD_VALUE; - descriptor = get_fd(get_current_io_context(true), fd); + FDGetter fdGetter; + struct file_descriptor *descriptor = fdGetter.SetTo(fd, true); + if (!descriptor) return B_FILE_ERROR; - if ((descriptor->open_mode & O_RWMASK) == O_WRONLY) { - put_fd(descriptor); + if ((descriptor->open_mode & O_RWMASK) == O_WRONLY) return B_FILE_ERROR; - } bool movePosition = false; if (pos == -1) { @@ -928,21 +924,23 @@ _kern_read(int fd, off_t pos, void *buffer, size_t length) movePosition = true; } - if (descriptor->ops->fd_read) { - bytesRead = descriptor->ops->fd_read(descriptor, pos, buffer, &length); - if (bytesRead >= B_OK) { - if (length > SSIZE_MAX) - bytesRead = SSIZE_MAX; - else - bytesRead = (ssize_t)length; + SyscallFlagUnsetter _; - if (movePosition) - descriptor->pos = pos + length; - } - } else - bytesRead = B_BAD_VALUE; + if (descriptor->ops->fd_read == NULL) + return B_BAD_VALUE; + + ssize_t bytesRead = descriptor->ops->fd_read(descriptor, pos, buffer, + &length); + if (bytesRead >= B_OK) { + if (length > SSIZE_MAX) + bytesRead = SSIZE_MAX; + else + bytesRead = (ssize_t)length; + + if (movePosition) + descriptor->pos = pos + length; + } - put_fd(descriptor); return bytesRead; } @@ -950,52 +948,53 @@ _kern_read(int fd, off_t pos, void *buffer, size_t length) ssize_t _kern_readv(int fd, off_t pos, const iovec *vecs, size_t count) { - struct file_descriptor *descriptor; bool movePosition = false; - ssize_t bytesRead = 0; status_t status; uint32 i; if (pos < -1) return B_BAD_VALUE; - descriptor = get_fd(get_current_io_context(true), fd); + FDGetter fdGetter; + struct file_descriptor *descriptor = fdGetter.SetTo(fd, true); + if (!descriptor) return B_FILE_ERROR; - if ((descriptor->open_mode & O_RWMASK) == O_WRONLY) { - put_fd(descriptor); + if ((descriptor->open_mode & O_RWMASK) == O_WRONLY) return B_FILE_ERROR; - } if (pos == -1) { pos = descriptor->pos; movePosition = true; } - if (descriptor->ops->fd_read) { - for (i = 0; i < count; i++) { - size_t length = vecs[i].iov_len; - status = descriptor->ops->fd_read(descriptor, pos, vecs[i].iov_base, - &length); - if (status < B_OK) { - bytesRead = status; - break; - } + if (descriptor->ops->fd_read == NULL) + return B_BAD_VALUE; - if ((uint64)bytesRead + length > SSIZE_MAX) - bytesRead = SSIZE_MAX; - else - bytesRead += (ssize_t)length; + SyscallFlagUnsetter _; - pos += vecs[i].iov_len; + ssize_t bytesRead = 0; + + for (i = 0; i < count; i++) { + size_t length = vecs[i].iov_len; + status = descriptor->ops->fd_read(descriptor, pos, vecs[i].iov_base, + &length); + if (status < B_OK) { + bytesRead = status; + break; } - } else - bytesRead = B_BAD_VALUE; + + if ((uint64)bytesRead + length > SSIZE_MAX) + bytesRead = SSIZE_MAX; + else + bytesRead += (ssize_t)length; + + pos += vecs[i].iov_len; + } if (movePosition) descriptor->pos = pos; - put_fd(descriptor); return bytesRead; } @@ -1003,19 +1002,16 @@ _kern_readv(int fd, off_t pos, const iovec *vecs, size_t count) ssize_t _kern_write(int fd, off_t pos, const void *buffer, size_t length) { - struct file_descriptor *descriptor; - ssize_t bytesWritten; - if (pos < -1) return B_BAD_VALUE; - descriptor = get_fd(get_current_io_context(true), fd); + FDGetter fdGetter; + struct file_descriptor *descriptor = fdGetter.SetTo(fd, true); + if (descriptor == NULL) return B_FILE_ERROR; - if ((descriptor->open_mode & O_RWMASK) == O_RDONLY) { - put_fd(descriptor); + if ((descriptor->open_mode & O_RWMASK) == O_RDONLY) return B_FILE_ERROR; - } bool movePosition = false; if (pos == -1) { @@ -1023,22 +1019,23 @@ _kern_write(int fd, off_t pos, const void *buffer, size_t length) movePosition = true; } - if (descriptor->ops->fd_write) { - bytesWritten = descriptor->ops->fd_write(descriptor, pos, buffer, - &length); - if (bytesWritten >= B_OK) { - if (length > SSIZE_MAX) - bytesWritten = SSIZE_MAX; - else - bytesWritten = (ssize_t)length; + if (descriptor->ops->fd_write == NULL) + return B_BAD_VALUE; - if (movePosition) - descriptor->pos = pos + length; - } - } else - bytesWritten = B_BAD_VALUE; + SyscallFlagUnsetter _; + + ssize_t bytesWritten = descriptor->ops->fd_write(descriptor, pos, buffer, + &length); + if (bytesWritten >= B_OK) { + if (length > SSIZE_MAX) + bytesWritten = SSIZE_MAX; + else + bytesWritten = (ssize_t)length; + + if (movePosition) + descriptor->pos = pos + length; + } - put_fd(descriptor); return bytesWritten; } @@ -1046,52 +1043,53 @@ _kern_write(int fd, off_t pos, const void *buffer, size_t length) ssize_t _kern_writev(int fd, off_t pos, const iovec *vecs, size_t count) { - struct file_descriptor *descriptor; bool movePosition = false; - ssize_t bytesWritten = 0; status_t status; uint32 i; if (pos < -1) return B_BAD_VALUE; - descriptor = get_fd(get_current_io_context(true), fd); + FDGetter fdGetter; + struct file_descriptor *descriptor = fdGetter.SetTo(fd, true); + if (!descriptor) return B_FILE_ERROR; - if ((descriptor->open_mode & O_RWMASK) == O_RDONLY) { - put_fd(descriptor); + if ((descriptor->open_mode & O_RWMASK) == O_RDONLY) return B_FILE_ERROR; - } if (pos == -1) { pos = descriptor->pos; movePosition = true; } - if (descriptor->ops->fd_write) { - for (i = 0; i < count; i++) { - size_t length = vecs[i].iov_len; - status = descriptor->ops->fd_write(descriptor, pos, - vecs[i].iov_base, &length); - if (status < B_OK) { - bytesWritten = status; - break; - } + if (descriptor->ops->fd_write == NULL) + return B_BAD_VALUE; - if ((uint64)bytesWritten + length > SSIZE_MAX) - bytesWritten = SSIZE_MAX; - else - bytesWritten += (ssize_t)length; + SyscallFlagUnsetter _; - pos += vecs[i].iov_len; + ssize_t bytesWritten = 0; + + for (i = 0; i < count; i++) { + size_t length = vecs[i].iov_len; + status = descriptor->ops->fd_write(descriptor, pos, + vecs[i].iov_base, &length); + if (status < B_OK) { + bytesWritten = status; + break; } - } else - bytesWritten = B_BAD_VALUE; + + if ((uint64)bytesWritten + length > SSIZE_MAX) + bytesWritten = SSIZE_MAX; + else + bytesWritten += (ssize_t)length; + + pos += vecs[i].iov_len; + } if (movePosition) descriptor->pos = pos; - put_fd(descriptor); return bytesWritten; } @@ -1120,7 +1118,7 @@ _kern_ioctl(int fd, ulong op, void *buffer, size_t length) { TRACE(("kern_ioctl: fd %d\n", fd)); - IoctlSyscallFlagUnsetter _; + SyscallFlagUnsetter _; return fd_ioctl(true, fd, op, buffer, length); } diff --git a/src/system/kernel/fs/socket.cpp b/src/system/kernel/fs/socket.cpp index ae6e8ebd5d..e826c1547e 100644 --- a/src/system/kernel/fs/socket.cpp +++ b/src/system/kernel/fs/socket.cpp @@ -189,7 +189,7 @@ socket_read(struct file_descriptor *descriptor, off_t pos, void *buffer, size_t *_length) { ssize_t bytesRead = sStackInterface->recv(descriptor->u.socket, buffer, - *_length, 0, !IS_USER_ADDRESS(buffer)); + *_length, 0); *_length = bytesRead >= 0 ? bytesRead : 0; return bytesRead >= 0 ? B_OK : bytesRead; } @@ -200,7 +200,7 @@ socket_write(struct file_descriptor *descriptor, off_t pos, const void *buffer, size_t *_length) { ssize_t bytesWritten = sStackInterface->send(descriptor->u.socket, buffer, - *_length, 0, !IS_USER_ADDRESS(buffer)); + *_length, 0); *_length = bytesWritten >= 0 ? bytesWritten : 0; return bytesWritten >= 0 ? B_OK : bytesWritten; } @@ -210,8 +210,7 @@ static status_t socket_ioctl(struct file_descriptor *descriptor, ulong op, void *buffer, size_t length) { - return sStackInterface->ioctl(descriptor->u.socket, op, buffer, - length, !IS_USER_ADDRESS(buffer)); + return sStackInterface->ioctl(descriptor->u.socket, op, buffer, length); } @@ -341,8 +340,7 @@ common_bind(int fd, const struct sockaddr *address, socklen_t addressLength, GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor); FDPutter _(descriptor); - return sStackInterface->bind(descriptor->u.socket, address, addressLength, - kernel); + return sStackInterface->bind(descriptor->u.socket, address, addressLength); } @@ -366,7 +364,7 @@ common_connect(int fd, const struct sockaddr *address, FDPutter _(descriptor); return sStackInterface->connect(descriptor->u.socket, address, - addressLength, kernel); + addressLength); } @@ -413,8 +411,7 @@ common_recv(int fd, void *data, size_t length, int flags, bool kernel) GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor); FDPutter _(descriptor); - return sStackInterface->recv(descriptor->u.socket, data, length, flags, - kernel); + return sStackInterface->recv(descriptor->u.socket, data, length, flags); } @@ -427,7 +424,7 @@ common_recvfrom(int fd, void *data, size_t length, int flags, FDPutter _(descriptor); return sStackInterface->recvfrom(descriptor->u.socket, data, length, - flags, address, _addressLength, kernel); + flags, address, _addressLength); } @@ -438,8 +435,7 @@ common_recvmsg(int fd, struct msghdr *message, int flags, bool kernel) GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor); FDPutter _(descriptor); - return sStackInterface->recvmsg(descriptor->u.socket, message, flags, - kernel); + return sStackInterface->recvmsg(descriptor->u.socket, message, flags); } @@ -450,8 +446,7 @@ common_send(int fd, const void *data, size_t length, int flags, bool kernel) GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor); FDPutter _(descriptor); - return sStackInterface->send(descriptor->u.socket, data, length, flags, - kernel); + return sStackInterface->send(descriptor->u.socket, data, length, flags); } @@ -464,7 +459,7 @@ common_sendto(int fd, const void *data, size_t length, int flags, FDPutter _(descriptor); return sStackInterface->sendto(descriptor->u.socket, data, length, flags, - address, addressLength, kernel); + address, addressLength); } @@ -475,8 +470,7 @@ common_sendmsg(int fd, const struct msghdr *message, int flags, bool kernel) GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor); FDPutter _(descriptor); - return sStackInterface->sendmsg(descriptor->u.socket, message, flags, - kernel); + return sStackInterface->sendmsg(descriptor->u.socket, message, flags); } @@ -585,6 +579,7 @@ common_get_next_socket_stat(int family, uint32 *cookie, struct net_stat *stat) int socket(int family, int type, int protocol) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_socket(family, type, protocol, true)); } @@ -592,6 +587,7 @@ socket(int family, int type, int protocol) int bind(int socket, const struct sockaddr *address, socklen_t addressLength) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_bind(socket, address, addressLength, true)); } @@ -599,6 +595,7 @@ bind(int socket, const struct sockaddr *address, socklen_t addressLength) int shutdown(int socket, int how) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_shutdown(socket, how, true)); } @@ -606,7 +603,7 @@ shutdown(int socket, int how) int connect(int socket, const struct sockaddr *address, socklen_t addressLength) { - IoctlSyscallFlagUnsetter _; + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_connect(socket, address, addressLength, true)); } @@ -614,6 +611,7 @@ connect(int socket, const struct sockaddr *address, socklen_t addressLength) int listen(int socket, int backlog) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_listen(socket, backlog, true)); } @@ -621,7 +619,7 @@ listen(int socket, int backlog) int accept(int socket, struct sockaddr *address, socklen_t *_addressLength) { - IoctlSyscallFlagUnsetter _; + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_accept(socket, address, _addressLength, true)); } @@ -629,7 +627,7 @@ accept(int socket, struct sockaddr *address, socklen_t *_addressLength) ssize_t recv(int socket, void *data, size_t length, int flags) { - IoctlSyscallFlagUnsetter _; + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_recv(socket, data, length, flags, true)); } @@ -638,7 +636,7 @@ ssize_t recvfrom(int socket, void *data, size_t length, int flags, struct sockaddr *address, socklen_t *_addressLength) { - IoctlSyscallFlagUnsetter _; + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_recvfrom(socket, data, length, flags, address, _addressLength, true)); } @@ -647,7 +645,7 @@ recvfrom(int socket, void *data, size_t length, int flags, ssize_t recvmsg(int socket, struct msghdr *message, int flags) { - IoctlSyscallFlagUnsetter _; + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_recvmsg(socket, message, flags, true)); } @@ -655,7 +653,7 @@ recvmsg(int socket, struct msghdr *message, int flags) ssize_t send(int socket, const void *data, size_t length, int flags) { - IoctlSyscallFlagUnsetter _; + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_send(socket, data, length, flags, true)); } @@ -664,7 +662,7 @@ ssize_t sendto(int socket, const void *data, size_t length, int flags, const struct sockaddr *address, socklen_t addressLength) { - IoctlSyscallFlagUnsetter _; + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_sendto(socket, data, length, flags, address, addressLength, true)); } @@ -673,7 +671,7 @@ sendto(int socket, const void *data, size_t length, int flags, ssize_t sendmsg(int socket, const struct msghdr *message, int flags) { - IoctlSyscallFlagUnsetter _; + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_sendmsg(socket, message, flags, true)); } @@ -681,6 +679,7 @@ sendmsg(int socket, const struct msghdr *message, int flags) int getsockopt(int socket, int level, int option, void *value, socklen_t *_length) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_getsockopt(socket, level, option, value, _length, true)); } @@ -690,6 +689,7 @@ int setsockopt(int socket, int level, int option, const void *value, socklen_t length) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_setsockopt(socket, level, option, value, length, true)); } @@ -698,6 +698,7 @@ setsockopt(int socket, int level, int option, const void *value, int getpeername(int socket, struct sockaddr *address, socklen_t *_addressLength) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_getpeername(socket, address, _addressLength, true)); } @@ -706,6 +707,7 @@ getpeername(int socket, struct sockaddr *address, socklen_t *_addressLength) int getsockname(int socket, struct sockaddr *address, socklen_t *_addressLength) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_getsockname(socket, address, _addressLength, true)); } @@ -714,6 +716,7 @@ getsockname(int socket, struct sockaddr *address, socklen_t *_addressLength) int sockatmark(int socket) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_sockatmark(socket, true)); } @@ -721,6 +724,7 @@ sockatmark(int socket) int socketpair(int family, int type, int protocol, int socketVector[2]) { + SyscallFlagUnsetter _; RETURN_AND_SET_ERRNO(common_socketpair(family, type, protocol, socketVector, true)); } @@ -732,7 +736,8 @@ socketpair(int family, int type, int protocol, int socketVector[2]) int _user_socket(int family, int type, int protocol) { - return common_socket(family, type, protocol, false); + SyscallRestartWrapper result; + return result = common_socket(family, type, protocol, false); } @@ -750,14 +755,17 @@ _user_bind(int socket, const struct sockaddr *userAddress, return B_BAD_ADDRESS; } - return common_bind(socket, (sockaddr*)address, addressLength, false); + SyscallRestartWrapper error; + return error = common_bind(socket, (sockaddr*)address, addressLength, + false); } status_t _user_shutdown_socket(int socket, int how) { - return common_shutdown(socket, how, false); + SyscallRestartWrapper error; + return error = common_shutdown(socket, how, false); } @@ -775,19 +783,18 @@ _user_connect(int socket, const struct sockaddr *userAddress, return B_BAD_ADDRESS; } - status_t error; - IoctlSyscallRestartWrapper restartWrapper(error); + SyscallRestartWrapper error; - error = common_connect(socket, (sockaddr*)address, addressLength, false); - - return error; + return error = common_connect(socket, (sockaddr*)address, addressLength, + false); } status_t _user_listen(int socket, int backlog) { - return common_listen(socket, backlog, false); + SyscallRestartWrapper error; + return error = common_listen(socket, backlog, false); } @@ -803,8 +810,7 @@ _user_accept(int socket, struct sockaddr *userAddress, return error; // accept() - int result; - IoctlSyscallRestartWrapper restartWrapper(result); + SyscallRestartWrapper result; char address[MAX_SOCKET_ADDRESS_LEN]; result = common_accept(socket, @@ -826,12 +832,8 @@ _user_accept(int socket, struct sockaddr *userAddress, ssize_t _user_recv(int socket, void *data, size_t length, int flags) { - ssize_t result; - IoctlSyscallRestartWrapper restartWrapper(result); - - result = common_recv(socket, data, length, flags, false); - - return result; + SyscallRestartWrapper result; + return result = common_recv(socket, data, length, flags, false); } @@ -847,8 +849,7 @@ _user_recvfrom(int socket, void *data, size_t length, int flags, return error; // recvfrom() - ssize_t result; - IoctlSyscallRestartWrapper restartWrapper(result); + SyscallRestartWrapper result; char address[MAX_SOCKET_ADDRESS_LEN]; result = common_recvfrom(socket, data, length, flags, @@ -884,8 +885,7 @@ _user_recvmsg(int socket, struct msghdr *userMessage, int flags) return error; // recvmsg() - ssize_t result; - IoctlSyscallRestartWrapper restartWrapper(result); + SyscallRestartWrapper result; result = common_recvmsg(socket, &message, flags, false); if (result < 0) @@ -906,12 +906,8 @@ _user_recvmsg(int socket, struct msghdr *userMessage, int flags) ssize_t _user_send(int socket, const void *data, size_t length, int flags) { - ssize_t result; - IoctlSyscallRestartWrapper restartWrapper(result); - - result = common_send(socket, data, length, flags, false); - - return result; + SyscallRestartWrapper result; + return result = common_send(socket, data, length, flags, false); } @@ -934,12 +930,10 @@ _user_sendto(int socket, const void *data, size_t length, int flags, } // sendto() - ssize_t result; - IoctlSyscallRestartWrapper restartWrapper(result); + SyscallRestartWrapper result; - result = common_sendto(socket, data, length, flags, (sockaddr*)address, - addressLength, false); - return result; + return result = common_sendto(socket, data, length, flags, + (sockaddr*)address, addressLength, false); } @@ -965,11 +959,9 @@ _user_sendmsg(int socket, const struct msghdr *userMessage, int flags) } // sendmsg() - ssize_t result; - IoctlSyscallRestartWrapper restartWrapper(result); + SyscallRestartWrapper result; - result = common_sendmsg(socket, &message, flags, false); - return result; + return result = common_sendmsg(socket, &message, flags, false); } @@ -993,7 +985,8 @@ _user_getsockopt(int socket, int level, int option, void *userValue, // getsockopt() char value[MAX_SOCKET_OPTION_LEN]; - status_t error = common_getsockopt(socket, level, option, value, &length, + SyscallRestartWrapper error; + error = common_getsockopt(socket, level, option, value, &length, false); if (error != B_OK) return error; @@ -1022,7 +1015,9 @@ _user_setsockopt(int socket, int level, int option, const void *userValue, } // setsockopt(); - return common_setsockopt(socket, level, option, value, length, false); + SyscallRestartWrapper error; + return error = common_setsockopt(socket, level, option, value, length, + false); } @@ -1032,8 +1027,9 @@ _user_getpeername(int socket, struct sockaddr *userAddress, { // check parameters socklen_t addressLength = 0; - status_t error = prepare_userland_address_result(userAddress, - _addressLength, addressLength, true); + SyscallRestartWrapper error; + error = prepare_userland_address_result(userAddress, _addressLength, + addressLength, true); if (error != B_OK) return error; @@ -1062,8 +1058,9 @@ _user_getsockname(int socket, struct sockaddr *userAddress, { // check parameters socklen_t addressLength = 0; - status_t error = prepare_userland_address_result(userAddress, - _addressLength, addressLength, true); + SyscallRestartWrapper error; + error = prepare_userland_address_result(userAddress, _addressLength, + addressLength, true); if (error != B_OK) return error; @@ -1089,7 +1086,8 @@ _user_getsockname(int socket, struct sockaddr *userAddress, int _user_sockatmark(int socket) { - return common_sockatmark(socket, false); + SyscallRestartWrapper error; + return error = common_sockatmark(socket, false); } @@ -1104,8 +1102,8 @@ _user_socketpair(int family, int type, int protocol, int *userSocketVector) // socketpair() int socketVector[2]; - status_t error = common_socketpair(family, type, protocol, socketVector, - false); + SyscallRestartWrapper error; + error = common_socketpair(family, type, protocol, socketVector, false); if (error != B_OK) return error; @@ -1135,7 +1133,8 @@ _user_get_next_socket_stat(int family, uint32 *_cookie, struct net_stat *_stat) } net_stat stat; - status_t error = common_get_next_socket_stat(family, &cookie, &stat); + SyscallRestartWrapper error; + error = common_get_next_socket_stat(family, &cookie, &stat); if (error != B_OK) return error;