Disabling tainting

Would it make sense to have a flag passed to the interpreter on startup
that
would allow you to disable tainting?

The goal would be to eliminate the performance losses caused by this
esoteric and not particularly useful feature.

Tony A. wrote:

Would it make sense to have a flag passed to the interpreter on startup
that
would allow you to disable tainting?

The goal would be to eliminate the performance losses caused by this
esoteric and not particularly useful feature.

I have had that thought recently, too–most apps don’t use $SAFE.

-r

Tony A. wrote:

The goal would be to eliminate the performance losses caused by this
esoteric and not particularly useful feature.
do you have benchmarks that show how much performance is lost by taint
checking? I’d assume it’s not even measurable.

[murphy]

On Mon, Oct 5, 2009 at 12:45 PM, Kornelius K.
[email protected]wrote:

do you have benchmarks that show how much performance is lost by taint
checking? I’d assume it’s not even measurable.

Actually my main motivation would be providing a migration path for
non-MRI
implementations of Ruby, which I guess is a bit strange.

It would be interesting to try to disable tainting in MRI/YARV and run
ruby-benchmark-suite on both and compare the results.

Sounds like an interesting weekend project.

Switching off taint checking at runtime doesn’t make sense, because it
adds an additional check (“do we have to do taint checking”) in case
it’s on, and keeps the same number of checks (one check; “do we have to
do taint checking” instead of “is the object tainted”) if switched off.

The way to gain some (probably not much) time would be a compile-time
switch. I can’t speak for Matz or Nobu, but I guess if you submit a
patch, and give some actual numbers of time saved, there’s some chance
it would be accepted.

Regards, Martin.

On Mon, Oct 5, 2009 at 8:56 PM, “Martin J. Dürst”
[email protected]wrote:

Switching off taint checking at runtime doesn’t make sense, because it adds
an additional check (“do we have to do taint checking”) in case it’s on, and
keeps the same number of checks (one check; “do we have to do taint
checking” instead of “is the object tainted”) if switched off.

I’m sure there’s a solution (function pointer or otherwise) that would
eliminate the need to branch on “do we have to do taint checking” every
single time a message is dispatched which would work for MRI/YARV, even
if
it were a runtime flag.

2009/10/6 Tony A. [email protected]:

The goal would be to eliminate the performance losses caused by this
esoteric and not particularly useful feature.

Why do you think the feature is not useful?
It might not be useful for you but some ruby programs developed on
early era often use it.
And Ruby 1.9 has even trust/untrusted model in addition to
taint/untainted for more secure/usable security checking.

Could you tell us your opinion? Or your patch will be rejected even if
you will have disabled the feature.

– Yuki S. (Yugui)

Excerpts from Tony A.'s message of Tue Oct 06 07:33:28 +0300 2009:

I’m sure there’s a solution (function pointer or otherwise) that would
eliminate the need to branch on “do we have to do taint checking” every
single time a message is dispatched which would work for MRI/YARV, even if
it were a runtime flag.

Only if the taintedness were always checked in method
dispatch, I think. Currently taint is checked individually
by various methods, so you would need to either provide
non-checking versions of each or you end up testing for
a flag anyway.

Both it and freezing could certainly be compile-time
options.

Eero

On Tue, Oct 6, 2009 at 3:52 AM, Yugui [email protected] wrote:

Why do you think the feature is not useful?

To really build a secure system around something like $SAFE/taint, you
must
be extremely vigilant with handling the flow of tainted objects through
the
system. One little mistake anywhere and it doesn’t offer you any
security
at all.

It might not be useful for you but some ruby programs developed on
early era often use it.

That’s fine, but 99.9% of Ruby programs out there don’t use it and it
impacts performance, so isn’t making it an on-by-default configurable
option
a good idea?

And Ruby 1.9 has even trust/untrusted model in addition to
taint/untainted for more secure/usable security checking.

The need for something like trust/untrusted shows is that $SAFE/taint
are no
where good enough.

Hi,

In message “Re: [ruby-core:25981] Re: Disabling tainting”
on Wed, 7 Oct 2009 12:11:57 +0900, Tony A. [email protected]
writes:

|To really build a secure system around something like $SAFE/taint, you must
|be extremely vigilant with handling the flow of tainted objects through the
|system. One little mistake anywhere and it doesn’t offer you any security
|at all.

As an application security should be perfect. But in the process of
developing one, detecting even 50% of security issues are using, and I
believe taint system catches far more than 50%.

|> It might not be useful for you but some ruby programs developed on
|> early era often use it.
|
|That’s fine, but 99.9% of Ruby programs out there don’t use it and it
|impacts performance, so isn’t making it an on-by-default configurable option
|a good idea?

Did you say “impacts”? Do you know how much impact it does for
performance? I don’t buy any performance proposals without
measurement. I am afraid you cannot measure any difference at all,
when you remove tainting.

          matz.

No, but it looks with that I could actually get some. Thanks.

Hi,

At Wed, 7 Oct 2009 12:11:57 +0900,

That’s fine, but 99.9% of Ruby programs out there don’t use it and it
impacts performance, so isn’t making it an on-by-default configurable option
a good idea?

Do you have exact data?

Index: configure.in

— configure.in (revision 25254)
+++ configure.in (working copy)
@@ -2131,4 +2131,11 @@ esac
AC_SUBST(INSTALLDOC)

+AC_ARG_ENABLE(taintness-checking,

  • AS_HELP_STRING([–disable-taintness-checking], [do not check
    taintness]),
  • [taintness_checking=$enableval], [taintness_checking=yes])
    +if test $taintness_checking = no; then
  • AC_DEFINE(RUBY_DISABLE_TAINTNESS)
    +fi

if test “$rb_with_pthread” = “yes”; then
THREAD_MODEL=pthread
Index: include/ruby/ruby.h

— include/ruby/ruby.h (revision 25254)
+++ include/ruby/ruby.h (working copy)
@@ -513,8 +513,14 @@ VALUE rb_int2big(SIGNED_VALUE);
VALUE rb_newobj(void);
#define NEWOBJ(obj,type) type obj = (type)rb_newobj()
+#ifdef RUBY_DISABLE_TAINTNESS
+#define TAINT_IF_UNSAFE(level, obj) \

  • if (rb_safe_level() >= level) FL_SET(obj, FL_TAINT | FL_UNTRUSTED)
    +#else
    +#define TAINT_IF_UNSAFE(level, obj) (void)0
    +#endif
    #define OBJSETUP(obj,c,t) do {
    RBASIC(obj)->flags = (t);
    RBASIC(obj)->klass = ©;\
  • if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT | FL_UNTRUSTED);\
  • TAINT_IF_UNSAFE(3, obj);
    } while (0)
    #define CLONESETUP(clone,obj) do {
    @@ -891,4 +897,11 @@ struct RBignum {
    #define FL_REVERSE(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags ^= (f);}
    while (0)

+#ifdef RUBY_DISABLE_TAINTNESS
+#define OBJ_TAINTED(x) 0
+#define OBJ_TAINT(x) do {(void)(x);} while (0)
+#define OBJ_UNTRUSTED(x) 0
+#define OBJ_UNTRUST(x) do {(void)(x);} while (0)
+#define OBJ_INFECT(x,s) do {(void)(x);(void)(s);} while (0)
+#else
#define OBJ_TAINTED(x) (!!FL_TEST((x), FL_TAINT))
#define OBJ_TAINT(x) FL_SET((x), FL_TAINT)
@@ -896,4 +909,5 @@ struct RBignum {
#define OBJ_UNTRUST(x) FL_SET((x), FL_UNTRUSTED)
#define OBJ_INFECT(x,s) do {if (FL_ABLE(x) && FL_ABLE(s))
RBASIC(x)->flags |= RBASIC(s)->flags & (FL_TAINT | FL_UNTRUSTED);} while
(0)
+#endif

#define OBJ_FROZEN(x) (!!FL_TEST((x), FL_FREEZE))

Tony A. wrote:

That’s fine, but 99.9% of Ruby programs out there don’t use it and it
impacts performance, so isn’t making it an on-by-default
configurable option a good idea?
I would find it confusing to have Ruby versions with different features.
code that works on one Ruby would no longer work on the
Ruby-w/o-tainting version, or the other way round. it’s complictaed
enough to have Ruby 1.8.6, 1.8.7, and 1.9.1 for now.

so, no, in my view it would not be a good idea to use a compile-time
switch that make Rubys with different feature sets.

but it would still be very interesting to measure the performance impact
of some features :slight_smile:

does JRuby have such a switch?

[murphy]

No, but it looks with that I could actually get some. Thanks.

You might try it without gc_stress, too :slight_smile:

-r

On Tue, Oct 6, 2009 at 9:48 PM, Yukihiro M.
[email protected]wrote:

Did you say “impacts”? Do you know how much impact it does for
performance? I don’t buy any performance proposals without
measurement. I am afraid you cannot measure any difference at all,
when you remove tainting.

I’ll see if I can put together some numbers on the performance impacts.

Tony A.
Medioh/Nagravision

On Wed, Oct 7, 2009 at 8:59 AM, Kornelius K. [email protected]
wrote:

does JRuby have such a switch?

I did an experiment to turn off tainting in JRuby, running a benchmark
that manually reverses a long string several times. With no
modifications, JRuby’s best time on the benchmark was 3.409s (compare
to Ruby 1.9’s time of 7.08s). With tainting and untrust removed,
performance improved to 3.28s, but it was pretty noisy, usually faster
but sometimes slower. So there’s a small, possibly measurable
improvement from eliminating taint, but it’s rather small.

The unfortunate thing is that although tainting (and now the
additional “untrust” flag in 1.9) don’t have a high perf impact, they
have a very large implementation impact. The codebase essentially has
to be littered with taint checks, which makes it possibly the worst
way to do security (very high chance of minor changes introducing
security holes). I’m not sure any alternative implementation (other
than JRuby) has even come close to getting tainting right, and we
don’t even use the value since we don’t support SAFE levels (which
require a whole other set of checks, equally as fragile).

  • Charlie

On Oct 7, 2009, at 7:59 AM, Kornelius K. wrote:

so, no, in my view it would not be a good idea to use a compile-time
switch that make Rubys with different feature sets.

but it would still be very interesting to measure the performance
impact
of some features :slight_smile:

does JRuby have such a switch?

No. JRuby just doesn’t implement $SAFE.

 [apatterson@higgins ~]$ ~/Downloads/jruby-1.3.1/bin/jruby -

e’$SAFE = 1’
-e:1 warning: SAFE levels are not supported in JRuby
[apatterson@higgins ~]$


Aaron P.
http://tenderlovemaking.com