あおきです。

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;