Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Scripters, watch out in new version

Yumi Murakami
DoIt!AttachTheEarOfACat!
Join date: 27 Sep 2005
Posts: 6,860
11-29-2006 08:49
Just a fair warning about something I tested in the beta grid. I did report this to LL, but they probably weren't able to do anything to fix it.

In the new version, maximum chat length is 1024 characters. That means that any script you have that recieves any listen events is liable, at any time, to recieve one with a 1024 character argument. If your script doesn't have 1k of memory free, it will crash as soon as the listen event activates, before your code has even started running. Let me emphasise that: testing the length of the input string in the listen event is no good, because the script will crash as soon as the listen event is dispatched, while the LSL system is copying the parameters of the event into your script. Your actual scripted statements will never get a look in.

If you're doing any string handling on the message, be very careful of anything that uses negative indexing to clip off the end part of a string - you might be clipping off as much as 1023 characters, which could easily run your script out of memory during the temporary allocation.

Furthermore, if you have any code of this type:

CODE

listen(integer channel, string name, key id, string message) {
list messageBits = llParseString2List(message,[" "],[]);
....


Then you will almost certainly need to change this, as a griefer who comes up and says 1k worth of "a a a a a a a a a a a a a a a a a a a a..." will cause your ParseString2List call to return an 8k list. I can't think of very many serious scripts that could survive that.

The most obvious quick fix is to move the listen event into a seperate script, have it check the length, and then deliver the message to the real script via a link message if it's small enough. But this does generate an extra script's worth of lag, unfortunately.
RobbyRacoon Olmstead
Red warrior is hungry!
Join date: 20 Sep 2006
Posts: 1,821
11-29-2006 10:05
<sarcasm>Oh, wonderful!</sarcasm>

I should think something that exposes an attack vector like this would be worth delaying the update. I guess we can't know what back-end issues are being resolved by this update, perhaps those were critical to release as soon as possible, but I certainly hope this one gets fixed in the very near future.
Jacques Groshomme
Registered User
Join date: 16 Mar 2005
Posts: 355
11-29-2006 10:15
This seems to be a potential vulnerability with a very limited scope. It's also easily sidestepped by filtering out noise and validating any incoming data -- something that you should already be doing.

In order for a griefer to make use of this, they must already have a good amount of knowledge of your script's the inner workings - knowing what channel to spam on, knowing what patterns to spam, etc.

This isn't something that is suddenly going to make every script in world run into stack/heap errors.


Benefits of expanding the message length far outweigh the potential (and unlikely) pitfalls.
Yumi Murakami
DoIt!AttachTheEarOfACat!
Join date: 27 Sep 2005
Posts: 6,860
11-29-2006 10:21
From: Jacques Groshomme
This seems to be a potential vulnerability with a very limited scope. It's also easily sidestepped by filtering out noise and validating any incoming data -- something that you should already be doing.


I think you probably already understood this but I'll say it one more time just in case: you can't, at the moment, deal with this just by filtering. In the llListen call you can't put a limit on the number of characters in the message you recieve. And no amount of filtering in the listen event will help if the script doesn't have 1k of memory free: the out of memory error will occur before the filtering does. (Of course, things like doing string manipulation or list parsing on an outsize string can be stopped by filtering, but you need to make sure you have that base 1k free.)
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
11-29-2006 10:46
Yeah, I've been a little concerned about this possibility, too. Fortunately, it's not quite as bad as it could be: listen events waiting on the event queue don't take up your script memory, so an attacker can't send a rapid-fire barrage of 16 1023-length strings to your listen event and crash your script before it can even process them.

This is a sticky little problem, but I think the benefits of being able to send 1023-length messages FAR outweighs the potential denial-of-service vulnerabilities it opens. 255 characters at a time was severely limiting.
Kalel Venkman
Citizen
Join date: 10 Mar 2006
Posts: 587
One thing you CAN do..
11-29-2006 10:48
.. is check to make sure you have enough memory to handle a 1K listen before you turn the listen on, and after processing each listen, check available memory again and either turn listens off or reset the script if memory is too low. It's an extra hoop to jump through, but the expanded size of the available listen string is a boon, and scripts should probably be doing these sorts of memory tests in general anyway.
Dargon Pacer
Registered User
Join date: 2 Jul 2005
Posts: 19
maybe...
11-29-2006 11:19
I am kinda new at the LSL stuff, but just wondering if something like this might work..

llListen(Channel,llGetSubString(message,0,254),llGetOwner(), "";);
Jeremy Bender
anachronistic iconoclast
Join date: 12 Aug 2006
Posts: 99
11-29-2006 11:46
From: Lex Neva
... listen events waiting on the event queue don't take up your script memory, so an attacker can't send a rapid-fire barrage of 16 1023-length strings to your listen event and crash your script before it can even process them....
Can you explain this in more detail for the more "newbie-ish" in the audience?

Why can't a griefer simply make a device that scans up and down the channel spectrum spamming giant messages to crash all the scripts on the channel?
Dimentox Travanti
DCS Coder
Join date: 10 Sep 2006
Posts: 228
11-29-2006 12:28
they can
It would be easy
would take about 10 mins to run though all the channels.
_____________________
LSL Scripting Database - http://lsl.dimentox.com
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
11-29-2006 12:31
From: Dargon Pacer
I am kinda new at the LSL stuff, but just wondering if something like this might work..

llListen(Channel,llGetSubString(message,0,254),llGetOwner(), "";);


Sorry but no wont work at all.

The llListen call sets up the handler to start the listen, so will have no effect on the received data.

It may actually stop it working all together depending upon the contents of message when you perform the call. As written you are passing it in as the name of the object to listen for.

For the majority of scripts that I myself produce, I always know approximately how much data is expected, to within a few bytes anyway. So I dont think the problem is as great as first feared.
Dargon Pacer
Registered User
Join date: 2 Jul 2005
Posts: 19
11-29-2006 12:45
hrmm...so if I have a script that listens, and the current memmory is just about full (various lists etc) and it hears enough to go over the mem limit, it will error out on me?

Say for example a poker table script..lots of lists to keep track of when 10 people are playing..(hands, chips, player seats, whos turn it is, etc)...

for stupidity sake and better understanding the problem, say it only has 3 bits left available in mem. it listens and hears a 4 letter word like 'FOLD' ..and instead of folding the players hand, the script will 'FOLD' itself into a little stack_heap and weep endlessy until somebody resets it?
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
11-29-2006 12:51
From: Dargon Pacer
hrmm...so if I have a script that listens, and the current memmory is just about full (various lists etc) and it hears enough to go over the mem limit, it will error out on me?

Say for example a poker table script..lots of lists to keep track of when 10 people are playing..(hands, chips, player seats, whos turn it is, etc)...

for stupidity sake and better understanding the problem, say it only has 3 bits left available in mem. it listens and hears a 4 letter word like 'FOLD' ..and instead of folding the players hand, the script will 'FOLD' itself into a little stack_heap and weep endlessy until somebody resets it?


Exactly.....

The thing is this problem has always existed. Its not a new bug, its just that now we have 4 times the amount of potential data to worry about. For most "run of the mill" scripts it will not be a problem. If you are that close to the edge on memory then hopefully you will already have enough experience to be able to split the processing into one or more cooperative scripts. Taking the poker example, instead of one script maintaining the list of all 10 players, 11 scripts, one per player and a control/organiser.
Ralph Doctorow
Registered User
Join date: 16 Oct 2005
Posts: 560
11-29-2006 12:53
From: Newgate Ludd

For the majority of scripts that I myself produce, I always know approximately how much data is expected, to within a few bytes anyway. So I dont think the problem is as great as first feared.
But as the OP said, the only way to guard against this is to be sure you always have well over 1K memory free whenever a listen is active. There's no way in LSL to limit the amount of data gotten by a listen.

Having said that though, letting a script get that close to the edge is pretty dangerous IMHO. It's all too easy to make a copy of something like a string or array and have it blow up all by itself.
Showdog Tiger
Registered User
Join date: 30 Nov 2005
Posts: 404
Sob!
11-29-2006 12:59
Dearly Darlings,

Oh my! <sniffle> This will make my requisite 50,000 words per day a little harder to maintain for my membership in TLOLC (The Little Old Lady CLub)

Ever Yours,

Mrs. Showdog Tiger
_____________________
Dogdom Doge
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
11-29-2006 13:00
From: Ralph Doctorow
But as the OP said, the only way to guard against this is to be sure you always have well over 1K memory free whenever a listen is active. There's no way in LSL to limit the amount of data gotten by a listen.

Having said that though, letting a script get that close to the edge is pretty dangerous IMHO. It's all too easy to make a copy of something like a string or array and have it blow up all by itself.


precisely, (we crossed in the post)
If your running that tight then you probably need to think about spliting functionality.
RobbyRacoon Olmstead
Red warrior is hungry!
Join date: 20 Sep 2006
Posts: 1,821
11-29-2006 13:02
From: Jacques Groshomme
This seems to be a potential vulnerability with a very limited scope.

Agreed, but that doesn't make it harmless.

From: Jacques Groshomme
It's also easily sidestepped by filtering out noise and validating any incoming data -- something that you should already be doing.

And for the vast majority of scripts, this is already being done. Doesn't change the fact that it does not make sense for some scripts, for instance some scripts simply *cannot* filter by owner in order to work the way that they do.

From: Jacques Groshomme
In order for a griefer to make use of this, they must already have a good amount of knowledge of your script's the inner workings - knowing what channel to spam on, knowing what patterns to spam, etc.

I disagree. It takes very little information at all to know which channel to spam, for instance some very well known vendors have such information readily available to anyone that purchases them. Only the channel is necessary, and not even that if someone were to mass-spam or use a listener.

The big issue is that once the script crashes it must be manually reset, right? You cannot automatically reset a script that has stopped due to a stack/heap collision or runtime error.

From: Jacques Groshomme
This isn't something that is suddenly going to make every script in world run into stack/heap errors.

Nobody said it was. All anybody has really said is that this is a potential pain in the ass and could allow some jackass to crash *some* scripts. Don't know why you would read more into it than that :)

From: Jacques Groshomme
Benefits of expanding the message length far outweigh the potential (and unlikely) pitfalls.

While I completely disagree with your use of the word "unlikely", I agree that it has tremendous benefits, and am glad that it was implemented, I just wish that it was more robust.
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-29-2006 13:08
From: Ralph Doctorow
But as the OP said, the only way to guard against this is to be sure you always have well over 1K memory free whenever a listen is active. There's no way in LSL to limit the amount of data gotten by a listen.

Having said that though, letting a script get that close to the edge is pretty dangerous IMHO. It's all too easy to make a copy of something like a string or array and have it blow up all by itself.


Actually it isn't the only way to guard against it. It is extremely rare I have a completely open listen, no matter what channel I use. If you have it set to only listen to the owner or the person's key that touched it etc, then you are protected. I also keep the listens tight when I am listening to another one of my objects, by specifying the name of the object to listen to.

So I also don't think this is going to be a big deal.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Ralph Doctorow
Registered User
Join date: 16 Oct 2005
Posts: 560
11-29-2006 13:13
Jesse - good point. Actually I do that too, so I think you're correct that for most cases it shouldn't be too big a deal.
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-29-2006 13:17
I forgot to also mention the other built in protection: timer events.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
RobbyRacoon Olmstead
Red warrior is hungry!
Join date: 20 Sep 2006
Posts: 1,821
11-29-2006 13:22
From: Jesse Barnett
I forgot to also mention the other built in protection: timer events.


Protection in what sense, exactly? Do you just mean only having an open listen for a short period of time?
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-29-2006 13:37
From: RobbyRacoon Olmstead
Protection in what sense, exactly? Do you just mean only having an open listen for a short period of time?

Yes let's look at this. I want to crash some scripts for fun. I will deploy 10,000 objects with scripts after figuring out how to get around the grey goo fence. Each object will find a script to sit beside and hope that:

A) Who to listen to is not specified

B) What to listen to is not specified

C)Someone hasn't already figured out something is going on because I am having to continually spout out long messages waiting for the listen event to be fired and I also hopefully have enough time for it to recieve my message.

It is possible for someone to be determined enough to crash a script, maybe even two? Anything is possible. But is it going to be more then a tiny, remote threat? No.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Tyken Hightower
Automagical
Join date: 15 Feb 2006
Posts: 472
11-29-2006 13:49
If you have any script that plans on dealing with text input and doesn't have over 1k free memory, you're doing something wrong to begin with.

However, this gets far, far, worse:

CODE

default
{
state_entry()
{
llListen(0, "", "", "");
llOwnerSay((string)llGetFreeMemory() + " bytes free.");
}

listen(integer channel, string name, key id, string msg)
{
llOwnerSay((string)llGetFreeMemory() + "bytes free.");
list temp = llParseString2List(msg, [" "], []);
llOwnerSay((string)llGetFreeMemory() + "bytes free.");
}
}


Result:
CODE

[13:44] Object: Hello, Avatar!
[13:46] Object: 15918 bytes free.
[13:48] You: a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
[13:48] Object: 14803bytes free.
[13:48] Object: 8136bytes free.


Me nooooo likey. :(

EDIT: I have to recode one of my products that was broken by this (although the likelyhood of anyone but a griefer making that pattern of input is pretty miniscule).
_____________________
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
11-29-2006 15:00
I had a function a long time ago that stripped off leading whitespace that basicly did
CODE
list messageBits = llParseString2List(message,[" "],[]); 

It would crash exactly as you mentioned. In this case it wasn't the length of the strings that mattered, but how many spaces. Lists with many elements have huge overheads.

Everything in LSL is pass by value; there is no way to work with a variable without copying it into the stack. If there isn't enough space for that copy operation it, then it will crash the script.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
DoteDote Edison
Thinks Too Much
Join date: 6 Jun 2004
Posts: 790
11-29-2006 17:47
Another possible solution/idea... Use a dedicated listen script(s). For a single listen, one script simply listens, filters down to the max length needed, and passes data to another script for processing. For the poker example, use one script per listen.
CODE

default {
link_message(integer sender, integer channel, string command, key id) {
if (command == "assign_channel") {
handle = llListen(channel, "", id, "");
}
else if (command == "clear_channel") llListenRemove(handle);
}
listen(integer channel, string name, key id, string msg) {
msg = llGetSubString(msg, 0, 255);
llMessageLinked(LINK_ROOT, channel, id, msg);
}
}
Jopsy Pendragon
Perpetual Outsider
Join date: 15 Jan 2004
Posts: 1,906
11-29-2006 18:36
Jopsy Pendragon says: "!quit using open listens on channel zero in populated areas because they have to process every single line of text uttered and can add enough processing to the sim to cause just that much more lag when many people are present, which can be really annoying, know what I mean? Anyway, maybe this is less of a problem and more of a blessing in disgui<thunk><thunk><thunk>...
1 2