The following article is an guest blog post from an external researcher (i.e. cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 author is not a Project Zero or Google researcher).
This post is about a Chrome OS exploit I reported to Chrome VRP in September. The Project Zero folks were nice to let me do a guest post about it, so here goes. The report includes a detailed writeup, so this post will have less detail.
1 byte overflow in a DNS library
In April I found a TCP port listening on localhost in Chrome OS. It was an HTTP proxy built into shill, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome OS network manager. The proxy has now been removed as part of a fix, but its source can still be seen from an old revision: shill/http_proxy.cc. The code is simple and doesn’t seem to contain any obvious exploitable bugs, although it is very liberal in what it accepts as incoming HTTP. It calls into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 c-ares library for resolving DNS. There was a possible one byte overflow in c-ares while building cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DNS packet. Here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerable code, stripped heavily from its original to make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug more visible:
It parses dot-separated labels and writes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m into a buffer allocated by malloc(). Each label is prefixed by a length byte and separating dots are omitted. The buffer length calculation is essentially just a strlen(). A dot that follows a label accounts for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length byte. The last label may or may not end with a dot. If it doesn’t, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer length is incremented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first black box to account for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length byte of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last label.
Dots may be escaped though and an escaped dot is part of a label instead of being a separator. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last label ends with “\.”, an escaped dot, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first black box wrongly concludes that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length byte of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last label has already been accounted for. The buffer remains short by one byte and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least significant byte of dnsclass overflows. The value of dnsclass is most commonly a constant 1.
Exploit from JavaScript?
Shill runs as root. A direct exploit from JavaScript would accomplish in a single step what might ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise take three: renderer code execution -> browser code execution -> privesc to root. This means less work and fewer points of failure. It’s convenient that shill and chrome are separate processes, so if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit fails and crashes shill, it doesn’t bring down chrome and shill is restarted automatically. The direct exploit turned out to be possible, but with difficulties.
There doesn’t seem to be an obvious way to get chrome to place “\.” at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of a Host header using HTTP. So instead cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TURN protocol with WebRTC. It encodes what looks like HTTP into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 username field of TURN. TURN is a binary protocol and it can only be used because HTTP parsing by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 proxy is lax.
Also, shill is listening on a random port. The exploit uses TURN again, to scan cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 localhost ports. It measures connection time to determine if a port was open. The scan also runs into a surprising behavior explained nicely in here. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source and destination TCP ports of a localhost connection attempt happen to match, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel connects cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 socket to itself. Anything sent on a socket is received on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same socket. This causes false positives, so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 scan must retry until a single port remains.
A more difficult issue is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re aren’t any decent memory grooming primitives. The proxy allocates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 headers into a vector of strings. It applies minimal processing to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Via and Host headers, forwards cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 headers to anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r server and frees cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. It accepts a single client at a time. The number of headers is limited to <= 0x7f, header size is <= 0x800 bytes and TURN packet is <= 0x8000 bytes. The rough plan is to do rooming over 6 connections or stages. The problem is that different stages need to reliably place allocations at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same location. This is difficult because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory layout changes between connections in ways that are hard to predict. The solution is to create what I call a persistent size 0x820 byte hole.
820 hole
First, it should be mentioned that shill uses dlmalloc, which is a best-fit allocator. malloc() uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 smallest free chunk that can fit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 request. free() coalesces any neighboring free chunks.
Let’s look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 picture of grooming at stage 1. This creates a persistent hole of 0x820 bytes:
Red means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chunk is in use chunk and green means free. Cyan is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 large top chunk of dlmalloc. The number on each chunk is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chunk size in hex. 0x is omitted. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest of this post, I’ll always refer to chunk sizes in hex, omitting 0x. Also, I’ll often refer to chunk sizes as nouns, which is a short way of referring to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chunk with such size. I’ll omit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual grooming primitives used for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se allocations, but for those interested, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Host and Via header processing in here is used.
So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first picture shows how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 820 hole is created. Four chunks of size 410 are allocated from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 top chunk in [0-3]. In [5,6], cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first 410 is freed and replaced with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 backing allocation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vector of headers. Even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 headers cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365mselves are freed after stage 1 connection closes, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 backing allocation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vector is persistent across connections. The fourth 410 is also freed and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer for incoming server data is placed into it. It is also persistent across stages. Then cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 connection closes, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two 410 headers in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 middle are freed and consolidated into 820.
Why is this 820 hole useful? It is persistent because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous and following 410 are not freed between stages. Each stage can now start with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 steps:
- allocate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 820
- eat all free holes up to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 top chunk by doing tons of small allocations
- free cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 820
Let’s say a stage cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n allocates a small chunk of 100. dlmalloc uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 smallest free chunk, which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 820, because smaller ones were allocated. Now let’s say cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stage finishes and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 100 is freed. Next stage can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same algorithm to place a 100 at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same location. This capability allows just enough grooming in stage 2 and 3 to get from one byte overwrite to overlapping chunks.
But things could go wrong. There might be anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r 820 hole by chance and different stages might allocate a different 820. Or it could happen that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tons of small allocations fail to eat all holes, because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 amount of memory allocated per connection is limited. So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit attempts to get rid of most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 free chunks before stage 1 by combining different techniques. An interesting one perhaps is that it intentionally crashes shill. The process is restarted automatically and starts with a clean heap layout. It also uses two techniques to allocate lots of memory—more than what’s allowed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 limits mentioned above. I won’t go into details here though.
Overlapping chunks
Stage 2 triggers cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory corruption and stage 3 creates overlapping chunks:
First, a 1e0 chunk is allocated in [10-12] by allocating 640, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n 1e0 and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n freeing 640. Then cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 query buffer of ares is allocated into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 110 slot at [13]. This leaves a free 530 in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 middle. Now is a good time to take a closer look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 dlmalloc chunk header declared here:
This header is kept in front of each chunk. The 3 least significant bits of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size field are used as flags. Most importantly, lsb = 1 indicates that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous chunk is in use. So looking at [13], cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 530 chunk has size = 531 and 1e0 chunk has prev_size = 530. The prev_size field is only used when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous chunk is free. Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous chunk spans cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 prev_size field. This means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size field of 530 immediately follows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 query buffer in 110. The single byte that overflows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 query buffer overwrites cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least significant byte of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size field of 530: 0x31 -> 0x01. So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 three flags are not affected. But chunk size is corrupted from 530 to 500 as can be seen from [14].
What’s interesting is that 1e0 doesn’t know anything about this corruption and its prev_size remains 530. Now, [15-17] split cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 free 500 into free 2e0 and in-use 220. But dlmalloc is already confused at this point. When it tries to update cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 prev_size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chunk following 220, it’s off by 30 bytes from 1e0. And 1e0 keeps on believing that prev_size = 530. It also believes that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous chunk is free even though 220 is in-use. So now in [18], 1e0 is freed. It tries to coalesce with a previous 530 chunk. There is a 2e0, where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re used to be 530. dlmalloc is fine with that and creates a large 710 chunk that overlaps cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 220.
These kind of overlapping chunks are relatively easy to exploit. They’re good both for breaking ASLR and getting RCE. This technique for going from a single byte overflow to overlapping chunks is not new. Chris Evans demonstrated it here in 2014 as part of an investigation for this Project Zero post. I’m not sure if anyone has demonstrated earlier.
What’s not shown in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 picture for simplicity is that [14-15] is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 boundary between stage 2 and 3. The memory corruption of stage 2 occurs in DNS code after Via and Host headers are processed, so no furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r grooming is possible. Stage 3 continues with grooming to get overlapping chunks. But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 110 query buffer is actually freed after stage 2. Stage 3 needs to reallocate a 110 chunk at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same location. The method described above is used.
ASLR
Stage 4 breaks ASLR. It first turns cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overlapping 220 into a more convenient 810 chunk:
So it allocates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 820, which overwrites cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header of 220 and changes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size to 810. It’s interesting to note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fd and bk pointers in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header of 220 are also overwritten. The exploit can’t afford to corrupt pointers at this point because it hasn’t broken ASLR. But fd and bk are only used when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chunk is free—cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are used for a doubly linked freelist. [21] frees cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overwritten chunk and dlmalloc finds it to be of size 810.
Next, two free 2a0 chunks are crafted into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 810:
So 2a0 is allocated, 2d0 is allocated and 2a0 is freed. Now, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recently mentioned fd and bk pointers are leaked to break ASLR. The two 2a0 chunks have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same size and are placed into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same freelist. With additional grooming at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 beginning of stage 4, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit can be certain that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two chunks are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only ones in this freelist. Well, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is also a third element linked in—cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 freelist head allocated statically from libc. So looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first 2a0, its fd and bk point to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r 2a0 and into libc. Also, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first 2a0 overlaps with 820, which contains an HTTP header that is forwarded to an attacker-controlled HTTP proxy. So that leaks two pointers that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 proxy server forwards to JavaScript. The two pointers are used to calculate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of 820 and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base address of libc.
To root
ASLR defeated, stages 5 and 6 get code execution:
The rough idea is to overwrite a BindState which holds callback information—a function pointer and arguments. The function pointer is overwritten to point to system() in libc, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base address of which is known. And cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first argument is overwritten to point to a shell command string crafted into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 820 slot, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of which is also known. BindState chunk size is 40, so now, 810 is resized to 40. First, [25] frees 2d0, which consolidates to 810. For cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 810 chunk to be placed into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size 40 freelist, it is removed from its current freelist by allocating it in [27]. 810 size is overwritten to 40 by freeing 820 in [26] and reallocating it with new data in [28]. [29] frees cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resized 40 and [30] allocates a BindState into it. BindState now conveniently overlaps with 820. [31-32] reallocates 820 to corrupt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 BindState to launch system(). The particular callback used triggers in 30 seconds and system() runs a shell command as root.
Persistence bug
It may sound surprising, but an attacker that has gained root on Chrome OS will lose cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 privileges after reboot. Chrome OS has verified boot. Bootloader in read-only memory verifies cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel, which in turn verifies cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hash of each disk block that it needs during runtime. This applies to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system partition which contains all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 executable binaries, libraries and scripts. So an attacker can’t just set up a script to run at boot. But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is also a stateful partition that can be modified. It is intended for variable stuff like logs, configuration files and caches.
The way this exploit achieves persistence across reboots will sound familiar to anyone who’s read about this exploit by geohot. Both use symlinks, dump_vpd_log and modprobe. The dump_vpd_log script itself was fixed to not follow symlinks, but here is a snippet from /etc/init/ui-collect-machine-info.conf:
/var is a stateful partition so UI_MACHINE_INFO_FILE can be turned into an arbitrary symlink. dump_vpd_log --full --stdout writes /mnt/stateful_partition/unencrypted/cache/vpd/full-v2.txt to stdout. This can be used to create an arbitrary file with arbitrary contents during boot. geohot used dump_vpd_log to write a command into /proc/sys/kernel/modprobe at boot so a following modprobe would execute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command. But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are some extra problems when trying to reuse this approach.
The first issue is that /var/run is a symlink to /run, which is a tmpfs and not persistent. The exploit makes /var/run persistent by relinking it to /var/real_run. Some parts of Chrome OS get confused by that and it is dealt with by using more symlinks. I’ll skip cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 details here.
modprobe.d config file
So now it’s possible to write into arbitrary files during boot. Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r issue is that writing into /proc/sys/kernel/modprobe with dump_vpd_log won’t work in this case, because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following udevadm writes into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same file and its output can’t be controlled. The last write() syscall is what counts when writing into /proc/sys/kernel/modprobe. So instead, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit creates /run/modprobe.d, which is is a configuration file for modprobe. Parsing of modprobe.d is lax. Any line starting with "install modulename command..." specifies a command to execute when that module is loaded. Any lines that fail to parse are ignored.
Late modprobe
The final problem is that ui-collect-machine-info.conf runs late during boot, when all modprobing is complete. The created configuration file is not of much use. So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final trick is to find a way to trigger modprobe late during boot. The exploit creates a device file with mknod, which has a major number 173. 173 is unknown to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel, which means that when something accesses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device file, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will attempt to modprobe a handler module named char-major-173-0. Then it is sufficient to turn some commonly accessed file into a symlink to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device file and each access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file will modprobe. The exploit uses /var/lib/metrics/uma-event.
There is yet one more issue. Stateful partitions are mounted with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nodev flag, which blocks access to device files. So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device has to be moved to /dev during startup. This code in /etc/init/cryptohomed.conf is used for that:
The device is created as /mnt/stateful_partition/home/.shadow/attestation.epb and /mnt/stateful_partition/unencrypted/preserve/attestation.epb is turned into a symlink to /dev/net. This moves cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device to /dev/net. /dev/net is used instead of /dev because cryptohomed changes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 owner of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target attestation.epb. This would change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 owner of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 whole /dev directory and cause chrome to crash.
So that completes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Rube Goldberg machine of symlinks. dump_vpd_log creates /run/modprobe.d configuration file with a command to launch as root. cryptohomed moves a device file to /dev/net. Any generated metric accesses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 uma-event symlink to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device, which launches modprobe, which launches a command from modprobe.d.
Patches
By now, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issues have been fixed pretty thoroughly. c-ares was patched in Chrome OS and upstream. The HTTP proxy was removed from shill. TURN implementation was hardened to block JavaScript from sending an arbitrary username to a localhost TCP port. And cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symlink issues were fixed here, here, here and here.