Commit 04d8b7c5 authored by Jukka Rissanen's avatar Jukka Rissanen Committed by Mahesh Mahadevan
Browse files

net: sockets: Cleanup socket properly if POSIX API is enabled



The sock_obj_core_dealloc() was not called if close() is called
instead of zsock_close(). This happens if POSIX API is enabled.

Fix this by calling zvfs_close() from zsock_close() and then
pass the socket number to zsock_close_ctx() so that the cleanup
can be done properly.

Reported-by: default avatarAndreas Ålgård <aal@ixys.no>
Signed-off-by: default avatarJukka Rissanen <jukka.rissanen@nordicsemi.no>
parent 92d02878
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -64,7 +64,10 @@ struct fd_op_vtable {
		ssize_t (*write)(void *obj, const void *buf, size_t sz);
		ssize_t (*write_offs)(void *obj, const void *buf, size_t sz, size_t offset);
	};
	union {
		int (*close)(void *obj);
		int (*close2)(void *obj, int fd);
	};
	int (*ioctl)(void *obj, unsigned int request, va_list args);
};

+8 −1
Original line number Diff line number Diff line
@@ -389,8 +389,15 @@ int zvfs_close(int fd)
	(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
	if (fdtable[fd].vtable->close != NULL) {
		/* close() is optional - e.g. stdinout_fd_op_vtable */
		if (fdtable[fd].mode & ZVFS_MODE_IFSOCK) {
			/* Network socket needs to know socket number so pass
			 * it via close2() call.
			 */
			res = fdtable[fd].vtable->close2(fdtable[fd].obj, fd);
		} else {
			res = fdtable[fd].vtable->close(fdtable[fd].obj);
		}
	}
	k_mutex_unlock(&fdtable[fd].lock);

	zvfs_free_fd(fd);
+8 −24
Original line number Diff line number Diff line
@@ -147,42 +147,26 @@ static inline int z_vrfy_zsock_socket(int family, int type, int proto)
#include <zephyr/syscalls/zsock_socket_mrsh.c>
#endif /* CONFIG_USERSPACE */

extern int zvfs_close(int fd);

int z_impl_zsock_close(int sock)
{
	return zvfs_close(sock);
}

#ifdef CONFIG_USERSPACE
static inline int z_vrfy_zsock_close(int sock)
{
	const struct socket_op_vtable *vtable;
	struct k_mutex *lock;
	void *ctx;
	int ret;

	SYS_PORT_TRACING_OBJ_FUNC_ENTER(socket, close, sock);

	ctx = get_sock_vtable(sock, &vtable, &lock);
	if (ctx == NULL) {
		errno = EBADF;
		SYS_PORT_TRACING_OBJ_FUNC_EXIT(socket, close, sock, -errno);
		return -1;
	}

	(void)k_mutex_lock(lock, K_FOREVER);

	NET_DBG("close: ctx=%p, fd=%d", ctx, sock);

	ret = vtable->fd_vtable.close(ctx);

	k_mutex_unlock(lock);

	SYS_PORT_TRACING_OBJ_FUNC_EXIT(socket, close, sock, ret < 0 ? -errno : ret);

	zvfs_free_fd(sock);

	(void)sock_obj_core_dealloc(sock);

	return ret;
}

#ifdef CONFIG_USERSPACE
static inline int z_vrfy_zsock_close(int sock)
{
	return z_impl_zsock_close(sock);
}
#include <zephyr/syscalls/zsock_close_mrsh.c>
+16 −6
Original line number Diff line number Diff line
@@ -137,10 +137,14 @@ static int zsock_socket_internal(int family, int type, int proto)
	return fd;
}

int zsock_close_ctx(struct net_context *ctx)
int zsock_close_ctx(struct net_context *ctx, int sock)
{
	int ret;

	SYS_PORT_TRACING_OBJ_FUNC_ENTER(socket, close, sock);

	NET_DBG("close: ctx=%p, fd=%d", ctx, sock);

	/* Reset callbacks to avoid any race conditions while
	 * flushing queues. No need to check return values here,
	 * as these are fail-free operations and we're closing
@@ -160,10 +164,16 @@ int zsock_close_ctx(struct net_context *ctx)
	ret = net_context_put(ctx);
	if (ret < 0) {
		errno = -ret;
		return -1;
		ret = -1;
	}

	return 0;
	SYS_PORT_TRACING_OBJ_FUNC_EXIT(socket, close, sock, ret < 0 ? -errno : ret);

	if (ret == 0) {
		(void)sock_obj_core_dealloc(sock);
	}

	return ret;
}

static void zsock_accepted_cb(struct net_context *new_ctx,
@@ -2771,9 +2781,9 @@ static int sock_setsockopt_vmeth(void *obj, int level, int optname,
	return zsock_setsockopt_ctx(obj, level, optname, optval, optlen);
}

static int sock_close_vmeth(void *obj)
static int sock_close2_vmeth(void *obj, int fd)
{
	return zsock_close_ctx(obj);
	return zsock_close_ctx(obj, fd);
}
static int sock_getpeername_vmeth(void *obj, struct sockaddr *addr,
				  socklen_t *addrlen)
@@ -2791,7 +2801,7 @@ const struct socket_op_vtable sock_fd_op_vtable = {
	.fd_vtable = {
		.read = sock_read_vmeth,
		.write = sock_write_vmeth,
		.close = sock_close_vmeth,
		.close2 = sock_close2_vmeth,
		.ioctl = sock_ioctl_vmeth,
	},
	.shutdown = sock_shutdown_vmeth,
+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
#define SOCK_NONBLOCK 2
#define SOCK_ERROR 4

int zsock_close_ctx(struct net_context *ctx);
int zsock_close_ctx(struct net_context *ctx, int sock);
int zsock_poll_internal(struct zsock_pollfd *fds, int nfds, k_timeout_t timeout);

int zsock_wait_data(struct net_context *ctx, k_timeout_t *timeout);
Loading