mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
libc: fix page fault in socket_fs_plugin
In the error case of socket_fs_accept() the Unconfirmed utility was incompletely applied with the result of executing the cleanup routines in the wrong order. Fixes #4417
This commit is contained in:
parent
50c7104e22
commit
392a2cba66
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Utility to automatically unroll unconfirmed operations
|
|
||||||
* \author Christian Helmuth
|
|
||||||
* \date 2020-07-31
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Genode Labs GmbH
|
|
||||||
*
|
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _LIBC__INTERNAL__UNCONFIRMED_H_
|
|
||||||
#define _LIBC__INTERNAL__UNCONFIRMED_H_
|
|
||||||
|
|
||||||
namespace Libc {
|
|
||||||
template <typename> struct Unconfirmed;
|
|
||||||
|
|
||||||
template <typename FUNC>
|
|
||||||
Unconfirmed<FUNC> make_unconfirmed(FUNC const &cleanup)
|
|
||||||
{
|
|
||||||
return { cleanup };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename FUNC>
|
|
||||||
struct Libc::Unconfirmed
|
|
||||||
{
|
|
||||||
bool confirmed { false };
|
|
||||||
|
|
||||||
FUNC const &cleanup;
|
|
||||||
|
|
||||||
Unconfirmed(FUNC const &cleanup) : cleanup(cleanup) { }
|
|
||||||
~Unconfirmed() { if (!confirmed) cleanup(); }
|
|
||||||
|
|
||||||
void confirm() { confirmed = true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _LIBC__INTERNAL__UNCONFIRMED_H_ */
|
|
@ -43,7 +43,6 @@
|
|||||||
#include <internal/init.h>
|
#include <internal/init.h>
|
||||||
#include <internal/suspend.h>
|
#include <internal/suspend.h>
|
||||||
#include <internal/pthread.h>
|
#include <internal/pthread.h>
|
||||||
#include <internal/unconfirmed.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Libc {
|
namespace Libc {
|
||||||
@ -604,12 +603,11 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen)
|
|||||||
return Errno(EMFILE);
|
return Errno(EMFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto _accept_fd = make_unconfirmed([&] { file_descriptor_allocator()->free(accept_fd); });
|
|
||||||
|
|
||||||
if (addr && addrlen) {
|
if (addr && addrlen) {
|
||||||
Socket_fs::Remote_functor func(*accept_context, false);
|
Socket_fs::Remote_functor func(*accept_context, false);
|
||||||
int ret = read_sockaddr_in(func, (sockaddr_in *)addr, addrlen);
|
int ret = read_sockaddr_in(func, (sockaddr_in *)addr, addrlen);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
|
file_descriptor_allocator()->free(accept_fd);
|
||||||
Libc::Allocator alloc { };
|
Libc::Allocator alloc { };
|
||||||
destroy(alloc, accept_context);
|
destroy(alloc, accept_context);
|
||||||
return ret;
|
return ret;
|
||||||
@ -619,7 +617,6 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen)
|
|||||||
/* inherit the O_NONBLOCK flag if set */
|
/* inherit the O_NONBLOCK flag if set */
|
||||||
accept_context->fd_flags(listen_context->fd_flags());
|
accept_context->fd_flags(listen_context->fd_flags());
|
||||||
|
|
||||||
_accept_fd.confirm();
|
|
||||||
return accept_fd->libc_fd;
|
return accept_fd->libc_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user