[ruby-core:121673] [Ruby Bug#21212] IO::Buffer can be freed while its slice is locked
From:
"hanazuki (Kasumi Hanazuki) via ruby-core" <ruby-core@...>
Date:
2025-04-16 15:45:29 UTC
List:
ruby-core #121673
Issue #21212 has been updated by hanazuki (Kasumi Hanazuki).
I think the problem is that each IO::Buffer slice manages the lock state independently, and so the root IO::Buffer cannot know whether the memory is locked by one of its slices.
If the memory is being accessed by a native function like `rb_io_buffer_read` when the buffer is freed, this may be a loophole to trigger use-after-free.
```ruby
# Assume this file is on a very slow device such as NFS.
io = File.open('/mnt/slowfs/slow')
buffer = IO::Buffer.new(100)
slice = buffer.slice
t1 = Thread.new do
puts "start reading"
slice.read(io) # This takes too long.
# If the memory backing the slice is freed already, read can write into invalid address.
puts "finished reading"
end
t2 = Thread.new do
sleep 0.5 # This waits for the read to begin.
buffer.free # This may free the buffer before the read finishes.
puts "freed buffer"
end
t1.join
t2.join
```
----------------------------------------
Bug #21212: IO::Buffer can be freed while its slice is locked
https://bugs.ruby-lang.org/issues/21212#change-112725
* Author: hanazuki (Kasumi Hanazuki)
* Status: Open
* ruby -v: ruby 3.5.0dev (2025-04-01T16:11:01Z master 30e5e7c005) +PRISM [x86_64-linux]
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
```ruby
buffer = IO::Buffer.new(100)
slice = buffer.slice
buffer.locked do
buffer.free rescue p $! #=> IO::Buffer::LockedError (expected)
end
slice.locked do
p slice.locked? #=> true (expected)
p buffer.locked? #=> false (what should this be?)
slice.free rescue p $! #=> IO::Buffer::LockedError (expected)
buffer.free # Should we allow this?
slice.set_value(:U8, 0, 42) # raises IO::Buffer::InvalidatedError (surprising!)
end
```
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- [email protected]
To unsubscribe send an email to [email protected]
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/