** Description changed:
+ [ Impact ]
+
+ The Files app (nautilus) crashes when trying to open a bookmark from the
+ context menu in the Ubuntu Desktop dock.
+
+ [ Test Plan ]
+
+ 1. Open Files
+ 2. Right click on the Files icon in the dock
+ 3. Select a bookmarked location, such as "Documents"
+ 4. Verify that the Files app did not crash
+ 5. Verify that a Files window was opened in the Documents location
+ 6. Repeat 10 times from step 2 (the invalid memory usage may not always
trigger a crash)
+
+ [ Where problems could occur ]
+
+ Problems could manifest in the Files app, default file manager and file
picker dialog provider in Ubuntu Desktop.
+ The patch is removing a single call to decrease the ref-count of an object in
memory; in the worst case this would cause a memory leak.
+
+ [ Original report, dismissed as a security issue ]
+
This is a security issue in Ubuntu downstream Nautilus integration
(unity_launcher_support.patch), specifically src/unity-bookmarks-
handler.c in activate_bookmark_by_quicklist().
The function obtains a GFile* via
nautilus_bookmark_get_location(bookmark) and later calls
g_object_unref(location). Under current semantics this pointer is non-
owning, so unref is invalid and can cause premature free. Reopening the
same bookmark from quicklist later triggers invalid object use and
crash.
Ubuntu version: 26.04 LTS
Kernel version: 7.0.0-22-generic
Nautilus version: 1:50.0-0ubuntu2
Affected version confirmed: nautilus 1:50.0-0ubuntu2
Type: Use-After-Free
Impact: Local DoS (Nautilus crash) While this is a local denial of service,
it can be triggered repeatedly by any local user without authentication,
causing loss of work and disruption to the desktop session.
Reproducer:
Open Nautilus
Right-click dock icon
Open bookmarked folder from quicklist
Close window
Repeat same quicklist open
Crash occurs
Crash signature:
GLib-GObject-CRITICAL: g_object_ref: assertion 'G_IS_OBJECT (object)' failed,
followed by SIGTRAP in GLib abort path.
Root cause:
activate_bookmark_by_quicklist() does:
location = nautilus_bookmark_get_location(bookmark);
g_application_open(... location ...)
g_object_unref(location) <-- invalid for current non-owning semantics
The function nautilus_bookmark_get_location() historically may have returned
a GFile* with full ownership (transfer-full), but in the current version it
returns a non-owning reference (transfer-none). The code still assumes the old
semantics and calls g_object_unref(), causing premature free.
Backtrace key frames:
g_object_ref
begin_location_change
nautilus_application_open_location_full
source code:
static void
activate_bookmark_by_quicklist (DbusmenuMenuitem *menu,
- guint timestamp,
- NautilusBookmark *bookmark)
+ guint timestamp,
+ NautilusBookmark *bookmark)
{
- GFile *location;
- NautilusApplication *application;
+ GFile *location;
+ NautilusApplication *application;
- g_return_if_fail (NAUTILUS_IS_BOOKMARK (bookmark));
+ g_return_if_fail (NAUTILUS_IS_BOOKMARK (bookmark));
- location = nautilus_bookmark_get_location (bookmark);
+ location = nautilus_bookmark_get_location (bookmark);
- application = NAUTILUS_APPLICATION (g_application_get_default ());
+ application = NAUTILUS_APPLICATION (g_application_get_default ());
- g_application_open (G_APPLICATION (application),
- (GFile* []) { location, NULL }, 1, "new-window");
+ g_application_open (G_APPLICATION (application),
+ (GFile* []) { location, NULL }, 1, "new-window");
- g_object_unref (location); // UAF is here!
+ g_object_unref (location); // UAF is here!
}
-
GDB(pwndbg) message:
(org.gnome.Nautilus:150660): GLib-GObject-CRITICAL **: 16:54:18.360:
g_object_ref: assertion 'G_IS_OBJECT (object)' failed
Thread 1 "nautilus" received signal SIGTRAP, Trace/breakpoint trap.
_g_log_abort (breakpoint=breakpoint@entry=0x1) at
../../../glib/gmessages.c:452
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
LAST SIGNAL
]────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Breakpoint hit at 0x7ffff7c625e9
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
REGISTERS / show-flags off / show-compact-regs off
]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
- RAX 0xfffffffffffffcd0
- RBX 1
- RCX 0x51d1
- RDX 0x7ffff5412ac8 (main_arena+8) —▸ 0x55555eb05d70 ◂— 0xa0
- RDI 0x7ffff5412ac0 (main_arena) ◂— 0
- RSI 0x5810
- R8 1
- R9 0xa37d68d7b79bde6c
- R10 0
- R11 0x297
- R12 0x7ffff7c62d90 (g_log_default_handler) ◂— endbr64
- R13 3
- R14 0xa
- R15 8
- RBP 0x7fffffffc940 —▸ 0x7fffffffca10 —▸ 0x7fffffffcaf0 —▸ 0x7fffffffcb30 —▸
0x7fffffffcb80 ◂— ...
- RSP 0x7fffffffc900 ◂— 0x62f
- RIP 0x7ffff7c625e9 (_g_log_abort+89) ◂— mov rax, qword ptr [rbp - 0x18]
+ RAX 0xfffffffffffffcd0
+ RBX 1
+ RCX 0x51d1
+ RDX 0x7ffff5412ac8 (main_arena+8) —▸ 0x55555eb05d70 ◂— 0xa0
+ RDI 0x7ffff5412ac0 (main_arena) ◂— 0
+ RSI 0x5810
+ R8 1
+ R9 0xa37d68d7b79bde6c
+ R10 0
+ R11 0x297
+ R12 0x7ffff7c62d90 (g_log_default_handler) ◂— endbr64
+ R13 3
+ R14 0xa
+ R15 8
+ RBP 0x7fffffffc940 —▸ 0x7fffffffca10 —▸ 0x7fffffffcaf0 —▸ 0x7fffffffcb30 —▸
0x7fffffffcb80 ◂— ...
+ RSP 0x7fffffffc900 ◂— 0x62f
+ RIP 0x7ffff7c625e9 (_g_log_abort+89) ◂— mov rax, qword ptr [rbp - 0x18]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
DISASM / x86-64 / set emulate on
]──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
- ► 0x7ffff7c625e9 <_g_log_abort+89> mov rax, qword ptr [rbp - 0x18]
RAX, [0x7fffffffc928] => 0x236f31748ebed500
- 0x7ffff7c625ed <_g_log_abort+93> sub rax, qword ptr fs:[0x28]
RAX => 0 (0x236f31748ebed500 - 0x236f31748ebed500)
- 0x7ffff7c625f6 <_g_log_abort+102> ✘ jne _g_log_abort+182
<_g_log_abort+182>
-
- 0x7ffff7c625f8 <_g_log_abort+104> mov rbx, qword ptr [rbp - 8]
RBX, [0x7fffffffc938] => 0x7ffff7d9b015 ◂— 'GLib-GObject'
- 0x7ffff7c625fc <_g_log_abort+108> leave
- 0x7ffff7c625fd <_g_log_abort+109> ret
<g_logv+802>
- ↓
- 0x7ffff7c63212 <g_logv+802> jmp g_logv+612
<g_logv+612>
- ↓
- 0x7ffff7c63154 <g_logv+612> mov esi, dword ptr [rbp - 0x88]
ESI, [0x7fffffffc988] => 0
- 0x7ffff7c6315a <g_logv+618> lea rdi, [rip + 0xefbbf]
RDI => 0x7ffff7d52d20 (g_log_depth) ◂— 0xffffffff0000000c /* '\x0c' */
- 0x7ffff7c63161 <g_logv+625> call g_private_set
<g_private_set>
-
- 0x7ffff7c63166 <g_logv+630> test r13d, r13d
+ ► 0x7ffff7c625e9 <_g_log_abort+89> mov rax, qword ptr [rbp - 0x18]
RAX, [0x7fffffffc928] => 0x236f31748ebed500
+ 0x7ffff7c625ed <_g_log_abort+93> sub rax, qword ptr fs:[0x28]
RAX => 0 (0x236f31748ebed500 - 0x236f31748ebed500)
+ 0x7ffff7c625f6 <_g_log_abort+102> ✘ jne _g_log_abort+182
<_g_log_abort+182>
+
+ 0x7ffff7c625f8 <_g_log_abort+104> mov rbx, qword ptr [rbp - 8]
RBX, [0x7fffffffc938] => 0x7ffff7d9b015 ◂— 'GLib-GObject'
+ 0x7ffff7c625fc <_g_log_abort+108> leave
+ 0x7ffff7c625fd <_g_log_abort+109> ret
<g_logv+802>
+ ↓
+ 0x7ffff7c63212 <g_logv+802> jmp g_logv+612
<g_logv+612>
+ ↓
+ 0x7ffff7c63154 <g_logv+612> mov esi, dword ptr [rbp - 0x88]
ESI, [0x7fffffffc988] => 0
+ 0x7ffff7c6315a <g_logv+618> lea rdi, [rip + 0xefbbf]
RDI => 0x7ffff7d52d20 (g_log_depth) ◂— 0xffffffff0000000c /* '\x0c' */
+ 0x7ffff7c63161 <g_logv+625> call g_private_set
<g_private_set>
+
+ 0x7ffff7c63166 <g_logv+630> test r13d, r13d
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
STACK
]───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffc900 ◂— 0x62f
01:0008│-038 0x7fffffffc908 —▸ 0x55555db7e930 —▸ 0x7ffff5412ac8
(main_arena+8) —▸ 0x55555eb05d70 ◂— 0xa0
02:0010│-030 0x7fffffffc910 —▸ 0x7ffff7d2842d ◂— 'SYSLOG_IDENTIFIER'
03:0018│-028 0x7fffffffc918 {len} ◂— 0x62f
04:0020│-020 0x7fffffffc920 {proc_status} —▸ 0x55555db7e930 —▸ 0x7ffff5412ac8
(main_arena+8) —▸ 0x55555eb05d70 ◂— 0xa0
05:0028│-018 0x7fffffffc928 ◂— 0x236f31748ebed500
06:0030│-010 0x7fffffffc930 —▸ 0x7ffff7d9b015 ◂— 'GLib-GObject'
07:0038│-008 0x7fffffffc938 —▸ 0x7ffff7d9b015 ◂— 'GLib-GObject'
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
BACKTRACE
]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
- ► 0 0x7ffff7c625e9 _g_log_abort+89
- 1 0x7ffff7c63212 g_logv+802
- 2 0x7ffff7c634d3 g_log+147
- 3 0x7ffff7c644fd None
- 4 0x7ffff7d7732a g_object_ref+138
- 5 0x7ffff7d7732a g_object_ref+138
- 6 0x5555555eaaa3 begin_location_change+115
- 7 0x555555592769 nautilus_application_open_location_full+329
+ ► 0 0x7ffff7c625e9 _g_log_abort+89
+ 1 0x7ffff7c63212 g_logv+802
+ 2 0x7ffff7c634d3 g_log+147
+ 3 0x7ffff7c644fd None
+ 4 0x7ffff7d7732a g_object_ref+138
+ 5 0x7ffff7d7732a g_object_ref+138
+ 6 0x5555555eaaa3 begin_location_change+115
+ 7 0x555555592769 nautilus_application_open_location_full+329
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
THREADS (33 TOTAL)
]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
- ► 1 "nautilus" stopped: 0x7ffff7c625e9 <_g_log_abort+89>
- 70 "pool-45" stopped: 0x7ffff5334d0d <syscall+29>
- 69 "pool-44" stopped: 0x7ffff5334d0d <syscall+29>
- 63 "pool-38" stopped: 0x7ffff5334d0d <syscall+29>
+ ► 1 "nautilus" stopped: 0x7ffff7c625e9 <_g_log_abort+89>
+ 70 "pool-45" stopped: 0x7ffff5334d0d <syscall+29>
+ 69 "pool-44" stopped: 0x7ffff5334d0d <syscall+29>
+ 63 "pool-38" stopped: 0x7ffff5334d0d <syscall+29>
Not showing 29 thread(s). Use set context-max-threads <number of threads> to
change this.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
-
Proposed fix:
Remove g_object_unref(location) for transfer-none getter semantics, or
explicitly g_object_ref() before use and keep balanced unref.
Request: CVE assignment requested.
Reporter: zhangweichao ([email protected])
** Description changed:
[ Impact ]
- The Files app (nautilus) crashes when trying to open a bookmark from the
- context menu in the Ubuntu Desktop dock.
+ The Files app (nautilus) may crash when trying to open a bookmark from
+ the context menu in the Ubuntu Desktop dock.
[ Test Plan ]
1. Open Files
2. Right click on the Files icon in the dock
3. Select a bookmarked location, such as "Documents"
4. Verify that the Files app did not crash
5. Verify that a Files window was opened in the Documents location
6. Repeat 10 times from step 2 (the invalid memory usage may not always
trigger a crash)
[ Where problems could occur ]
Problems could manifest in the Files app, default file manager and file
picker dialog provider in Ubuntu Desktop.
The patch is removing a single call to decrease the ref-count of an object in
memory; in the worst case this would cause a memory leak.
[ Original report, dismissed as a security issue ]
This is a security issue in Ubuntu downstream Nautilus integration
(unity_launcher_support.patch), specifically src/unity-bookmarks-
handler.c in activate_bookmark_by_quicklist().
The function obtains a GFile* via
nautilus_bookmark_get_location(bookmark) and later calls
g_object_unref(location). Under current semantics this pointer is non-
owning, so unref is invalid and can cause premature free. Reopening the
same bookmark from quicklist later triggers invalid object use and
crash.
Ubuntu version: 26.04 LTS
Kernel version: 7.0.0-22-generic
Nautilus version: 1:50.0-0ubuntu2
Affected version confirmed: nautilus 1:50.0-0ubuntu2
Type: Use-After-Free
Impact: Local DoS (Nautilus crash) While this is a local denial of service,
it can be triggered repeatedly by any local user without authentication,
causing loss of work and disruption to the desktop session.
Reproducer:
Open Nautilus
Right-click dock icon
Open bookmarked folder from quicklist
Close window
Repeat same quicklist open
Crash occurs
Crash signature:
GLib-GObject-CRITICAL: g_object_ref: assertion 'G_IS_OBJECT (object)' failed,
followed by SIGTRAP in GLib abort path.
Root cause:
activate_bookmark_by_quicklist() does:
location = nautilus_bookmark_get_location(bookmark);
g_application_open(... location ...)
g_object_unref(location) <-- invalid for current non-owning semantics
The function nautilus_bookmark_get_location() historically may have returned
a GFile* with full ownership (transfer-full), but in the current version it
returns a non-owning reference (transfer-none). The code still assumes the old
semantics and calls g_object_unref(), causing premature free.
Backtrace key frames:
g_object_ref
begin_location_change
nautilus_application_open_location_full
source code:
static void
activate_bookmark_by_quicklist (DbusmenuMenuitem *menu,
guint timestamp,
NautilusBookmark *bookmark)
{
GFile *location;
NautilusApplication *application;
g_return_if_fail (NAUTILUS_IS_BOOKMARK (bookmark));
location = nautilus_bookmark_get_location (bookmark);
application = NAUTILUS_APPLICATION (g_application_get_default ());
g_application_open (G_APPLICATION (application),
(GFile* []) { location, NULL }, 1, "new-window");
g_object_unref (location); // UAF is here!
}
GDB(pwndbg) message:
(org.gnome.Nautilus:150660): GLib-GObject-CRITICAL **: 16:54:18.360:
g_object_ref: assertion 'G_IS_OBJECT (object)' failed
Thread 1 "nautilus" received signal SIGTRAP, Trace/breakpoint trap.
_g_log_abort (breakpoint=breakpoint@entry=0x1) at
../../../glib/gmessages.c:452
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
LAST SIGNAL
]────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Breakpoint hit at 0x7ffff7c625e9
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
REGISTERS / show-flags off / show-compact-regs off
]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
RAX 0xfffffffffffffcd0
RBX 1
RCX 0x51d1
RDX 0x7ffff5412ac8 (main_arena+8) —▸ 0x55555eb05d70 ◂— 0xa0
RDI 0x7ffff5412ac0 (main_arena) ◂— 0
RSI 0x5810
R8 1
R9 0xa37d68d7b79bde6c
R10 0
R11 0x297
R12 0x7ffff7c62d90 (g_log_default_handler) ◂— endbr64
R13 3
R14 0xa
R15 8
RBP 0x7fffffffc940 —▸ 0x7fffffffca10 —▸ 0x7fffffffcaf0 —▸ 0x7fffffffcb30 —▸
0x7fffffffcb80 ◂— ...
RSP 0x7fffffffc900 ◂— 0x62f
RIP 0x7ffff7c625e9 (_g_log_abort+89) ◂— mov rax, qword ptr [rbp - 0x18]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
DISASM / x86-64 / set emulate on
]──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
► 0x7ffff7c625e9 <_g_log_abort+89> mov rax, qword ptr [rbp - 0x18]
RAX, [0x7fffffffc928] => 0x236f31748ebed500
0x7ffff7c625ed <_g_log_abort+93> sub rax, qword ptr fs:[0x28]
RAX => 0 (0x236f31748ebed500 - 0x236f31748ebed500)
0x7ffff7c625f6 <_g_log_abort+102> ✘ jne _g_log_abort+182
<_g_log_abort+182>
0x7ffff7c625f8 <_g_log_abort+104> mov rbx, qword ptr [rbp - 8]
RBX, [0x7fffffffc938] => 0x7ffff7d9b015 ◂— 'GLib-GObject'
0x7ffff7c625fc <_g_log_abort+108> leave
0x7ffff7c625fd <_g_log_abort+109> ret
<g_logv+802>
↓
0x7ffff7c63212 <g_logv+802> jmp g_logv+612
<g_logv+612>
↓
0x7ffff7c63154 <g_logv+612> mov esi, dword ptr [rbp - 0x88]
ESI, [0x7fffffffc988] => 0
0x7ffff7c6315a <g_logv+618> lea rdi, [rip + 0xefbbf]
RDI => 0x7ffff7d52d20 (g_log_depth) ◂— 0xffffffff0000000c /* '\x0c' */
0x7ffff7c63161 <g_logv+625> call g_private_set
<g_private_set>
0x7ffff7c63166 <g_logv+630> test r13d, r13d
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
STACK
]───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffc900 ◂— 0x62f
01:0008│-038 0x7fffffffc908 —▸ 0x55555db7e930 —▸ 0x7ffff5412ac8
(main_arena+8) —▸ 0x55555eb05d70 ◂— 0xa0
02:0010│-030 0x7fffffffc910 —▸ 0x7ffff7d2842d ◂— 'SYSLOG_IDENTIFIER'
03:0018│-028 0x7fffffffc918 {len} ◂— 0x62f
04:0020│-020 0x7fffffffc920 {proc_status} —▸ 0x55555db7e930 —▸ 0x7ffff5412ac8
(main_arena+8) —▸ 0x55555eb05d70 ◂— 0xa0
05:0028│-018 0x7fffffffc928 ◂— 0x236f31748ebed500
06:0030│-010 0x7fffffffc930 —▸ 0x7ffff7d9b015 ◂— 'GLib-GObject'
07:0038│-008 0x7fffffffc938 —▸ 0x7ffff7d9b015 ◂— 'GLib-GObject'
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
BACKTRACE
]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
► 0 0x7ffff7c625e9 _g_log_abort+89
1 0x7ffff7c63212 g_logv+802
2 0x7ffff7c634d3 g_log+147
3 0x7ffff7c644fd None
4 0x7ffff7d7732a g_object_ref+138
5 0x7ffff7d7732a g_object_ref+138
6 0x5555555eaaa3 begin_location_change+115
7 0x555555592769 nautilus_application_open_location_full+329
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[
THREADS (33 TOTAL)
]─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
► 1 "nautilus" stopped: 0x7ffff7c625e9 <_g_log_abort+89>
70 "pool-45" stopped: 0x7ffff5334d0d <syscall+29>
69 "pool-44" stopped: 0x7ffff5334d0d <syscall+29>
63 "pool-38" stopped: 0x7ffff5334d0d <syscall+29>
Not showing 29 thread(s). Use set context-max-threads <number of threads> to
change this.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Proposed fix:
Remove g_object_unref(location) for transfer-none getter semantics, or
explicitly g_object_ref() before use and keep balanced unref.
Request: CVE assignment requested.
Reporter: zhangweichao ([email protected])
--
You received this bug notification because you are a member of Ubuntu
Desktop Bugs, which is subscribed to nautilus in Ubuntu.
https://bugs.launchpad.net/bugs/2156984
Title:
UAF in Nautilus Unity quicklist bookmark handler
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/nautilus/+bug/2156984/+subscriptions
--
desktop-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/desktop-bugs