Ruby tainting on primitives

Hi there,

I am trying to use tainting on Ruby primitives, but it seems to be
difficult:

~ (main) > x = 123
=> 123
~ (main) > x.taint
=> 123
~ (main) > x.tainted?
=> false
~ (main) > x = 999999999999999999999999999999999
=> 999999999999999999999999999999999
~ (main) > x.taint
=> 999999999999999999999999999999999
~ (main) > x.tainted?
=> true
~ (main) >

Fixnum doesn’t allow to be tainted, but Bignums are.
I was wondering if we could upgrade Fixnums into Bignums whenever they
get tainted.
In other words, I’d like automatic boxing on primitives when tainting is
used.

that was fixed in 2.0 or 2.1dev at there Fixnums and Bignums are now
frozen and cant be tainted or untrusted anymore (they also cant hold
instance variables anymore)

Maybe I was not clear.

I actually want to be able to taint numbers (and also booleans).
Ruby makes numbers and booleans behave like instances of classes, and so
I would expect tainting to work normally (in some ways, the abstraction
is leaking).

On Wed, Mar 20, 2013 at 8:23 AM, Nicolas V. [email protected]
wrote:

Maybe I was not clear.

I actually want to be able to taint numbers (and also booleans).
Ruby makes numbers and booleans behave like instances of classes, and so
I would expect tainting to work normally (in some ways, the abstraction
is leaking).

What would be the point in tainting numbers? Numbers are immutable
anyway (well, you can set instance variables but that won’t change
their behavior). Also, since Fixnums are singletons tainting would
affect all locations - not likely that you would want that.

Kind regards

robert

it does not work because this primitives are instances of Classes, but
on the C side they does not have a Struct that hold this information …

so tainting or untrusting does not work. (ok for some reason you can
freeze boolean, but i dont know why)

I’d like to use tainting to keep track of some data moving around.

The fact that numbers are immutable isn’t really relevant. The fact that
they’re immutable doesn’t necessitate they be singletons.

I realize that Fixnums are implemented as singletons as an optimization,
but that’s an implementation detail that shouldn’t change the behavior
of tainting. Ruby abstracts the implementation of Fixnums in other ways.
For example, running 123.class suggests that 123 is an instance of
Fixnum. I don’t understand why tainting should be different.

On Wed, Mar 20, 2013 at 6:35 PM, Nicolas V. [email protected]
wrote:

I’d like to use tainting to keep track of some data moving around.

The fact that numbers are immutable isn’t really relevant. The fact that
they’re immutable doesn’t necessitate they be singletons.

But they are singletons. That is a fact.

I realize that Fixnums are implemented as singletons as an optimization,
but that’s an implementation detail that shouldn’t change the behavior
of tainting.

It doesn’t. But tainting is associated with the instance. Hence if
you taint 0 all empty Arrays and Hashes will return a tainted 0 as
result of #size. That doesn’t make sense at all. It also won’t help
you with tracking “data moving around”.

Ruby abstracts the implementation of Fixnums in other ways.
For example, running 123.class suggests that 123 is an instance of
Fixnum. I don’t understand why tainting should be different.

See above.

Cheers

robert

On Mar 20, 2013, at 15:41 , “Nicolas V.” [email protected] wrote:

Let me formulate it like this: if I wrote a patch for Ruby to support
tainting Fixnums with no performance overhead, would you accept it, or
do you think tainting Fixnums semantically does not make sense? If not,
why?

Is there a practical reason to taint a number? Is there something I’m
not getting?

On Wed, Mar 20, 2013 at 11:41 PM, Nicolas V. [email protected]
wrote:

I understand now that we cannot taint Fixnums in the current Ruby
implementations.

My question is whether there is an inherent conceptual reason not to
support this behavior based on the language model Ruby tries to provide.
You said that tainting Fixnums is not possible because Fixnums because
they are implemented as singletons for performance reasons. But this is
an implementation detail, not something that’s part of the language
model.

It may be an implementation detail in other contexts but when it comes
to attaching state to a singleton it is an important feature because
all users of the singleton will be affected.

Let me formulate it like this: if I wrote a patch for Ruby to support
tainting Fixnums with no performance overhead, would you accept it, or
do you think tainting Fixnums semantically does not make sense? If not,
why?

I would not accept it because of the unwanted side effects. I have
explained that in my previous posting. Since you did not react to it
I have no idea whether you read or understood it. If not, please do.

Cheers

robert

I understand now that we cannot taint Fixnums in the current Ruby
implementations.

My question is whether there is an inherent conceptual reason not to
support this behavior based on the language model Ruby tries to provide.
You said that tainting Fixnums is not possible because Fixnums because
they are implemented as singletons for performance reasons. But this is
an implementation detail, not something that’s part of the language
model.

Let me formulate it like this: if I wrote a patch for Ruby to support
tainting Fixnums with no performance overhead, would you accept it, or
do you think tainting Fixnums semantically does not make sense? If not,
why?

We would preserve all the semantics. Let me explain.

For example, when the user tries to taint a Fixnum, instead of throwing
a freeze error, we would upgrade the Fixnum into a Bignum.
In other words, we can box primitives when the user tries to taint.
Tainted numbers would obviously have a performance hit due to the
unboxing, but I don’t expect performance regressions for code that does
not taint Fixnums.

Hans M. wrote in post #1102567:

did you image how to “upgrade the Fixnum into a Bignum.”?
Fair enough, I was wrong.

it does not make sense, cause the world of Integer is parted … little
ones are Fixnum, big ones are Bignum.

you cant “upgrade” them so that you get an Bignum with the same value as
a fixnum, you need a Holder Class for that, and if you use a
HolderClass, you already have something that can be tainted

Which brings me to this point. I think it would be nice if we could use
Bignum as HolderClass for Fixnum. For example, 123.to_fixnum would
return a Bignum of value 123. Operations involving a tainted Bignum
would preserve the semantics. For example with an addition:
BignumTainted + Fixnum -> BignumTainted.

Would it be preferable to implement that HolderClass in userland? or in
Ruby?

did you image how to “upgrade the Fixnum into a Bignum.”?

it does not make sense, cause the world of Integer is parted … little
ones are Fixnum, big ones are Bignum.

you cant “upgrade” them so that you get an Bignum with the same value as
a fixnum, you need a Holder Class for that, and if you use a
HolderClass, you already have something that can be tainted

On Mar 21, 2013, at 02:34 , Nicolas V. [email protected] wrote:

We would preserve all the semantics. Let me explain.

Which gets you … what?

Tainting a number makes no sense to me. You can’t use it as an attack
vector. You can’t get it from a socket. You can’t get it from a file.
Basically… to get a number, you’ve already untainted it at some point.
The only place I can think of where you can get a number from an
external resource is via marshal or some other marshalling format. If it
is already compromised, you’ve got other problems.

On Mar 21, 2013, at 17:53 , Nicolas V. [email protected] wrote:

I don’t use tainting to achieve some level of security, but to perform
various optimization in a distributed algorithm.

which is not what tainting is for.

That is actually where I’m coming from. Some JSON is coming from an
external source, and I would like to track the parsed content.

The default JSON parser has its own set of problems:

(main) > json = ‘{“key”:“value”}’;
(main) > json.taint
=> “{“key”:“value”}”
(main) > json.tainted?
=> true
(main) > JSON.parse(json).tainted?
=> false
(main) > JSON.parse(json)[‘key’].tainted?
=> false

Assuming this is easily fixable, I would like to track the parsed data,
especially numbers.

I don’t use tainting to achieve some level of security, but to perform
various optimization in a distributed algorithm.

Wouldn’t it be simpler to create a custom class with an attribute that
covers this? I should think that using taint just to track numbers could
have nasty side effects if your program expanded later.

Ryan D. wrote in post #1102698:

On Mar 21, 2013, at 17:53 , Nicolas V. [email protected] wrote:

I don’t use tainting to achieve some level of security, but to perform
various optimization in a distributed algorithm.

which is not what tainting is for.

Oh wow.

I am going out of the discussion,
Thanks.