-
-
Notifications
You must be signed in to change notification settings - Fork 168
Open
Labels
bug-report这是一个bug报告(如果确认是一个bug,请管理人员添加`bug` label)这是一个bug报告(如果确认是一个bug,请管理人员添加`bug` label)
Description
描述错误
在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
Metadata
Metadata
Assignees
Labels
bug-report这是一个bug报告(如果确认是一个bug,请管理人员添加`bug` label)这是一个bug报告(如果确认是一个bug,请管理人员添加`bug` label)