あおきです。
ruby-list のセキュリティのスレッドを読んで穴を探してみたんですが、
dl を経由するとなんでもできることがわかりました。たとえば次の
コードで sh が起動できます。
require 'dl'
$SAFE = 4
DL.dlopen('libc.so.6').sym('system', 'IS').call("/bin/sh")
とりあえず最低限のパッチだけ付けます。セキュリティレベル
いくつで拒否するのかという点や、ptr の汚染などはちゃんと
考える必要がありそうです。
-------------------------------------------------------------------
青木峰郎
Index: dl.c
===================================================================
RCS file: /home/aamine/cvs/ruby/ruby/ext/dl/dl.c,v
retrieving revision 1.16
diff -u -p -r1.16 dl.c
--- dl.c 16 Jan 2003 07:38:40 -0000 1.16
+++ dl.c 21 Mar 2003 03:46:06 -0000
@@ -542,18 +542,21 @@ rb_io_to_ptr(VALUE self)
VALUE
rb_dl_dlopen(int argc, VALUE argv[], VALUE self)
{
+ rb_secure(2);
return rb_class_new_instance(argc, argv, rb_cDLHandle);
}
VALUE
rb_dl_malloc(VALUE self, VALUE size)
{
+ rb_secure(2);
return rb_dlptr_malloc(DLNUM2LONG(size), dlfree);
}
VALUE
rb_dl_strdup(VALUE self, VALUE str)
{
+ rb_secure(2);
str = rb_String(str);
return rb_dlptr_new(strdup(RSTRING(str)->ptr), RSTRING(str)->len, dlfree);
}
@@ -561,6 +564,7 @@ rb_dl_strdup(VALUE self, VALUE str)
static VALUE
rb_dl_sizeof(VALUE self, VALUE str)
{
+ rb_secure(2);
return INT2NUM(dlsizeof(StringValuePtr(str)));
}
@@ -571,6 +575,7 @@ rb_dl_callback(int argc, VALUE argv[], V
int rettype, entry, i;
char fname[127];
+ rb_secure(2);
proc = Qnil;
switch( rb_scan_args(argc, argv, "11", &type, &proc) ){
case 1:
@@ -636,9 +641,11 @@ rb_dl_callback(int argc, VALUE argv[], V
static VALUE
rb_dl_remove_callback(VALUE mod, VALUE sym)
{
- freefunc_t f = rb_dlsym2csym(sym);
+ freefunc_t f;
int i, j;
+ rb_secure(2);
+ f = rb_dlsym2csym(sym);
for( i=0; i < CALLBACK_TYPES; i++ ){
for( j=0; j < MAX_CALLBACK; j++ ){
if( rb_dl_callback_table[i][j] == f ){
Index: sym.c
===================================================================
RCS file: /home/aamine/cvs/ruby/ruby/ext/dl/sym.c,v
retrieving revision 1.16
diff -u -p -r1.16 sym.c
--- sym.c 16 Jan 2003 07:38:40 -0000 1.16
+++ sym.c 21 Mar 2003 03:46:39 -0000
@@ -77,6 +77,7 @@ rb_dlsym_new(void (*func)(), const char
struct sym_data *data;
const char *ptype;
+ rb_secure(2);
if( !type || !type[0] ){
return rb_dlptr_new((void*)func, 0, 0);
}
@@ -329,6 +330,7 @@ rb_dlsym_call(int argc, VALUE argv[], VA
long ftype;
void *func;
+ rb_secure(2);
Data_Get_Struct(self, struct sym_data, sym);
DEBUG_CODE({
printf("rb_dlsym_call(): type = '%s', func = 0x%x\n", sym->type, sym->func);
Index: ptr.c
===================================================================
RCS file: /home/aamine/cvs/ruby/ruby/ext/dl/ptr.c,v
retrieving revision 1.16
diff -u -p -r1.16 ptr.c
--- ptr.c 16 Jan 2003 07:38:40 -0000 1.16
+++ ptr.c 21 Mar 2003 03:49:29 -0000
@@ -26,6 +26,7 @@ rb_hash_delete(VALUE hash, VALUE key)
static void
rb_dlmem_delete(void *ptr)
{
+ rb_secure(2);
rb_hash_delete(DLMemoryTable, DLLONG2NUM(ptr));
}
@@ -89,6 +90,7 @@ rb_dlptr_new2(VALUE klass, void *ptr, lo
struct ptr_data *data;
VALUE val;
+ rb_secure(2);
if( ptr ){
val = rb_dlmem_aref(ptr);
if( val == Qnil ){
@@ -130,6 +132,7 @@ rb_dlptr_malloc(long size, freefunc_t fu
{
void *ptr;
+ rb_secure(2);
ptr = dlmalloc((size_t)size);
memset(ptr,0,(size_t)size);
return rb_dlptr_new(ptr, size, func);
@@ -161,6 +164,7 @@ rb_dlptr_s_allocate(VALUE klass)
VALUE obj;
struct ptr_data *data;
+ rb_secure(2);
obj = Data_Make_Struct(klass, struct ptr_data, 0, dlptr_free, data);
data->ptr = 0;
data->free = 0;
@@ -850,6 +854,7 @@ rb_dlptr_aset(int argc, VALUE argv[], VA
long memsize;
void *memimg;
+ rb_secure(2);
switch( rb_scan_args(argc, argv, "21", &key, &num, &val) ){
case 2:
val = num;