Fix race conditions in UNIX socket listen()

This commit is contained in:
Ruihan Li
2024-08-15 13:17:36 +08:00
committed by Tate, Hongliang Tian
parent a2d94675eb
commit ac19a7e0e7
2 changed files with 14 additions and 10 deletions

View File

@ -16,9 +16,9 @@ pub(super) struct Listener {
} }
impl Listener { impl Listener {
pub(super) fn new(addr: UnixSocketAddrBound, backlog: usize) -> Result<Self> { pub(super) fn new(addr: UnixSocketAddrBound, backlog: usize) -> Self {
let backlog = BACKLOG_TABLE.add_backlog(addr, backlog)?; let backlog = BACKLOG_TABLE.add_backlog(addr, backlog).unwrap();
Ok(Self { backlog }) Self { backlog }
} }
pub(super) fn addr(&self) -> &UnixSocketAddrBound { pub(super) fn addr(&self) -> &UnixSocketAddrBound {
@ -78,21 +78,22 @@ impl BacklogTable {
} }
} }
fn add_backlog(&self, addr: UnixSocketAddrBound, backlog: usize) -> Result<Arc<Backlog>> { fn add_backlog(&self, addr: UnixSocketAddrBound, backlog: usize) -> Option<Arc<Backlog>> {
let inode = { let inode = {
let UnixSocketAddrBound::Path(_, ref dentry) = addr else { let UnixSocketAddrBound::Path(_, ref dentry) = addr else {
todo!() todo!()
}; };
create_keyable_inode(dentry) create_keyable_inode(dentry)
}; };
let new_backlog = Arc::new(Backlog::new(addr, backlog));
let mut backlog_sockets = self.backlog_sockets.write(); let mut backlog_sockets = self.backlog_sockets.write();
if backlog_sockets.contains_key(&inode) { if backlog_sockets.contains_key(&inode) {
return_errno_with_message!(Errno::EADDRINUSE, "the addr is already used"); return None;
} }
let new_backlog = Arc::new(Backlog::new(addr, backlog));
backlog_sockets.insert(inode, new_backlog.clone()); backlog_sockets.insert(inode, new_backlog.clone());
Ok(new_backlog)
Some(new_backlog)
} }
fn get_backlog(&self, addr: &UnixSocketAddrBound) -> Result<Arc<Backlog>> { fn get_backlog(&self, addr: &UnixSocketAddrBound) -> Result<Arc<Backlog>> {

View File

@ -232,7 +232,9 @@ impl Socket for UnixStreamSocket {
} }
fn listen(&self, backlog: usize) -> Result<()> { fn listen(&self, backlog: usize) -> Result<()> {
let addr = match &*self.state.read() { let mut state = self.state.write();
let addr = match &*state {
State::Init(init) => init State::Init(init) => init
.addr() .addr()
.ok_or(Error::with_message( .ok_or(Error::with_message(
@ -248,8 +250,9 @@ impl Socket for UnixStreamSocket {
} }
}; };
let listener = Listener::new(addr, backlog)?; let listener = Listener::new(addr, backlog);
*self.state.write() = State::Listen(listener); *state = State::Listen(listener);
Ok(()) Ok(())
} }