Home Trying to Enable KCOV on Samsung Galaxy S22
Post
Cancel

Trying to Enable KCOV on Samsung Galaxy S22

In this article, I will talk about the research I did by spending about 1.5 months on the S22 device. The primary purpose of my research was to fuzz the device by compiling the kernel with KCOV, but unfortunately, I could not succeed as a result of my many attempts. In the rest of our article, I will explain the experiments I made respectively.

First I downloaded the firmware of the device from SAMFW, then I downloaded the kernel code of the device from Samsung Opensource and started working.

Enable KCOV

After downloading the code to my local, I first bought a clean build and flashed it to the device. Everything worked as it should. Then I enabled KCOV on the kernel config and flashed it to the device and I got bootloop. At that point, I started thinking about what was holding me back.

Setting props

The first thing that came to my mind afterwards was of course to think that it was the security features inside the device. From this point of view, the first thing I tried to do was to change the device’s props. For this I unpacked vendor_boot.img with Magisk, then I changed ro.selinux and all the other props that I thought were related to the security features but unfortunately it didn’t help me.

Trying to debug the device

We had a kernel image that did not boot when flashed. Then I thought about getting a log file and started looking for the log files on the system one by one, scrutinizing them to make sure I didn’t miss a single log.

But what I was ignoring is this: Since the device was not booting, naturally it was not creating a log file anywhere. Because the problem was the PKM of RKP feature. I will talk about this in the future.

At this step, I started to think to myself that I should come up with a solution. In this step, I wrote a code to log to /data/tmp/local in a function that runs when the kernel first boots and is called again at certain intervals. Here, too, I incurred the wrath of SELinux…

Even though I turned off SELinux through its props, it remained enforced during boot. Even though SELinux was permissive after boot, it didn’t work.

(NOTE: The function was called even when SELinux was permissive but SELinux prevented the write with a warning).

In this strange situation, I had to write a custom SELinux policy. I wrote this policy too, but even though it created the file, the write operation never happened.  

RKP

I mentioned that I couldn’t get any logs from the device so far, and I didn’t have a chance to open the phone and connect it to the UART. In this context, I started to analyze the device by trial and error.

First of all, to debug KCOV, I found all the code fragments that were added and removed when KCOV was opened in the kernel code. Then I deleted and compiled all the code fragments of KCOV. What I wanted to understand here was to understand whether the security feature on the device read the .config file and blocked us. Of course, it was not blocking us by reading the .config.

After that, I started to enable the code pieces step by step and I realized the following:

Every time I added or removed an element to the struct named task_struct, the kernel would bootloop. KCOV was a config that added elements to this task_struct. When I realized this, the first thing that came to my mind was that some code was hardcoded according to the size of the task_struct and therefore there was a shift in some casting operations. This slippage was crashing us.

But of course, this was not the case, there were two reasons for this: 1) We were also crashing when we added an element at the bottom of the task_struct. 2) Inside the task_struct, variables were pointing to a struct. I defined variables under these structs read the code that used this struct and made sure that I would not cause any crash (we examined it in detail to make sure that we would not cause any kernel BUGs), but it still did not boot.

At this stage, I realized that there was a security feature that prevented the following; adding elements to task_struct, Adding elements to structs under task_struct.

But this seemed ridiculous to me. Yes, I couldn’t define a variable inside a task_struct, but why can’t I define a variable inside a struct pointed to by a variable inside a task_struct!!!!

So I made one last attempt and tried to find all the structs that have pointers under task_struct and add elements to the bottom of each one.

pi_state_cache, rcu_node, futex_pi_state ------> I was successful with these three structs.

In other words, I could add variables to these structs as I wanted. In this way, instead of defining the elements that KCOV uses directly under task_struct, I would define them in one of these structs. Then, with some minor changes to the kcov file, I would have successfully compiled kcov.

Custom KCOV

As I mentioned in the previous section, I adapted the struct named futex_pi_state to kcov.

When I ran the file compiled with this kcov.c, I got bootloop again. The reason for this was symbols as far as I researched. RKP was somehow examining the symbols in the kernel image and blocking us. But I couldn’t find any conclusive evidence for this.

And at this step, I thought the only solution was to try to turn off RKP.

Trying to turn off security features (e.g. RKP, selinux…) via kernel code

To make SELinux permissive permanently in the kernel code, we need to edit the kernel_platform/common/security/selinux/selinuxfs.c file, where we need to make the following changes:

Lines 152-178 below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//CUT
/* No partial writes. */
  if (*ppos != 0)
   return -EINVAL;
  page = memdup_user_nul(buf, count);
  if (IS_ERR(page))
    return PTR_ERR(page);
  length = -EINVAL;
  if (sscanf(page, "%d", &new_value) != 1)
    goto out;
  new_value = !!new_value;

  old_value = enforcing_enabled(state);

  new_value = 0; //ADD FOR PERMANENT PERMESSIVE

  if (new_value != old_value) {
    length = avc_has_perm(&selinux_state,
           current_sid(), SECINITSID_SECURITY,
           SECCLASS_SECURITY, 
  //CUT

  This link is useful for turning off Knox and RKP security features:

I made all these changes normally and the device booted without KCOV. Then I enabled KCOV and failed. I believe that the reason for this is the PKM, which is a security feature under the RKP. It blocks to change kernel code.

Turning off RKP in Config does not mean turning off the RKP on the CPU.

This post is licensed under CC BY 4.0 by the author.