From: Jinoh Kang jinoh.kang.kr@gmail.com
If a client can crash a wineserver via requests only, it's a bug.
The wineserver crashes when a privileged client deletes every object in the NT object namespace (which frees `root_directory`) and then attempts to lookup or create any object name. --- server/directory.c | 7 ++++++- server/object.c | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/server/directory.c b/server/directory.c index 23d7eb0a2b7..1c57a29ae71 100644 --- a/server/directory.c +++ b/server/directory.c @@ -494,13 +494,18 @@ void init_directories( struct fd *intl_fd ) release_object( named_pipe_device ); release_object( mailslot_device ); release_object( null_device ); - release_object( root_directory ); release_object( dir_driver ); release_object( dir_device ); release_object( dir_objtype ); release_object( dir_kernel ); release_object( dir_nls ); release_object( dir_global ); + + /* + * Leave at least one extra ref (in addition to permanent ref) for + * root_directory. This protects against use-after-free when the client + * makes it temporary and empties it on an unlikely occasion. + */ }
/* create a directory object */ diff --git a/server/object.c b/server/object.c index 89e541ffb6b..11689e6cbb3 100644 --- a/server/object.c +++ b/server/object.c @@ -79,6 +79,8 @@ void dump_objects(void)
void close_objects(void) { + struct object *rootdir = get_root_directory(); + /* release the permanent objects */ for (;;) { @@ -95,6 +97,11 @@ void close_objects(void) if (!found) break; }
+ /* release the initial and final reference */ + assert( rootdir->refcount >= 2 ); + release_object( rootdir ); + release_object( rootdir ); + dump_objects(); /* dump any remaining objects */ }