[DGD] copy() or lack thereof in Melville

Stephen Schmidt schmidsj at union.edu
Sun Jan 25 04:26:38 CET 2004


On Sat, 24 Jan 2004, M M wrote:
> We are working with Melville.

Yay :)

I should add that I haven't worked actively on Melville in
about four years (sidetracked by other things) and my memory
of this is not perfect, far from it. M M (real name?) is
entirely correct that Melville was last released back
when the driver was many versions earlier than now, and
that may have something to do with this issue - I'm not
up to date on the driver, so I can't comment on that.

> in /system/auto/security.c - there is a function called copy:
> which is used, according to the header, as a
> non-recursive copy function for mappings, arrays and
> other variables represented by pointers.

Right. This is to prevent you from changing the original
pointer to point somewhere else, for security reasons.

> It also
> states, that if the variable itself contains pointers,
> that they are _not_ copied.

Right again. It ought to do that, but does not, because
the Melville system code doesn't contain mappings of
mappings or other recursive structures (at least not
in security-related situations, at least not that I
am aware of). It's not terribly hard to add it if you
need it (and add-it-if-you-need-it is a key plank of
the Melville design philosophy).

> value for query_this_player() -> return
> copy(this_player)

If this didn't invoke copy, then the pointer to this_player
could be changed on being returned. If it was changed to point
to an admin player, this could result in security problems.

> in /inherit/room.c we see it:
>     mapping query_exits() { return copy(exits); }

This prevents the calling object from changing the exits in
its returned value and having the value of exits in the room
itself change. This one is probably not necessary, as it's
hard to see how any serious breach of security could arise
from such a change. (Unless I had thought of something when
I coded it in [gulp] 1994 that I've since forgotten.)

> ----------------------
> in /system/users_d.c:
> object find_user(string name) {
>     if (!users) users = ([ ]) ;
>     if (member_array(name,map_indices(users))==-1)
>         return 0 ;
>     return users[name] ;
> }
> which returns the user obj which is paired with name.

This one probably needs to have it added. It would probably
be Bad if the calling object could cause users["Ahab"] to
point to someone else's user object. I can't think of a
specific way to exploit this offhand but I would bet one
exists.

> in /inherit/object.c:
> string *query_id() { return id ; }
> which returns an array of id names.

This one is less critical. Changing an object's ID is a
Wrong Thing but I don't see intrinsically how it could
lead to a security problem. Nothing in security is linked
to an object's id strings. This is especially true if
there is an unsecured set_id() function in object anyway.
No need to protect ids against indirect changes when direct
changes are legal in all cases. If you secure set_id() in
some way (possibly by not having it at all - I don't recall
if Melville does or not) then you might want to close
this down as well.

> So my question is, is the copy() function needed?

Unless DGD handles pointers differently than it did in
1994, yes, it is. It is necessary to protect the
system's references to this_player and this_user, if
nothing else.

> And if it's not
> redundant, then shouldn't everything that returns a
> mapping/array need it?

You could make that argument. I didn't put it everywhere
because copying takes up some CPU and I didn't wish to
spend the CPU unnecessarily. (Computers were slower in
1994 than they are now.) In general, it is used whenever
changing the pointer in the calling object could cause
a security issue in the object providing the pointer.
Elsewhere it's not used.

Steve/Mobydick


_________________________________________________________________
List config page:  http://list.imaginary.com/mailman/listinfo/dgd



More information about the DGD mailing list