Hi there,
I just did some preliminary analysis on this.
There are in fact three exploits involved in this.
CVE-2023-6546: https://github.com/Nassim-Asrir/ZDI-24-020/
jmpe4x's GSM exploit:
https://github.com/jmpe4x/GSM_Linux_Kernel_LPE_Nday_Exploit
YuriiCrimson's GSM exploit: https://github.com/YuriiCrimson/ExploitGSM
I tested all of them. All of them targeted the same subsystem (GSM),
used the same KASLR leak method ("/sys/kernel/notes"). But there are
two vulnerabilities involved here.
In short. jmpe4x's and YuriiCrimson's exploits are the same, but the
vulnerability is not CVE-2023-6546.
!!!!!!!!!!!!
It is a 0day that is not patched in the main tree yet.
Not a patch gap.
!!!!!!!!!!!!
My analysis is performed on the latest commit of Linus's tree:
```
commit e8c39d0f57f358950356a8e44ee5159f57f86ec5 (HEAD -> master,
origin/master, origin/HEAD)
Merge: 03a55b63919 325f3fb551f
Author: Linus Torvalds <[email protected]>
Date: Wed Apr 10 19:48:05 2024 -0700
```
And jmpe4x's and YuriiCrimson's are exactly the same. The difference
is mostly spaces. The diff is attached to this email.
Thanks,
Kyle Zeng
On Thu, Apr 11, 2024 at 8:07 AM Dr. Christopher Kunz
<[email protected]> wrote:
>
> Hi,
>
> > There are two exploits in Yurii's repo above, according to Yurii for two
> > different bugs. The above is one of them. Perhaps also try the other?
> The two exploit versions are for different kernels. The 6.5 exploit
> doesn't compile on the Debian 12 6.1 kernel, and no Debian version
> currently distributes a 6.5 kernel, AFAICT. I used
> ExploitGSM_5_15_to_6_1/ExploitGSM and it worked.
> > I don't know, and apparently it'd need to be two CVEs for two bugs that
> > Yurii exploits.
> Possibly. I'm definitely out of my depth trying to analyze which bugs
> are being exploited.
> > CVE-2023-52564: Revert "tty: n_gsm: fix UAF in gsm_cleanup_mux"
> > https://lists.openwall.net/linux-cve-announce/2024/03/02/54
> >
> > Maybe CVE-2023-52564 is one of the bugs Yurii exploits, or maybe not.
> > I didn't look into this closely enough to tell.
>
> Apparently not. Debian 12 "Bookworm" currently runs this kernel:
>
> Linux debianexploitgsm 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian
> 6.1.76-1 (2024-02-01) x86_64 GNU/Linux
>
> According to the changelog, this kernel has the fix for CVE-2023-52564
> included:
> - Revert "tty: n_gsm: fix UAF in gsm_cleanup_mux"
> (from
> https://metadata.ftp-master.debian.org/changelogs//main/l/linux-signed-amd64/linux-signed-amd64_6.1.76+1_changelog)
>
> Still, the exploit works, so it must exploit a different issue.
>
> Just my two cents,
>
> --cku
>
0a1,2
> // GSM Linux Kernel Race Condition -> UAF 0day Exploit written by jmpe4x
>
45a48
> #define PAGE_UP(addr) (((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1)))
47d49
< #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
49,51c51
< #define BIT(name) (1ULL << name)
< #define HEAP_SPRAY_SIZE 1024
< #define BITS_PER_LONG 64
---
> #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
54,60c54,60
< __u32 channel; /* DLCI (0 for the associated DLCI) */
< __u32 adaption; /* Convergence layer type */
< __u32 mtu; /* Maximum transfer unit */
< __u32 priority; /* Priority (0 for default value) */
< __u32 i; /* Frame type (1 = UIH, 2 = UI) */
< __u32 k; /* Window size (0 for default value) */
< __u32 reserved[8]; /* For future use, must be initialized to zero
*/
---
> __u32 channel; /* DLCI (0 for the associated DLCI) */
> __u32 adaption; /* Convergence layer type */
> __u32 mtu; /* Maximum transfer unit */
> __u32 priority; /* Priority (0 for default value) */
> __u32 i; /* Frame type (1 = UIH, 2 = UI) */
> __u32 k; /* Window size (0 for default value) */
> __u32 reserved[8]; /* For future use, must be initialized to zero */
63,64c63,64
< #define GSMIOC_GETCONF_DLCI _IOWR('G', 7, struct gsm_dlci_config)
< #define GSMIOC_SETCONF_DLCI _IOW('G', 8, struct gsm_dlci_config)
---
> #define GSMIOC_GETCONF_DLCI _IOWR('G', 7, struct gsm_dlci_config)
> #define GSMIOC_SETCONF_DLCI _IOW('G', 8, struct gsm_dlci_config)
72c72
< const unsigned char CMD_MSC = 0x71;
---
> const unsigned char CMD_MSC = 0x71;
82a83,91
> const int KERNEL_PATH_READ_OFFSET = 11;
> const int SECTOR_SIZE = 512;
> const int BOOT_ENTRY_OFFSET = SECTOR_SIZE;
> const int BOOT_SECTOR_COUNT = 1;
> const int BOOT_FLAG = 0xAA55;
> const int UNCOMPRESSED_KERNEL_SIZE_OFFSET = 4;
> const int SETUP_HEADER_OFFSET = BOOT_ENTRY_OFFSET - 15;
> const int ASCII_OFFSET = 48;
> const int WQ_FLAG_BOOKMARK = 0x04;
84a94
> #define BIT(name) (1ULL << name)
85a96,97
>
> #define HEAP_SPRAY_SIZE 1024
87a100,101
> #define BITS_PER_LONG 64
>
89,92c103,106
< WORK_STRUCT_PENDING_BIT = 0, /* work item is pending execution */
< WORK_STRUCT_INACTIVE_BIT= 1, /* work item is inactive */
< WORK_STRUCT_PWQ_BIT = 2, /* data points to pwq */
< WORK_STRUCT_LINKED_BIT = 3, /* next work is linked to this one */
---
> WORK_STRUCT_PENDING_BIT = 0, /* work item is pending execution */
> WORK_STRUCT_INACTIVE_BIT= 1, /* work item is inactive */
> WORK_STRUCT_PWQ_BIT = 2, /* data points to pwq */
> WORK_STRUCT_LINKED_BIT = 3, /* next work is linked to this one */
94,95c108,109
< WORK_STRUCT_STATIC_BIT = 4, /* static initializer (debugobjects) */
< WORK_STRUCT_COLOR_SHIFT = 5, /* color for workqueue flushing */
---
> WORK_STRUCT_STATIC_BIT = 4, /* static initializer (debugobjects)
> */
> WORK_STRUCT_COLOR_SHIFT = 5, /* color for workqueue flushing */
97c111
< WORK_STRUCT_COLOR_SHIFT = 4, /* color for workqueue flushing */
---
> WORK_STRUCT_COLOR_SHIFT = 4, /* color for workqueue flushing */
100c114
< WORK_STRUCT_COLOR_BITS = 4,
---
> WORK_STRUCT_COLOR_BITS = 4,
102,105c116,119
< WORK_STRUCT_PENDING = 1 << WORK_STRUCT_PENDING_BIT,
< WORK_STRUCT_INACTIVE = 1 << WORK_STRUCT_INACTIVE_BIT,
< WORK_STRUCT_PWQ = 1 << WORK_STRUCT_PWQ_BIT,
< WORK_STRUCT_LINKED = 1 << WORK_STRUCT_LINKED_BIT,
---
> WORK_STRUCT_PENDING = 1 << WORK_STRUCT_PENDING_BIT,
> WORK_STRUCT_INACTIVE = 1 << WORK_STRUCT_INACTIVE_BIT,
> WORK_STRUCT_PWQ = 1 << WORK_STRUCT_PWQ_BIT,
> WORK_STRUCT_LINKED = 1 << WORK_STRUCT_LINKED_BIT,
107c121
< WORK_STRUCT_STATIC = 1 << WORK_STRUCT_STATIC_BIT,
---
> WORK_STRUCT_STATIC = 1 << WORK_STRUCT_STATIC_BIT,
109c123
< WORK_STRUCT_STATIC = 0,
---
> WORK_STRUCT_STATIC = 0,
112c126
< WORK_NR_COLORS = (1 << WORK_STRUCT_COLOR_BITS),
---
> WORK_NR_COLORS = (1 << WORK_STRUCT_COLOR_BITS),
115c129
< WORK_CPU_UNBOUND = 8192,
---
> WORK_CPU_UNBOUND = 8192,
122c136
< WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT +
---
> WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT +
126c140
< WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT,
---
> WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT,
128c142
< __WORK_OFFQ_CANCELING = WORK_OFFQ_FLAG_BASE,
---
> __WORK_OFFQ_CANCELING = WORK_OFFQ_FLAG_BASE,
135,138c149,152
< WORK_OFFQ_FLAG_BITS = 1,
< WORK_OFFQ_POOL_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS,
< WORK_OFFQ_LEFT = BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT,
< WORK_OFFQ_POOL_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31,
---
> WORK_OFFQ_FLAG_BITS = 1,
> WORK_OFFQ_POOL_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS,
> WORK_OFFQ_LEFT = BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT,
> WORK_OFFQ_POOL_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31,
141,142c155,156
< WORK_BUSY_PENDING = 1 << 0,
< WORK_BUSY_RUNNING = 1 << 1,
---
> WORK_BUSY_PENDING = 1 << 0,
> WORK_BUSY_RUNNING = 1 << 1,
145c159
< WORKER_DESC_LEN = 24,
---
> WORKER_DESC_LEN = 24,
148,149c162,163
< #define WORK_OFFQ_POOL_NONE ((1ul << WORK_OFFQ_POOL_BITS) - 1)
< #define WORK_STRUCT_NO_POOL (WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT)
---
> #define WORK_OFFQ_POOL_NONE ((1ul << WORK_OFFQ_POOL_BITS) - 1)
> #define WORK_STRUCT_NO_POOL (WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT)
154,156c168,170
< #define ULL(x) (_ULL(x))
< #define BIT_ULL(nr) (ULL(1) << (nr))
< #define CAP_VALID_MASK (BIT_ULL(CAP_LAST_CAP+1)-1)
---
> #define ULL(x) (_ULL(x))
> #define BIT_ULL(nr) (ULL(1) << (nr))
> #define CAP_VALID_MASK (BIT_ULL(CAP_LAST_CAP+1)-1)
164,168c178,182
< DLCI_WAITING_CONFIG, /* Waiting for DLCI configuration from user */
< DLCI_CONFIGURE, /* Sending PN (for adaption > 1) */
< DLCI_OPENING, /* Sending SABM not seen UA */
< DLCI_OPEN, /* SABM/UA complete */
< DLCI_CLOSING, /* Sending DISC not seen UA/DM */
---
> DLCI_WAITING_CONFIG, /* Waiting for DLCI configuration from user */
> DLCI_CONFIGURE, /* Sending PN (for adaption > 1) */
> DLCI_OPENING, /* Sending SABM not seen UA */
> DLCI_OPEN, /* SABM/UA complete */
> DLCI_CLOSING, /* Sending DISC not seen UA/DM */
170a185,188
> const char* KALLSYMS_PATH = "/proc/kallsyms";
> const char* KPTR_RESTRICT_PATH = "/proc/sys/kernel/kptr_restrict";
> const char* PERF_EVENT_PARANOID_PATH = "/proc/sys/kernel/perf_event_paranoid";
> const char* CMDLINE_PATH = "/proc/cmdline";
267,281c285,299
< int usage;
< kuid_t uid; /* real UID of the task */
< kgid_t gid; /* real GID of the task */
< kuid_t suid; /* saved UID of the task */
< kgid_t sgid; /* saved GID of the task */
< kuid_t euid; /* effective UID of the task */
< kgid_t egid; /* effective GID of the task */
< kuid_t fsuid; /* UID for VFS ops */
< kgid_t fsgid; /* GID for VFS ops */
< unsigned securebits; /* SUID-less security management */
< kernel_cap_t cap_inheritable; /* caps our children can inherit */
< kernel_cap_t cap_permitted; /* caps we're permitted */
< kernel_cap_t cap_effective; /* caps we can actually use */
< kernel_cap_t cap_bset; /* capability bounding set */
< kernel_cap_t cap_ambient; /* Ambient capability set */
---
> int usage;
> kuid_t uid; /* real UID of the task */
> kgid_t gid; /* real GID of the task */
> kuid_t suid; /* saved UID of the task */
> kgid_t sgid; /* saved GID of the task */
> kuid_t euid; /* effective UID of the task */
> kgid_t egid; /* effective GID of the task */
> kuid_t fsuid; /* UID for VFS ops */
> kgid_t fsgid; /* GID for VFS ops */
> unsigned securebits; /* SUID-less security management */
> kernel_cap_t cap_inheritable; /* caps our children can inherit */
> kernel_cap_t cap_permitted; /* caps we're permitted */
> kernel_cap_t cap_effective; /* caps we can actually use */
> kernel_cap_t cap_bset; /* capability bounding set */
> kernel_cap_t cap_ambient; /* Ambient capability set */
292,293c310,311
< uint8_t num_parents;
< uint8_t new_parent_index;
---
> uint8_t num_parents;
> uint8_t new_parent_index;
307c325
< int32_t phase;
---
> int32_t phase;
310,311c328,329
< struct hlist_node child_node;
< uint64_t clks;
---
> struct hlist_node child_node;
> uint64_t clks;
324,325c342,343
< uint8_t num_parents;
< uint8_t new_parent_index;
---
> uint8_t num_parents;
> uint8_t new_parent_index;
340c358
< int32_t phase;
---
> int32_t phase;
343,344c361,362
< struct hlist_node child_node;
< uint64_t clks;
---
> struct hlist_node child_node;
> uint64_t clks;
376c394
< const int QUANTITY_KERNELS = 2;
---
> const int QUANTITY_KERNELS = 3;
379,381c397,399
< {"ubuntu", "6.5.0-25-generic", false, false, false, true, false, 0x26933c0,
0x3910d00, 0xa22630, 0x1274c0, 0x133eb0, 0x1120a20},
< {"fedora", "6.5.6-300.fc39.x86_64", false, false, false, true, false,
0x2ad7eb0, 0x3cfcc60, 0x9b4a30, 0x13c3d0, 0x148780, 0xfbbe20}
< };
---
> //{"ubuntu", "6.5.0-25-generic", false, false, false, true, false, 0x26933c0,
> 0x3910d00, 0xa22630, 0x1274c0, 0x133eb0, 0x1120a20},
> {"fedora", "6.5.6-300.fc39.x86_64", false, false, false, true, false,
> 0x2ad7eb0, 0x3cfcc60, 0x9b4a30, 0x13c3d0, 0x148780, 0xfbbe20},
> {"ubuntu", "6.5.0-26-generic", false, false, false, true, false, 0x26933c0,
> 0x3910d00, 0xa22630, 0x1274c0, 0x133eb0, 0x1120a20}};
534,535c552,553
< //if (strcmp(iter_kernel->os_name, argv[1]) ||
strcmp(iter_kernel->kernel, kernel_info.release))
< // continue;
---
> if (strcmp(iter_kernel->os_name, argv[1]) ||
> strcmp(iter_kernel->kernel, kernel_info.release))
> continue;