Bug 1211952 - nautilus dumps core in gtk_widget_get_sensitive() after bad password input
Summary: nautilus dumps core in gtk_widget_get_sensitive() after bad password input
Status: RESOLVED FIXED
Alias: None
Product: openSUSE Distribution
Classification: openSUSE
Component: GNOME (show other bugs)
Version: Leap 15.4
Hardware: Other Other
: P5 - None : Normal (vote)
Target Milestone: ---
Assignee: Martin Wilck
QA Contact: E-mail List
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-06-02 10:25 UTC by Martin Wilck
Modified: 2024-06-26 21:00 UTC (History)
2 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments
proposed patch (2.84 KB, patch)
2023-06-02 13:31 UTC, Martin Wilck
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Wilck 2023-06-02 10:25:51 UTC
nautilus crashes reproducably after trying to access an SMB share. 

steps to reproduce: ask nautilus to access SMB share. Click "Connect As → Registered User", enter wrong password, click "Connect". The crash happens when nautilus tries to display the login prompt again.

(gdb) bt
#0  0x00007fe31dc37a3d in gtk_widget_set_sensitive (widget=0x55696558a720, sensitive=0) at gtkwidget.c:9515
#1  0x00007fe31db05ba6 in pw_dialog_anonymous_toggled (widget=<optimized out>, operation=<optimized out>) at gtkmountoperation.c:474
#2  0x00007fe31c55f973 in g_closure_invoke (closure=0x55696502e830, return_value=0x0, n_param_values=1, param_values=0x7ffd0585dd20, invocation_hint=0x7ffd0585dca0) at ../gobject/gclosure.c:830
#3  0x00007fe31c573a7e in signal_emit_unlocked_R (node=node@entry=0x556964c0c170, detail=detail@entry=0, instance=instance@entry=0x55696524fe00, emission_return=emission_return@entry=0x0, 
    instance_and_params=instance_and_params@entry=0x7ffd0585dd20) at ../gobject/gsignal.c:3742
#4  0x00007fe31c57d684 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7ffd0585def0) at ../gobject/gsignal.c:3497
#5  0x00007fe31c57e11f in g_signal_emit (instance=<optimized out>, signal_id=<optimized out>, detail=detail@entry=0) at ../gobject/gsignal.c:3553
#6  0x00007fe31dbd5f6d in gtk_toggle_button_toggled (toggle_button=<optimized out>) at gtktogglebutton.c:527
#7  0x00007fe31db05fd1 in gtk_mount_operation_ask_password_do_gtk (default_domain=0x5569654ce990 "WILCKS", default_user=<optimized out>, message=0x55696524fc00 "", operation=0x556964a639f0) at gtkmountoperation.c:793
#8  gtk_mount_operation_ask_password (mount_op=0x556964a639f0, message=message@entry=0x556964d6c2c0 "Authentication Required\nEnter user and password for share “wilck” on “nashorn.local”:", 
    default_user=default_user@entry=0x556964cfd740 "martin", default_domain=default_domain@entry=0x5569654ce990 "WILCKS", flags=<optimized out>) at gtkmountoperation.c:900
#9  0x00007fe31c6360b8 in _g_cclosure_marshal_VOID__STRING_STRING_STRING_FLAGSv (closure=0x5569653f59f0, return_value=<optimized out>, instance=<optimized out>, args=<optimized out>, marshal_data=<optimized out>, 
    n_params=<optimized out>, param_types=0x556965007460) at ../gio/gmarshal-internal.c:2254
#10 0x00007fe31c55fb8c in _g_closure_invoke_va (closure=0x5569653f59f0, return_value=0x0, instance=0x556964a639f0, args=0x7ffd0585e458, n_params=4, param_types=0x556965007460) at ../gobject/gclosure.c:893
#11 0x00007fe31c57dbb1 in g_signal_emit_valist (instance=instance@entry=0x556964a639f0, signal_id=signal_id@entry=563, detail=detail@entry=0, var_args=var_args@entry=0x7ffd0585e458) at ../gobject/gsignal.c:3406
#12 0x00007fe31c57e5da in g_signal_emit_by_name (instance=<optimized out>, detailed_signal=detailed_signal@entry=0x7fe31279a71c "ask_password") at ../gobject/gsignal.c:3594
#13 0x00007fe312792b7d in handle_ask_password (object=<optimized out>, invocation=<optimized out>, 
    arg_message_string=0x556965660ce0 "Authentication Required\nEnter user and password for share “wilck” on “nashorn.local”:", arg_default_user=0x55696535e310 "martin", 
    arg_default_domain=0x55696505b820 "WILCKS", arg_flags_as_int=31, data=0x556964d757f0) at ../common/gmountoperationdbus.c:112
#14 0x00007fe3172956dd in ffi_call_unix64 () at ../src/x86/unix64.S:101
#15 0x00007fe317294bdf in ffi_call_int (cif=cif@entry=0x7ffd0585e810, fn=fn@entry=0x7fe312792b20 <handle_ask_password>, rvalue=<optimized out>, avalue=avalue@entry=0x7ffd0585e6e0, closure=closure@entry=0x0)
    at ../src/x86/ffi64.c:662
#16 0x00007fe31729521d in ffi_call (cif=cif@entry=0x7ffd0585e810, fn=fn@entry=0x7fe312792b20 <handle_ask_password>, rvalue=<optimized out>, avalue=avalue@entry=0x7ffd0585e6e0) at ../src/x86/ffi64.c:674
--Type <RET> for more, q to quit, c to continue without paging--c
#17 0x00007fe31c5601f4 in g_cclosure_marshal_generic (closure=<optimized out>, return_gvalue=<optimized out>, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=<optimized out>) at ../gobject/gclosure.c:1534
#18 0x00007fe31c55f973 in g_closure_invoke (closure=0x55696537dd90, return_value=0x7ffd0585e9e0, n_param_values=6, param_values=0x5569653b0400, invocation_hint=0x7ffd0585e9c0) at ../gobject/gclosure.c:830
#19 0x00007fe31c573a7e in signal_emit_unlocked_R (node=node@entry=0x55696537e9b0, detail=detail@entry=0, instance=instance@entry=0x5569652b5550, emission_return=emission_return@entry=0x7ffd0585eb20, instance_and_params=instance_and_params@entry=0x5569653b0400) at ../gobject/gsignal.c:3742
#20 0x00007fe31c57cae2 in g_signal_emitv (instance_and_params=instance_and_params@entry=0x5569653b0400, signal_id=signal_id@entry=573, detail=detail@entry=0, return_value=return_value@entry=0x7ffd0585eb20) at ../gobject/gsignal.c:3227
#21 0x00007fe31278aa49 in _gvfs_dbus_mount_operation_skeleton_handle_method_call (connection=<optimized out>, sender=<optimized out>, object_path=<optimized out>, interface_name=0x5569654f5ff0 "org.gtk.vfs.MountOperation", method_name=0x556965453210 "AskPassword", parameters=<optimized out>, invocation=0x556964b57b50, user_data=0x5569652b5550) at common/gvfsdbus.c:8133
#22 0x00007fe31c6d55b7 in g_dbus_interface_method_dispatch_helper (interface=<optimized out>, method_call_func=0x7fe31278a890 <_gvfs_dbus_mount_operation_skeleton_handle_method_call>, invocation=0x556964b57b50) at ../gio/gdbusinterfaceskeleton.c:613
#23 0x00007fe31c6bc2fa in call_in_idle_cb (user_data=user_data@entry=0x556964b57b50) at ../gio/gdbusconnection.c:5010
#24 0x00007fe31e3184d7 in g_idle_dispatch (source=0x556964d6dfc0, callback=0x7fe31c6bc0e0 <call_in_idle_cb>, user_data=0x556964b57b50) at ../glib/gmain.c:5897
#25 0x00007fe31e31c82b in g_main_dispatch (context=0x556964a62920) at ../glib/gmain.c:3381
#26 g_main_context_dispatch (context=context@entry=0x556964a62920) at ../glib/gmain.c:4099
#27 0x00007fe31e31cbd0 in g_main_context_iterate (context=context@entry=0x556964a62920, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4175
#28 0x00007fe31e31cc5c in g_main_context_iteration (context=context@entry=0x556964a62920, may_block=may_block@entry=1) at ../glib/gmain.c:4240
#29 0x00007fe31c69110d in g_application_run (application=0x556964a50210, argc=<optimized out>, argv=<optimized out>) at ../gio/gapplication.c:2569
#30 0x000055696373e1d7 in ?? ()
#31 0x00007fe31b85824d in __libc_start_main () from /lib64/libc.so.6
#32 0x000055696373e22a in ?? ()


(gdb) disas /s
Dump of assembler code for function gtk_widget_set_sensitive:
gtkwidget.c:
9512	{
   0x00007fe31dc37a10 <+0>:	push   %rbp
   0x00007fe31dc37a11 <+1>:	push   %rbx
   0x00007fe31dc37a12 <+2>:	mov    %rdi,%rbx
   0x00007fe31dc37a15 <+5>:	mov    %esi,%ebp
   0x00007fe31dc37a17 <+7>:	sub    $0x28,%rsp
   0x00007fe31dc37a1b <+11>:	mov    %fs:0x28,%rax
   0x00007fe31dc37a24 <+20>:	mov    %rax,0x18(%rsp)
   0x00007fe31dc37a29 <+25>:	xor    %eax,%eax

9513	  GtkWidgetPrivate *priv;
9514	
9515	  g_return_if_fail (GTK_IS_WIDGET (widget));
   0x00007fe31dc37a2b <+27>:	call   0x7fe31dc25f10 <gtk_widget_get_type>
   0x00007fe31dc37a30 <+32>:	test   %rbx,%rbx
   0x00007fe31dc37a33 <+35>:	je     0x7fe31dc37a51 <gtk_widget_set_sensitive+65>
   0x00007fe31dc37a35 <+37>:	mov    (%rbx),%rdx
   0x00007fe31dc37a38 <+40>:	test   %rdx,%rdx
   0x00007fe31dc37a3b <+43>:	je     0x7fe31dc37a42 <gtk_widget_set_sensitive+50>
=> 0x00007fe31dc37a3d <+45>:	cmp    %rax,(%rdx)


(gdb) info reg
rax            0x556964a4d400      93911148450816
rbx            0x55696558a720      93911160235808
rcx            0x0                 0
rdx            0xaaaaaaaaaaaaaaaa  -6148914691236517206
rsi            0x0                 0
rdi            0x55696558a720      93911160235808
rbp            0x0                 0x0
rsp            0x7ffd0585db00      0x7ffd0585db00
r8             0x7fe31dad5100      140613432201472
r9             0x556964badae0      93911149894368
r10            0x0                 0
r11            0xc                 12
r12            0x1                 1
r13            0x7ffd0585dd20      140724696112416
r14            0x7ffd0585dca0      140724696112288
r15            0x7fe31c561b90      140613409708944


%rdx has a bogus value. It is fetched from %rbx, which is the return value of gtk_widget_get_type().


Called from this code:

457	static void
458	pw_dialog_anonymous_toggled (GtkWidget         *widget,
459	                             GtkMountOperation *operation)
460	{
461	  GtkMountOperationPrivate *priv = operation->priv;
462	  gboolean is_valid;
463	  GList *l;
464	
(gdb) 
465	  priv->anonymous = widget == priv->anonymous_toggle;
466	
467	  if (priv->anonymous)
468	    is_valid = TRUE;
469	  else
470	    is_valid = pw_dialog_input_is_valid (operation);
471	
472	  for (l = priv->user_widgets; l != NULL; l = l->next)
473	    {
474	      gtk_widget_set_sensitive (GTK_WIDGET (l->data), !priv->anonymous);
(gdb) 
475	    }

It
When the bug occurs, we're in the middle of the priv->user_widgets list, with l pointing the 8th member of 14. This element seems to be the only one with an invalid data pointer.

(gdb) p *((GtkWidget*) priv->user_widgets->next->next->next->next->next->next->data)
$33 = {parent_instance = {g_type_instance = {g_class = 0x556964e23340}, ref_count = 1, qdata = 0x0}, priv = 0x5569656899a0}
(gdb) p *((GtkWidget*) priv->user_widgets->next->next->next->next->next->next->next->data)
$31 = {parent_instance = {g_type_instance = {g_class = 0xaaaaaaaaaaaaaaaa}, ref_count = 2863311530, 
    qdata = 0xaaaaaaaaaaaaaaaa}, priv = 0xaaaaaaaaaaaaaaaa}
(gdb) p *((GtkWidget*) priv->user_widgets->next->next->next->next->next->next->next->next->data)
$32 = {parent_instance = {g_type_instance = {g_class = 0x556964ea7400}, ref_count = 1, qdata = 0x55696555ae90}, 


The problem seems to be that the 2nd time gtk_mount_operation_ask_password_do_gtk() is called, operation->priv->user_widgets is not empty, but the "data" fields of all widgets have been overwritten with 0xaaaaaaaaaaaaaaaa.

table_add_entry() then prepends new widgets to the user_widgets list.

gtk_mount_operation_ask_password_do_gtk
   table_add_entry
       operation->priv->user_widgets = g_list_prepend (operation->priv->user_widgets, entry);
      
When the list is later traversed in pw_dialog_anonymous_toggled(), the invalid previous first element with data == 0xaaaaaaaaaaaaaaaa will be encountered, causing the crash.
Comment 1 Martin Wilck 2023-06-02 10:43:05 UTC
The pattern 0xaaaaaaaaaaaaaaaa is written when a widget is destroyed. So this is a use-after-free: the list operation->priv->user_widgets is not cleared, but it the elements point to already-freed widgets.
Comment 2 Martin Wilck 2023-06-02 13:31:14 UTC
Created attachment 867371 [details]
proposed patch

The code that I change here is ancient. No idea why this is hitting me now.
Comment 3 Martin Wilck 2023-06-02 14:10:31 UTC
Jiang, please have a look. The patch from comment 2 fixes the issue for me.
Comment 4 Martin Wilck 2023-06-02 14:17:05 UTC
I've created a branch with the fix in 
https://build.suse.de/package/show/home:mwilck:branches:SUSE:SLE-15-SP4:Update/gtk3
Comment 5 Martin Wilck 2023-06-02 14:25:38 UTC
Upstream merge request:

https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6049
Comment 6 Martin Wilck 2023-06-02 15:49:16 UTC
The upstream MR has been merged.
Comment 7 Martin Wilck 2023-06-02 15:53:22 UTC
The problem has already been fixed (with basically the same patch) in GTK 4.7.2:

https://gitlab.gnome.org/GNOME/gtk/-/commit/111929593aa995c3286b84ad118280357cfe6bdd
Comment 8 Yifan Jiang 2023-06-05 03:04:06 UTC
(In reply to Martin Wilck from comment #3)
> Jiang, please have a look. The patch from comment 2 fixes the issue for me.

Hello Martin,

Thanks! This looks a pretty safe fix to me. Could you please submit it to GNOME:STABLE:41 on OBS, which is our devel branch for 15SP4:Update. I will review, accept and forward it to 15SP4:Update.
Comment 9 Martin Wilck 2023-06-05 10:36:16 UTC
sr#1090886
Comment 11 Martin Wilck 2023-07-05 16:41:12 UTC
https://smelt.suse.de/incident/29346/