Skip to content

Commit 788cb4c

Browse files
committed
[GR-40769] Check for native access when creating a Pointer
PullRequest: truffleruby/3474
2 parents 2607892 + f94339e commit 788cb4c

File tree

19 files changed

+187
-110
lines changed

19 files changed

+187
-110
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ Changes:
5959
* Refactored sharing of array objects between threads using new `SharedArrayStorage` (@aardvark179).
6060
* Marking of native structures wrapped in objects is now done on C call exit to reduce memory overhead (@aardvark179).
6161

62+
Security:
63+
64+
* The native access permission is now properly checked before any native pointer (e.g. `Truffle::FFI::Pointer`) is created (@eregon).
65+
6266
# 22.2.0
6367

6468
New features:

src/main/java/org/truffleruby/cext/CExtNodes.java

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.jcodings.Encoding;
2323
import org.jcodings.IntHolder;
2424
import org.truffleruby.Layouts;
25+
import org.truffleruby.RubyContext;
2526
import org.truffleruby.RubyLanguage;
2627
import org.truffleruby.builtins.CoreMethod;
2728
import org.truffleruby.builtins.CoreMethodArrayArgumentsNode;
@@ -149,9 +150,9 @@ public class CExtNodes {
149150
public static final int RUBY_TAG_THROW = 0x7;
150151
public static final int RUBY_TAG_FATAL = 0x8;
151152

152-
public static Pointer newNativeStringPointer(int capacity, RubyLanguage language) {
153+
public static Pointer newNativeStringPointer(RubyLanguage language, RubyContext context, int capacity) {
153154
// We need up to 4 \0 bytes for UTF-32. Always use 4 for speed rather than checking the encoding min length.
154-
Pointer pointer = Pointer.mallocAutoRelease(capacity + 4, language);
155+
Pointer pointer = Pointer.mallocAutoRelease(language, context, capacity + 4);
155156
pointer.writeInt(capacity, 0);
156157
return pointer;
157158
}
@@ -765,7 +766,7 @@ public abstract static class RbStrNewNulNode extends CoreMethodArrayArgumentsNod
765766
@Specialization
766767
protected RubyString rbStrNewNul(int byteLength,
767768
@Cached MutableTruffleString.FromNativePointerNode fromNativePointerNode) {
768-
final Pointer pointer = Pointer.callocAutoRelease(byteLength + 1, getLanguage());
769+
final Pointer pointer = Pointer.callocAutoRelease(getLanguage(), getContext(), byteLength + 1);
769770
var nativeTString = fromNativePointerNode.execute(pointer, 0, byteLength, Encodings.BINARY.tencoding,
770771
false);
771772
return createMutableString(nativeTString, Encodings.BINARY);
@@ -842,8 +843,8 @@ protected RubyString rbStrResize(RubyString string, int newByteLength,
842843
string.clearCodeRange();
843844
return string;
844845
} else {
845-
var newNativeTString = TrStrCapaResizeNode.resize(pointer, newByteLength, newByteLength, tencoding,
846-
fromNativePointerNode, getLanguage());
846+
var newNativeTString = TrStrCapaResizeNode.resize(getLanguage(), getContext(), pointer, newByteLength,
847+
newByteLength, tencoding, fromNativePointerNode);
847848
string.setTString(newNativeTString);
848849

849850
// Like MRI's rb_str_resize()
@@ -869,18 +870,18 @@ protected RubyString trStrCapaResize(RubyString string, int newCapacity,
869870
return string;
870871
} else {
871872
int byteLength = string.tstring.byteLength(tencoding);
872-
var newNativeTString = resize(pointer, newCapacity, byteLength, tencoding, fromNativePointerNode,
873-
getLanguage());
873+
var newNativeTString = resize(getLanguage(), getContext(), pointer, newCapacity, byteLength, tencoding,
874+
fromNativePointerNode);
874875
string.setTString(newNativeTString);
875876

876877
return string;
877878
}
878879
}
879880

880-
static MutableTruffleString resize(Pointer pointer, int newCapacity, int newByteLength,
881-
TruffleString.Encoding tencoding, MutableTruffleString.FromNativePointerNode fromNativePointerNode,
882-
RubyLanguage language) {
883-
final Pointer newPointer = newNativeStringPointer(newCapacity, language);
881+
static MutableTruffleString resize(RubyLanguage language, RubyContext context, Pointer pointer, int newCapacity,
882+
int newByteLength, TruffleString.Encoding tencoding,
883+
MutableTruffleString.FromNativePointerNode fromNativePointerNode) {
884+
final Pointer newPointer = newNativeStringPointer(language, context, newCapacity);
884885
newPointer.writeBytes(0, pointer, 0, Math.min(pointer.getSize(), newCapacity));
885886

886887
return fromNativePointerNode.execute(newPointer, 0, newByteLength, tencoding, false);
@@ -1285,8 +1286,8 @@ protected Pointer toNative(RubyString string,
12851286
pointer = (Pointer) getInternalNativePointerNode.execute(tstring, tencoding);
12861287
} else {
12871288
int byteLength = tstring.byteLength(tencoding);
1288-
pointer = allocateAndCopyToNative(tstring, tencoding, byteLength, copyToNativeMemoryNode,
1289-
getLanguage());
1289+
pointer = allocateAndCopyToNative(getLanguage(), getContext(), tstring, tencoding, byteLength,
1290+
copyToNativeMemoryNode);
12901291

12911292
var nativeTString = fromNativePointerNode.execute(pointer, 0, byteLength, tencoding, false);
12921293
string.setTString(nativeTString);
@@ -1300,9 +1301,10 @@ protected Pointer toNativeImmutable(ImmutableRubyString string) {
13001301
return string.getNativeString(getLanguage());
13011302
}
13021303

1303-
public static Pointer allocateAndCopyToNative(AbstractTruffleString tstring, TruffleString.Encoding tencoding,
1304-
int capacity, TruffleString.CopyToNativeMemoryNode copyToNativeMemoryNode, RubyLanguage language) {
1305-
final Pointer pointer = newNativeStringPointer(capacity, language);
1304+
public static Pointer allocateAndCopyToNative(RubyLanguage language, RubyContext context,
1305+
AbstractTruffleString tstring, TruffleString.Encoding tencoding, int capacity,
1306+
TruffleString.CopyToNativeMemoryNode copyToNativeMemoryNode) {
1307+
final Pointer pointer = newNativeStringPointer(language, context, capacity);
13061308
copyToNativeMemoryNode.execute(tstring, 0, pointer, 0, capacity, tencoding);
13071309
return pointer;
13081310
}
@@ -2026,7 +2028,7 @@ public abstract static class DataHolderCreate extends PrimitiveArrayArgumentsNod
20262028

20272029
@Specialization
20282030
protected DataHolder create(Object address) {
2029-
return new DataHolder(address, Pointer.NULL);
2031+
return new DataHolder(address, Pointer.getNullPointer(getContext()));
20302032
}
20312033
}
20322034

src/main/java/org/truffleruby/cext/DataHolder.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ public final class DataHolder implements TruffleObject {
2626
private Object pointer;
2727
private Object marker;
2828

29-
public DataHolder(Object address, Object marker) {
30-
this.pointer = address;
29+
public DataHolder(Object pointer, Object marker) {
30+
this.pointer = pointer;
3131
this.marker = marker;
3232
}
3333

3434
public Object getPointer() {
3535
return pointer;
3636
}
3737

38-
public void setPointer(Object address) {
39-
this.pointer = address;
38+
public void setPointer(Object pointer) {
39+
this.pointer = pointer;
4040
}
4141

4242
public Object getMarker() {

src/main/java/org/truffleruby/core/VMPrimitiveNodes.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -643,9 +643,9 @@ protected long argvLength() {
643643
}
644644

645645
int argc = getContext().nativeArgc;
646-
Pointer argv = new Pointer(getContext().nativeArgv, argc * Pointer.SIZE);
647-
Pointer first = argv.readPointer(0);
648-
Pointer last = argv.readPointer((argc - 1) * Pointer.SIZE);
646+
Pointer argv = new Pointer(getContext(), getContext().nativeArgv, argc * Pointer.SIZE);
647+
Pointer first = argv.readPointer(getContext(), 0);
648+
Pointer last = argv.readPointer(getContext(), (argc - 1) * Pointer.SIZE);
649649
long lastByte = last.getAddress() + last.findNullByte(getContext(), InteropLibrary.getUncached(), 0);
650650
nativeArgvLength = lastByte - first.getAddress();
651651

src/main/java/org/truffleruby/core/array/ArrayNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2325,7 +2325,7 @@ protected RubyArray storeToNative(RubyArray array,
23252325
@Cached IsSharedNode isSharedNode,
23262326
@Cached ConditionProfile sharedProfile) {
23272327
final int size = arraySizeProfile.profile(array.size);
2328-
Pointer pointer = Pointer.mallocAutoRelease(size * Pointer.SIZE, getLanguage());
2328+
Pointer pointer = Pointer.mallocAutoRelease(getLanguage(), getContext(), size * Pointer.SIZE);
23292329
Object newStore = new NativeArrayStorage(pointer, size);
23302330
stores.copyContents(store, 0, newStore, 0, size);
23312331
array.setStore(newStore);

src/main/java/org/truffleruby/core/array/library/NativeArrayStorage.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
1919
import com.oracle.truffle.api.profiles.ConditionProfile;
2020
import com.oracle.truffle.api.profiles.LoopConditionProfile;
21+
import org.truffleruby.RubyContext;
2122
import org.truffleruby.cext.UnwrapNode;
2223
import org.truffleruby.cext.UnwrapNodeGen.UnwrapNativeNodeGen;
2324
import org.truffleruby.cext.ValueWrapper;
@@ -122,9 +123,10 @@ protected int capacity() {
122123
}
123124

124125
@ExportMessage
125-
protected NativeArrayStorage expand(int newCapacity) {
126+
protected NativeArrayStorage expand(int newCapacity,
127+
@CachedLibrary("this") ArrayStoreLibrary node) {
126128
final int capacity = this.length;
127-
Pointer newPointer = Pointer.malloc(capacity);
129+
Pointer newPointer = Pointer.malloc(RubyContext.get(node), capacity);
128130
newPointer.writeBytes(0, pointer, 0, capacity);
129131
newPointer.writeBytes(capacity, newCapacity - capacity, (byte) 0);
130132
/* We copy the contents of the marked objects to ensure the references will be kept alive even if the old store

src/main/java/org/truffleruby/core/encoding/EncodingManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ private void initializeLocaleEncoding(TruffleNFIPlatform nfi, NativeConfiguratio
153153
} catch (InteropException e) {
154154
throw CompilerDirectives.shouldNotReachHere(e);
155155
}
156-
final byte[] bytes = new Pointer(address).readZeroTerminatedByteArray(
156+
final byte[] bytes = new Pointer(context, address).readZeroTerminatedByteArray(
157157
context,
158158
InteropLibrary.getUncached(),
159159
0);

src/main/java/org/truffleruby/core/format/read/bytes/ReadStringPointerNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ protected MissingValue decode(Nil nil) {
4848
protected RubyString read(VirtualFrame frame, long address,
4949
@CachedLibrary(limit = "getRubyLibraryCacheLimit()") RubyLibrary rubyLibrary,
5050
@CachedLibrary(limit = "1") InteropLibrary interop) {
51-
final Pointer pointer = new Pointer(address);
51+
final Pointer pointer = new Pointer(getContext(), address);
5252
checkAssociated(
5353
(Pointer[]) frame.getObject(FormatFrameDescriptor.SOURCE_ASSOCIATED_SLOT),
5454
pointer);

src/main/java/org/truffleruby/core/string/ImmutableRubyString.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,9 @@ private synchronized Pointer createNativeString(RubyLanguage language) {
8484
if (nativeString == null) {
8585
var tencoding = getEncodingUncached().tencoding;
8686
int byteLength = tstring.byteLength(tencoding);
87-
nativeString = CExtNodes.StringToNativeNode.allocateAndCopyToNative(tstring, tencoding, byteLength,
88-
TruffleString.CopyToNativeMemoryNode.getUncached(), language);
87+
nativeString = CExtNodes.StringToNativeNode.allocateAndCopyToNative(language,
88+
RubyLanguage.getCurrentContext(), tstring, tencoding, byteLength,
89+
TruffleString.CopyToNativeMemoryNode.getUncached());
8990
}
9091
return nativeString;
9192
}

src/main/java/org/truffleruby/core/string/StringNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ protected Object initializeCopyNative(RubyString self, RubyString from,
15891589
var tencoding = encoding.tencoding;
15901590
final Pointer fromPointer = (Pointer) getInternalNativePointerNode.execute(tstring, tencoding);
15911591

1592-
final Pointer newPointer = Pointer.mallocAutoRelease(fromPointer.getSize(), getLanguage());
1592+
final Pointer newPointer = Pointer.mallocAutoRelease(getLanguage(), getContext(), fromPointer.getSize());
15931593
newPointer.writeBytes(0, fromPointer, 0, fromPointer.getSize());
15941594

15951595
// TODO (eregon, 2022): should we have the copy be native too, or rather take the opportunity of having to copy to be managed?

0 commit comments

Comments
 (0)