mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 10:46:25 +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/suspend.h>
|
||||
#include <internal/pthread.h>
|
||||
#include <internal/unconfirmed.h>
|
||||
|
||||
|
||||
namespace Libc {
|
||||
@ -604,12 +603,11 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen)
|
||||
return Errno(EMFILE);
|
||||
}
|
||||
|
||||
auto _accept_fd = make_unconfirmed([&] { file_descriptor_allocator()->free(accept_fd); });
|
||||
|
||||
if (addr && addrlen) {
|
||||
Socket_fs::Remote_functor func(*accept_context, false);
|
||||
int ret = read_sockaddr_in(func, (sockaddr_in *)addr, addrlen);
|
||||
if (ret == -1) {
|
||||
file_descriptor_allocator()->free(accept_fd);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, accept_context);
|
||||
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 */
|
||||
accept_context->fd_flags(listen_context->fd_flags());
|
||||
|
||||
_accept_fd.confirm();
|
||||
return accept_fd->libc_fd;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user