描述错误
在kernel/src/net/socket/inet/stream/inner.rs中,enum Init 的listen和close 两个方法可能存在资源泄露问题。
在listen方法中通过一个for循环来创建新的BoundInner,并将socket绑定到self中存储的IP地址上,BoundInner::bind会把socket添加到对应的iface中。
//kernel/src/net/socket/inet/stream/inner.rs: 143
if let Err(err) = || -> Result<(), SystemError> {
for _ in 0..(backlog - 1) {
// -1 because the first one is already bound
let new_listen = socket::inet::BoundInner::bind(
new_listen_smoltcp_socket(listen_addr),
listen_addr
.addr
.as_ref()
.unwrap_or(&smoltcp::wire::IpAddress::from(
smoltcp::wire::Ipv4Address::UNSPECIFIED,
)),
inner.netns(),
)?;
inners.push(new_listen);
}
Ok(())
}() {
return Err((Init::Bound((inner, local)), err));
}
if let Err(err) = inner.with_mut::<smoltcp::socket::tcp::Socket, _, _>(|socket| {
socket
.listen(listen_addr)
.map_err(|_| SystemError::ECONNREFUSED)
}) {
return Err((Init::Bound((inner, local)), err));
}
如果循环中途(或闭包末尾)返回 Err:
已经成功 bind的那些 BoundInner 都在 inners 里,接着直接被 drop,但由于 BoundInner 没有 Drop 释放逻辑,不会调用BoundInner::release将这些socket释放到
结果:这些 socket handle 永久残留在 IfaceCommon.sockets中。
同样,后面这段也存在同类问题:
if let Err(err) = inner.with_mut::<tcp::Socket, _, _>(|socket| {
socket.listen(listen_addr).map_err(|_| SystemError::ECONNREFUSED)
}) {
return Err((Init::Bound((inner, local)), err));
}
如果直接return Err((Init::Bound((inner, local)), err)),此时 inners 里可能已经存了多个 BoundInner,仍然会被丢弃并泄露。
另外,在Init::close的Bound 分支不 release,导致“关闭也清不掉”。
TcpSocket::do_close()在 Inner::Init(init) 分支会调用 init.close():
// kernel/src/net/socket/inet/stream/mod.rs:482
inner::Inner::Init(init) => {
init.close();
}
但是在Init::close没有对self.inners中的每个inner调用inner.close(),可能导致资源没有被释放。
- DragonOS版本(哈希值):a68030ea174daa4bbbdeca2994502185bc57930e
描述错误
在kernel/src/net/socket/inet/stream/inner.rs中,
enum Init的listen和close两个方法可能存在资源泄露问题。在
listen方法中通过一个for循环来创建新的BoundInner,并将socket绑定到self中存储的IP地址上,BoundInner::bind会把socket添加到对应的iface中。如果循环中途(或闭包末尾)返回 Err:
已经成功 bind的那些 BoundInner 都在 inners 里,接着直接被 drop,但由于 BoundInner 没有 Drop 释放逻辑,不会调用
BoundInner::release将这些socket释放到结果:这些 socket handle 永久残留在
IfaceCommon.sockets中。同样,后面这段也存在同类问题:
如果直接return Err((Init::Bound((inner, local)), err)),此时 inners 里可能已经存了多个 BoundInner,仍然会被丢弃并泄露。
另外,在
Init::close的Bound 分支不 release,导致“关闭也清不掉”。TcpSocket::do_close()在Inner::Init(init)分支会调用init.close():但是在
Init::close没有对self.inners中的每个inner调用inner.close(),可能导致资源没有被释放。