socket: fix close shutdown properly

This commit is contained in:
Matheus
2026-07-07 16:49:21 -03:00
parent 196698c059
commit f46d85fe6d
15 changed files with 103 additions and 158 deletions
-6
View File
@@ -4,7 +4,6 @@
#include <logging.h> #include <logging.h>
#include <errno.h> #include <errno.h>
#include <kernel/alloc.h> #include <kernel/alloc.h>
#include <kernel/sock.h>
static scache_t *filecache; static scache_t *filecache;
#define FILE_HOLD(f) __atomic_add_fetch(&(f)->refcount, 1, __ATOMIC_SEQ_CST) #define FILE_HOLD(f) __atomic_add_fetch(&(f)->refcount, 1, __ATOMIC_SEQ_CST)
@@ -180,11 +179,6 @@ int fd_close(int fd) {
MUTEX_RELEASE(&proc->fdmutex); MUTEX_RELEASE(&proc->fdmutex);
if (file) { if (file) {
if (file->vnode && file->vnode->type == V_TYPE_SOCKET) {
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode);
socket->ops->shutdown(socket, SOCKET_SHUTDOWN_RW);
}
FILE_RELEASE(file); FILE_RELEASE(file);
} }
else { else {
+3 -1
View File
@@ -22,7 +22,9 @@ int sockfs_open(vnode_t **node, int flags, cred_t *cred) {
} }
int sockfs_close(vnode_t *node, int flags, cred_t *cred) { int sockfs_close(vnode_t *node, int flags, cred_t *cred) {
return ENOSYS; // not needed socket_t *socket = SOCKFS_SOCKET_FROM_NODE(node);
return socket->ops->shutdown ? socket->ops->shutdown(socket, SOCKET_SHUTDOWN_RW) : 0;
} }
int sockfs_read(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *bytes_read, cred_t *cred) { int sockfs_read(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *bytes_read, cred_t *cred) {
+22
View File
@@ -3,11 +3,13 @@
#include <kernel/net.h> #include <kernel/net.h>
#include <kernel/vfs.h> #include <kernel/vfs.h>
#include <kernel/file.h>
#include <mutex.h> #include <mutex.h>
#include <kernel/poll.h> #include <kernel/poll.h>
#include <kernel/usercopy.h> #include <kernel/usercopy.h>
#include <kernel/iovec.h> #include <kernel/iovec.h>
#include <stdbool.h> #include <stdbool.h>
#include <errno.h>
#define SOCKET_STATE_UNBOUND 0 #define SOCKET_STATE_UNBOUND 0
#define SOCKET_STATE_BOUND 1 #define SOCKET_STATE_BOUND 1
@@ -92,6 +94,26 @@ typedef struct {
#define SOCKET_TYPE_LOCAL_SEQPACKET 3 #define SOCKET_TYPE_LOCAL_SEQPACKET 3
#define SOCKFS_SOCKET_FROM_NODE(nodep) (((socketnode_t *)(nodep))->socket) #define SOCKFS_SOCKET_FROM_NODE(nodep) (((socketnode_t *)(nodep))->socket)
static inline int sockfd_get(int fd, vnode_t **vnodep, int *fileflags) {
file_t *file = fd_get(fd);
if (file == NULL)
return EBADF;
if (file->vnode->type != V_TYPE_SOCKET) {
fd_release(file);
return ENOTSOCK;
}
vnode_t *vnode = file->vnode;
VOP_HOLD(vnode);
if (fileflags)
*fileflags = file->flags;
fd_release(file);
*vnodep = vnode;
return 0;
}
static inline bool socket_nonblocking(socket_t *socket, uintmax_t flags) { static inline bool socket_nonblocking(socket_t *socket, uintmax_t flags) {
return socket->nonblocking || (flags & V_FFLAGS_NONBLOCKING); return socket->nonblocking || (flags & V_FFLAGS_NONBLOCKING);
} }
+12 -17
View File
@@ -15,18 +15,13 @@ syscallret_t syscall_accept(context_t *, int oldfd, abisockaddr_t *abisockaddr,
return ret; return ret;
} }
file_t *oldfile = fd_get(oldfd); vnode_t *servernode;
if (oldfile == NULL) { int fileflags;
ret.errno = EBADF; ret.errno = sockfd_get(oldfd, &servernode, &fileflags);
if (ret.errno)
return ret; return ret;
}
if (oldfile->vnode->type != V_TYPE_SOCKET) { socket_t *server = SOCKFS_SOCKET_FROM_NODE(servernode);
ret.errno = ENOTSOCK;
goto cleanup;
}
socket_t *server = SOCKFS_SOCKET_FROM_NODE(oldfile->vnode);
if (server->ops->accept == NULL) { if (server->ops->accept == NULL) {
ret.errno = ENOTSUP; ret.errno = ENOTSUP;
@@ -39,18 +34,18 @@ syscallret_t syscall_accept(context_t *, int oldfd, abisockaddr_t *abisockaddr,
goto cleanup; goto cleanup;
} }
vnode_t *vnode; vnode_t *clientnode;
ret.errno = sockfs_newsocket(&vnode, client); ret.errno = sockfs_newsocket(&clientnode, client);
if (ret.errno) { if (ret.errno) {
client->ops->destroy(client); client->ops->destroy(client);
goto cleanup; goto cleanup;
} }
sockaddr_t addr = {0}; sockaddr_t addr = {0};
ret.errno = server->ops->accept(server, client, &addr, fileflagstovnodeflags(oldfile->flags)); ret.errno = server->ops->accept(server, client, &addr, fileflagstovnodeflags(fileflags));
if (ret.errno) { if (ret.errno) {
// socket gets deleted by node cleanup // socket gets deleted by node cleanup
VOP_RELEASE(vnode); VOP_RELEASE(clientnode);
goto cleanup; goto cleanup;
} }
@@ -60,11 +55,11 @@ syscallret_t syscall_accept(context_t *, int oldfd, abisockaddr_t *abisockaddr,
ret.errno = fd_new(acceptflags & O_CLOEXEC, &newfile, &newfd); ret.errno = fd_new(acceptflags & O_CLOEXEC, &newfile, &newfd);
if (ret.errno) { if (ret.errno) {
// socket gets deleted by node cleanup // socket gets deleted by node cleanup
VOP_RELEASE(vnode); VOP_RELEASE(clientnode);
goto cleanup; goto cleanup;
} }
newfile->vnode = vnode; newfile->vnode = clientnode;
newfile->flags = FILE_READ | FILE_WRITE | (acceptflags & (O_NONBLOCK)); newfile->flags = FILE_READ | FILE_WRITE | (acceptflags & (O_NONBLOCK));
newfile->offset = 0; newfile->offset = 0;
newfile->mode = 0777; newfile->mode = 0777;
@@ -88,7 +83,7 @@ syscallret_t syscall_accept(context_t *, int oldfd, abisockaddr_t *abisockaddr,
ret.ret = newfd; ret.ret = newfd;
cleanup: cleanup:
fd_release(oldfile); VOP_RELEASE(servernode);
return ret; return ret;
} }
+6 -13
View File
@@ -24,16 +24,10 @@ syscallret_t syscall_bind(context_t *, int fd, void *uaddr, size_t addrlen) {
return ret; return ret;
} }
file_t *file = fd_get(fd); vnode_t *vnode = NULL;
if (file == NULL) { ret.errno = sockfd_get(fd, &vnode, NULL);
ret.errno = EBADF; if (ret.errno)
goto cleanup; goto cleanup;
}
if (file->vnode->type != V_TYPE_SOCKET) {
ret.errno = ENOTSOCK;
goto cleanup;
}
ret.errno = usercopy_fromuser(addr, uaddr, addrlen); ret.errno = usercopy_fromuser(addr, uaddr, addrlen);
if (ret.errno) if (ret.errno)
@@ -44,15 +38,14 @@ syscallret_t syscall_bind(context_t *, int fd, void *uaddr, size_t addrlen) {
if (ret.errno) if (ret.errno)
goto cleanup; goto cleanup;
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
ret.errno = socket->ops->bind(socket, &sockaddr, &current_thread()->proc->cred); ret.errno = socket->ops->bind(socket, &sockaddr, &current_thread()->proc->cred);
ret.ret = ret.errno ? -1 : 0; ret.ret = ret.errno ? -1 : 0;
cleanup: cleanup:
if (file) if (vnode)
fd_release(file); VOP_RELEASE(vnode);
free(addr); free(addr);
return ret; return ret;
} }
+8 -14
View File
@@ -25,16 +25,11 @@ syscallret_t syscall_connect(context_t *, int fd, abisockaddr_t *uaddr, size_t a
return ret; return ret;
} }
file_t *file = fd_get(fd); vnode_t *vnode = NULL;
if (file == NULL) { int fileflags;
ret.errno = EBADF; ret.errno = sockfd_get(fd, &vnode, &fileflags);
if (ret.errno)
goto cleanup; goto cleanup;
}
if (file->vnode->type != V_TYPE_SOCKET) {
ret.errno = ENOTSOCK;
goto cleanup;
}
ret.errno = usercopy_fromuser(addr, uaddr, addrlen); ret.errno = usercopy_fromuser(addr, uaddr, addrlen);
if (ret.errno) if (ret.errno)
@@ -45,15 +40,14 @@ syscallret_t syscall_connect(context_t *, int fd, abisockaddr_t *uaddr, size_t a
if (ret.errno) if (ret.errno)
goto cleanup; goto cleanup;
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
ret.errno = socket->ops->connect ? socket->ops->connect(socket, &sockaddr, fileflagstovnodeflags(file->flags), &current_thread()->proc->cred) : EOPNOTSUPP; ret.errno = socket->ops->connect ? socket->ops->connect(socket, &sockaddr, fileflagstovnodeflags(fileflags), &current_thread()->proc->cred) : EOPNOTSUPP;
ret.ret = ret.errno ? -1 : 0; ret.ret = ret.errno ? -1 : 0;
cleanup: cleanup:
if (file) if (vnode)
fd_release(file); VOP_RELEASE(vnode);
free(addr); free(addr);
return ret; return ret;
} }
+6 -13
View File
@@ -11,19 +11,13 @@ syscallret_t syscall_getpeername(context_t *, int fd, void *uaddr, int *uaddrlen
if (ret.errno) if (ret.errno)
return ret; return ret;
file_t *file = fd_get(fd); vnode_t *vnode;
if (file == NULL) { ret.errno = sockfd_get(fd, &vnode, NULL);
ret.errno = EBADF; if (ret.errno)
goto cleanup; return ret;
}
if (file->vnode->type != V_TYPE_SOCKET) {
ret.errno = ENOTSOCK;
goto cleanup;
}
sockaddr_t sockaddr; sockaddr_t sockaddr;
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
ret.errno = socket->ops->getpeername(socket, &sockaddr); ret.errno = socket->ops->getpeername(socket, &sockaddr);
if (ret.errno) if (ret.errno)
@@ -39,8 +33,7 @@ syscallret_t syscall_getpeername(context_t *, int fd, void *uaddr, int *uaddrlen
ret.ret = ret.errno ? -1 : 0; ret.ret = ret.errno ? -1 : 0;
cleanup: cleanup:
if (file) VOP_RELEASE(vnode);
fd_release(file);
return ret; return ret;
} }
+6 -13
View File
@@ -11,19 +11,13 @@ syscallret_t syscall_getsockname(context_t *, int fd, void *uaddr, int *uaddrlen
if (ret.errno) if (ret.errno)
return ret; return ret;
file_t *file = fd_get(fd); vnode_t *vnode;
if (file == NULL) { ret.errno = sockfd_get(fd, &vnode, NULL);
ret.errno = EBADF; if (ret.errno)
goto cleanup; return ret;
}
if (file->vnode->type != V_TYPE_SOCKET) {
ret.errno = ENOTSOCK;
goto cleanup;
}
sockaddr_t sockaddr; sockaddr_t sockaddr;
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
ret.errno = socket->ops->getname(socket, &sockaddr); ret.errno = socket->ops->getname(socket, &sockaddr);
if (ret.errno) if (ret.errno)
@@ -42,8 +36,7 @@ syscallret_t syscall_getsockname(context_t *, int fd, void *uaddr, int *uaddrlen
ret.ret = 0; ret.ret = 0;
cleanup: cleanup:
if (file) VOP_RELEASE(vnode);
fd_release(file);
return ret; return ret;
} }
+5 -12
View File
@@ -14,18 +14,12 @@ syscallret_t syscall_getsockopt(context_t *, int fd, int level, int optname, voi
return ret; return ret;
} }
file_t *file = fd_get(fd); vnode_t *vnode;
if (file == NULL) { ret.errno = sockfd_get(fd, &vnode, NULL);
ret.errno = EBADF; if (ret.errno)
return ret; return ret;
}
if (file->vnode->type != V_TYPE_SOCKET) { socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
ret.errno = ENOTSOCK;
goto cleanup;
}
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode);
MUTEX_ACQUIRE(&socket->mutex); MUTEX_ACQUIRE(&socket->mutex);
if (level == SOL_SOCKET) { if (level == SOL_SOCKET) {
@@ -59,9 +53,8 @@ syscallret_t syscall_getsockopt(context_t *, int fd, int level, int optname, voi
MUTEX_RELEASE(&socket->mutex); MUTEX_RELEASE(&socket->mutex);
cleanup:
ret.ret = ret.errno ? -1 : 0; ret.ret = ret.errno ? -1 : 0;
fd_release(file); VOP_RELEASE(vnode);
return ret; return ret;
} }
+5 -12
View File
@@ -7,24 +7,17 @@ syscallret_t syscall_listen(context_t *, int fd, int backlog) {
.ret = -1 .ret = -1
}; };
file_t *file = fd_get(fd); vnode_t *vnode;
if (file == NULL) { ret.errno = sockfd_get(fd, &vnode, NULL);
ret.errno = EBADF; if (ret.errno)
return ret; return ret;
}
if (file->vnode->type != V_TYPE_SOCKET) { socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
ret.errno = ENOTSOCK;
goto cleanup;
}
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode);
ret.errno = socket->ops->listen ? socket->ops->listen(socket, backlog) : EOPNOTSUPP; ret.errno = socket->ops->listen ? socket->ops->listen(socket, backlog) : EOPNOTSUPP;
ret.ret = ret.errno ? -1 : 0; ret.ret = ret.errno ? -1 : 0;
cleanup: VOP_RELEASE(vnode);
fd_release(file);
return ret; return ret;
} }
+8 -15
View File
@@ -21,7 +21,6 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
if (ret.errno) if (ret.errno)
return ret; return ret;
file_t *file = NULL;
size_t buffersize = iovec_size(msghdr.iov, msghdr.iovcount); size_t buffersize = iovec_size(msghdr.iov, msghdr.iovcount);
if (buffersize == 0) { if (buffersize == 0) {
sock_freemsghdr(&msghdr); sock_freemsghdr(&msghdr);
@@ -36,19 +35,14 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
return ret; return ret;
} }
file = fd_get(fd); vnode_t *vnode = NULL;
if (file == NULL) { int fileflags;
ret.errno = EBADF; ret.errno = sockfd_get(fd, &vnode, &fileflags);
if (ret.errno)
goto cleanup; goto cleanup;
}
if (file->vnode->type != V_TYPE_SOCKET) {
ret.errno = ENOTSOCK;
goto cleanup;
}
sockaddr_t sockaddr; sockaddr_t sockaddr;
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
uintmax_t recvflags = 0; uintmax_t recvflags = 0;
if (flags & MSG_PEEK) if (flags & MSG_PEEK)
@@ -68,7 +62,7 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
.addr = &sockaddr, .addr = &sockaddr,
.iovec_iterator = &iovec_iterator, .iovec_iterator = &iovec_iterator,
.count = buffersize, .count = buffersize,
.flags = fileflagstovnodeflags(file->flags) | recvflags, .flags = fileflagstovnodeflags(fileflags) | recvflags,
.donecount = 0, .donecount = 0,
.ctrl = msghdr.msgctrl, .ctrl = msghdr.msgctrl,
.ctrllen = msghdr.ctrllen, .ctrllen = msghdr.ctrllen,
@@ -120,9 +114,8 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
ret.ret = ret.errno ? -1 : desc.donecount; ret.ret = ret.errno ? -1 : desc.donecount;
cleanup: cleanup:
if (file) if (vnode)
fd_release(file); VOP_RELEASE(vnode);
sock_freemsghdr(&msghdr); sock_freemsghdr(&msghdr);
return ret; return ret;
} }
+11 -16
View File
@@ -6,7 +6,9 @@
#include <kernel/alloc.h> #include <kernel/alloc.h>
syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) { syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) {
syscallret_t ret; syscallret_t ret = {
.ret = -1
};
if (flags & ~(MSG_DONTWAIT | MSG_NOSIGNAL)) if (flags & ~(MSG_DONTWAIT | MSG_NOSIGNAL))
printf("sendmsg: unknown %x\n", flags); printf("sendmsg: unknown %x\n", flags);
@@ -16,7 +18,6 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
if (ret.errno) if (ret.errno)
return ret; return ret;
file_t *file = NULL;
size_t buffersize = iovec_size(msghdr.iov, msghdr.iovcount); size_t buffersize = iovec_size(msghdr.iov, msghdr.iovcount);
if (buffersize == 0) { if (buffersize == 0) {
sock_freemsghdr(&msghdr); sock_freemsghdr(&msghdr);
@@ -31,16 +32,11 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
return ret; return ret;
} }
file = fd_get(fd); vnode_t *vnode = NULL;
if (file == NULL) { int fileflags;
ret.errno = EBADF; ret.errno = sockfd_get(fd, &vnode, &fileflags);
if (ret.errno)
goto cleanup; goto cleanup;
}
if (file->vnode->type != V_TYPE_SOCKET) {
ret.errno = ENOTSOCK;
goto cleanup;
}
sockaddr_t sockaddr; sockaddr_t sockaddr;
if (msghdr.addr) { if (msghdr.addr) {
@@ -49,7 +45,7 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
goto cleanup; goto cleanup;
} }
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
int sendflags = 0; int sendflags = 0;
@@ -64,7 +60,7 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
.addr = msghdr.addr ? &sockaddr : NULL, .addr = msghdr.addr ? &sockaddr : NULL,
.iovec_iterator = &iovec_iterator, .iovec_iterator = &iovec_iterator,
.count = buffersize, .count = buffersize,
.flags = fileflagstovnodeflags(file->flags) | sendflags, .flags = fileflagstovnodeflags(fileflags) | sendflags,
.donecount = 0, .donecount = 0,
.ctrl = msghdr.msgctrl, .ctrl = msghdr.msgctrl,
.ctrllen = msghdr.ctrllen, .ctrllen = msghdr.ctrllen,
@@ -77,9 +73,8 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
ret.ret = ret.errno ? -1 : desc.donecount; ret.ret = ret.errno ? -1 : desc.donecount;
cleanup: cleanup:
if (file) if (vnode)
fd_release(file); VOP_RELEASE(vnode);
sock_freemsghdr(&msghdr); sock_freemsghdr(&msghdr);
return ret; return ret;
} }
+5 -12
View File
@@ -10,18 +10,12 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi
.ret = -1 .ret = -1
}; };
file_t *file = fd_get(fd); vnode_t *vnode;
if (file == NULL) { ret.errno = sockfd_get(fd, &vnode, NULL);
ret.errno = EBADF; if (ret.errno)
return ret; return ret;
}
if (file->vnode->type != V_TYPE_SOCKET) { socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
ret.errno = ENOTSOCK;
goto cleanup;
}
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode);
MUTEX_ACQUIRE(&socket->mutex); MUTEX_ACQUIRE(&socket->mutex);
if (level == SOL_SOCKET) { if (level == SOL_SOCKET) {
@@ -65,10 +59,9 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi
MUTEX_RELEASE(&socket->mutex); MUTEX_RELEASE(&socket->mutex);
cleanup:
ret.ret = ret.errno ? -1 : 0; ret.ret = ret.errno ? -1 : 0;
fd_release(file); VOP_RELEASE(vnode);
return ret; return ret;
} }
+5 -13
View File
@@ -20,24 +20,16 @@ syscallret_t syscall_shutdown(context_t *, int fd, int how) {
++how; // convert to internal meaning ++how; // convert to internal meaning
file_t *file = fd_get(fd); vnode_t *vnode;
if (file == NULL) { ret.errno = sockfd_get(fd, &vnode, NULL);
ret.errno = EBADF; if (ret.errno)
return ret; return ret;
}
if (file->vnode->type != V_TYPE_SOCKET) { socket_t *socket = SOCKFS_SOCKET_FROM_NODE(vnode);
ret.errno = ENOTSOCK;
goto cleanup;
}
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode);
ret.errno = socket->ops->shutdown(socket, how); ret.errno = socket->ops->shutdown(socket, how);
ret.ret = ret.errno ? -1 : 0; ret.ret = ret.errno ? -1 : 0;
cleanup: VOP_RELEASE(vnode);
fd_release(file);
return ret; return ret;
} }
+1 -1
View File
@@ -1,5 +1,5 @@
name=astral name=astral
revision=22 revision=23
from_source=astral from_source=astral
imagedeps="build-essential nasm" imagedeps="build-essential nasm"
hostdeps="xgcc xbinutils limine" hostdeps="xgcc xbinutils limine"