mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-12 07:24:07 +00:00
libc: socket fcntl flags inheritence
Set O_NONBLOCK on sockets from the fcntl syscall and propagate this flag to socket_fs control files and sockets returned from accept. Fix #2318
This commit is contained in:
parent
031337f039
commit
7ef8c81607
@ -43,8 +43,8 @@ namespace Libc {
|
|||||||
char const *fd_path = 0; /* for 'fchdir', 'fstat' */
|
char const *fd_path = 0; /* for 'fchdir', 'fstat' */
|
||||||
Plugin *plugin = 0;
|
Plugin *plugin = 0;
|
||||||
Plugin_context *context = 0;
|
Plugin_context *context = 0;
|
||||||
unsigned flags = 0; /* for 'fcntl' */
|
int flags = 0; /* for 'fcntl' */
|
||||||
unsigned status = 0; /* for 'fcntl' */
|
bool cloexec = 0; /* for 'fcntl' */
|
||||||
Genode::Lock lock;
|
Genode::Lock lock;
|
||||||
|
|
||||||
void path(char const *newpath)
|
void path(char const *newpath)
|
||||||
|
@ -80,20 +80,28 @@ namespace {
|
|||||||
int _remote_fd = -1;
|
int _remote_fd = -1;
|
||||||
int _local_fd = -1;
|
int _local_fd = -1;
|
||||||
|
|
||||||
|
template <typename FUNC>
|
||||||
|
void _fd_apply(FUNC const &fn)
|
||||||
|
{
|
||||||
|
if (_data_fd != -1) fn(_data_fd);
|
||||||
|
if (_local_fd != -1) fn(_local_fd);
|
||||||
|
if (_remote_fd != -1) fn(_remote_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _fd_flags = 0;
|
||||||
|
|
||||||
Socket_context(Absolute_path const &path)
|
Socket_context(Absolute_path const &path)
|
||||||
: path(path.base()) { }
|
: path(path.base()) { }
|
||||||
|
|
||||||
~Socket_context()
|
~Socket_context()
|
||||||
{
|
{
|
||||||
if (_data_fd != -1) close(_data_fd);
|
_fd_apply([] (int fd) { close(fd); });
|
||||||
if (_local_fd != -1) close(_local_fd);
|
|
||||||
if (_remote_fd != -1) close(_remote_fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _open_file(char const *file_name)
|
int _open_file(char const *file_name)
|
||||||
{
|
{
|
||||||
Absolute_path file(file_name, path.base());
|
Absolute_path file(file_name, path.base());
|
||||||
int const fd = open(file.base(), O_RDWR);
|
int const fd = open(file.base(), O_RDWR|_fd_flags);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
Genode::error(__func__, ": ", file_name, " file not accessible");
|
Genode::error(__func__, ": ", file_name, " file not accessible");
|
||||||
throw Inaccessible();
|
throw Inaccessible();
|
||||||
@ -101,6 +109,13 @@ namespace {
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fd_flags() const { return _fd_flags; }
|
||||||
|
void fd_flags(int flags)
|
||||||
|
{
|
||||||
|
_fd_flags = flags;
|
||||||
|
_fd_apply([flags] (int fd) { fcntl(fd, F_SETFL, flags); });
|
||||||
|
}
|
||||||
|
|
||||||
int data_fd()
|
int data_fd()
|
||||||
{
|
{
|
||||||
if (_data_fd == -1)
|
if (_data_fd == -1)
|
||||||
@ -144,6 +159,7 @@ namespace {
|
|||||||
|
|
||||||
ssize_t read(Libc::File_descriptor *, void *, ::size_t) override;
|
ssize_t read(Libc::File_descriptor *, void *, ::size_t) override;
|
||||||
ssize_t write(Libc::File_descriptor *, const void *, ::size_t) override;
|
ssize_t write(Libc::File_descriptor *, const void *, ::size_t) override;
|
||||||
|
int fcntl(Libc::File_descriptor *, int, long) override;
|
||||||
int close(Libc::File_descriptor *) override;
|
int close(Libc::File_descriptor *) override;
|
||||||
int select(int, fd_set *, fd_set *, fd_set *, timeval *) override;
|
int select(int, fd_set *, fd_set *, fd_set *, timeval *) override;
|
||||||
};
|
};
|
||||||
@ -367,7 +383,7 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen)
|
|||||||
char accept_socket[10];
|
char accept_socket[10];
|
||||||
{
|
{
|
||||||
Absolute_path file("accept", context->path.base());
|
Absolute_path file("accept", context->path.base());
|
||||||
int const fd = open(file.base(), O_RDONLY);
|
int const fd = open(file.base(), O_RDONLY|context->fd_flags());
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
Genode::error(__func__, ": accept file not accessible");
|
Genode::error(__func__, ": accept file not accessible");
|
||||||
return Errno(EINVAL);
|
return Errno(EINVAL);
|
||||||
@ -390,7 +406,7 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen)
|
|||||||
|
|
||||||
if (addr && addrlen) {
|
if (addr && addrlen) {
|
||||||
Absolute_path file("remote", accept_path.base());
|
Absolute_path file("remote", accept_path.base());
|
||||||
int const fd = open(file.base(), O_RDONLY);
|
int const fd = open(file.base(), O_RDONLY|context->fd_flags());
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
Genode::error(__func__, ": remote file not accessible");
|
Genode::error(__func__, ": remote file not accessible");
|
||||||
return Errno(EINVAL);
|
return Errno(EINVAL);
|
||||||
@ -409,6 +425,9 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen)
|
|||||||
*addrlen = sizeof(remote_addr);
|
*addrlen = sizeof(remote_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* inherit the O_NONBLOCK flag if set */
|
||||||
|
accept_context->fd_flags(context->fd_flags());
|
||||||
|
|
||||||
return accept_fd->libc_fd;
|
return accept_fd->libc_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -711,7 +730,22 @@ extern "C" int socket_fs_socket(int domain, int type, int protocol)
|
|||||||
** File-plugin operations **
|
** File-plugin operations **
|
||||||
****************************/
|
****************************/
|
||||||
|
|
||||||
//int Socket_plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg) override;
|
int Socket_plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg)
|
||||||
|
{
|
||||||
|
Socket_context *context = dynamic_cast<Socket_context *>(fd->context);
|
||||||
|
if (!context)
|
||||||
|
return Errno(EINVAL);
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case F_GETFL:
|
||||||
|
return context->fd_flags();
|
||||||
|
case F_SETFL:
|
||||||
|
context->fd_flags(arg); return 0;
|
||||||
|
default:
|
||||||
|
Genode::error(__func__, " command ", cmd, " not supported on sockets");
|
||||||
|
return Errno(EBADF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t Socket_plugin::read(Libc::File_descriptor *fd, void *buf, ::size_t count)
|
ssize_t Socket_plugin::read(Libc::File_descriptor *fd, void *buf, ::size_t count)
|
||||||
{
|
{
|
||||||
|
@ -190,7 +190,7 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags,
|
|||||||
Libc::File_descriptor *fd =
|
Libc::File_descriptor *fd =
|
||||||
Libc::file_descriptor_allocator()->alloc(this, vfs_context(handle), libc_fd);
|
Libc::file_descriptor_allocator()->alloc(this, vfs_context(handle), libc_fd);
|
||||||
|
|
||||||
fd->status = flags;
|
fd->flags = flags & (O_NONBLOCK|O_APPEND);
|
||||||
|
|
||||||
if ((flags & O_TRUNC) && (ftruncate(fd, 0) == -1)) {
|
if ((flags & O_TRUNC) && (ftruncate(fd, 0) == -1)) {
|
||||||
/* XXX leaking fd, missing errno */
|
/* XXX leaking fd, missing errno */
|
||||||
@ -632,9 +632,11 @@ int Libc::Vfs_plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg)
|
|||||||
|
|
||||||
return new_fd->libc_fd;
|
return new_fd->libc_fd;
|
||||||
}
|
}
|
||||||
case F_GETFD: return fd->flags;
|
case F_GETFD: return fd->cloexec ? FD_CLOEXEC : 0;
|
||||||
case F_SETFD: fd->flags = arg; return 0;
|
case F_SETFD: fd->cloexec = arg == FD_CLOEXEC; return 0;
|
||||||
case F_GETFL: return fd->status;
|
|
||||||
|
case F_GETFL: return fd->flags;
|
||||||
|
case F_SETFL: fd->flags = arg; return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user