mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 11:44:58 +00:00
Kernel/Net: Iron out the locking mechanism across the subsystem
There is a big mix of LockRefPtrs all over the Networking subsystem, as well as lots of room for improvements with our locking patterns, which this commit will not pursue, but will give a good start for such work. To deal with this situation, we change the following things: - Creating instances of NetworkAdapter should always yield a non-locking NonnullRefPtr. Acquiring an instance from the NetworkingManagement should give a simple RefPtr,as giving LockRefPtr does not really protect from concurrency problems in such case. - Since NetworkingManagement works with normal RefPtrs we should protect all instances of RefPtr<NetworkAdapter> with SpinlockProtected to ensure references are gone unexpectedly. - Protect the so_error class member with a proper spinlock. This happens to be important because the clear_so_error() method lacked any proper locking measures. It also helps preventing a possible TOCTOU when we might do a more fine-grained locking in the Socket code, so this could be definitely a start for this. - Change unnecessary LockRefPtr<PacketWithTimestamp> in the structure of OutgoingPacket to a simple RefPtr<PacketWithTimestamp> as the whole list should be MutexProtected.
This commit is contained in:
parent
bd7d4513bf
commit
7c1f645e27
13 changed files with 93 additions and 83 deletions
|
@ -100,7 +100,9 @@ ErrorOr<void> Socket::setsockopt(int level, int option, Userspace<void const*> u
|
|||
auto device = NetworkingManagement::the().lookup_by_name(ifname->view());
|
||||
if (!device)
|
||||
return ENODEV;
|
||||
m_bound_interface = move(device);
|
||||
m_bound_interface.with([&device](auto& bound_device) {
|
||||
bound_device = move(device);
|
||||
});
|
||||
return {};
|
||||
}
|
||||
case SO_DEBUG:
|
||||
|
@ -169,31 +171,35 @@ ErrorOr<void> Socket::getsockopt(OpenFileDescription&, int level, int option, Us
|
|||
case SO_ERROR: {
|
||||
if (size < sizeof(int))
|
||||
return EINVAL;
|
||||
int errno = 0;
|
||||
if (auto const& error = so_error(); error.has_value())
|
||||
errno = error.value();
|
||||
TRY(copy_to_user(static_ptr_cast<int*>(value), &errno));
|
||||
size = sizeof(int);
|
||||
TRY(copy_to_user(value_size, &size));
|
||||
clear_so_error();
|
||||
return {};
|
||||
return so_error().with([&size, value, value_size](auto& error) -> ErrorOr<void> {
|
||||
int errno = 0;
|
||||
if (error.has_value())
|
||||
errno = error.value();
|
||||
TRY(copy_to_user(static_ptr_cast<int*>(value), &errno));
|
||||
size = sizeof(int);
|
||||
TRY(copy_to_user(value_size, &size));
|
||||
error = {};
|
||||
return {};
|
||||
});
|
||||
}
|
||||
case SO_BINDTODEVICE:
|
||||
if (size < IFNAMSIZ)
|
||||
return EINVAL;
|
||||
if (m_bound_interface) {
|
||||
auto name = m_bound_interface->name();
|
||||
auto length = name.length() + 1;
|
||||
auto characters = name.characters_without_null_termination();
|
||||
TRY(copy_to_user(static_ptr_cast<char*>(value), characters, length));
|
||||
size = length;
|
||||
return copy_to_user(value_size, &size);
|
||||
} else {
|
||||
size = 0;
|
||||
TRY(copy_to_user(value_size, &size));
|
||||
// FIXME: This return value looks suspicious.
|
||||
return EFAULT;
|
||||
}
|
||||
return m_bound_interface.with([&](auto& bound_device) -> ErrorOr<void> {
|
||||
if (bound_device) {
|
||||
auto name = bound_device->name();
|
||||
auto length = name.length() + 1;
|
||||
auto characters = name.characters_without_null_termination();
|
||||
TRY(copy_to_user(static_ptr_cast<char*>(value), characters, length));
|
||||
size = length;
|
||||
return copy_to_user(value_size, &size);
|
||||
} else {
|
||||
size = 0;
|
||||
TRY(copy_to_user(value_size, &size));
|
||||
// FIXME: This return value looks suspicious.
|
||||
return EFAULT;
|
||||
}
|
||||
});
|
||||
case SO_TIMESTAMP:
|
||||
if (size < sizeof(int))
|
||||
return EINVAL;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue