Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 99e66875 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "seemp: read hypervisor rooting detections"

parents 331c0fd4 943c3b4f
Loading
Loading
Loading
Loading
+89 −0
Original line number Diff line number Diff line
@@ -13,6 +13,11 @@

#define pr_fmt(fmt) "seemp: %s: " fmt, __func__

#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/seemp_instrumentation.h>
#include <soc/qcom/scm.h>

#include "seemp_logk.h"
#include "seemp_ringbuf.h"

@@ -24,6 +29,8 @@
#define FOUR_MB 4
#define YEAR_BASE 1900

#define EL2_SCM_ID 0x02001902

static struct seemp_logk_dev *slogk_dev;

static unsigned int ring_sz = FOUR_MB;
@@ -49,11 +56,15 @@ static rwlock_t filter_lock;
static struct seemp_source_mask *pmask;
static unsigned int num_sources;

static void *el2_shared_mem;
static struct task_struct *rtic_thread;

static long seemp_logk_reserve_rdblks(
		struct seemp_logk_dev *sdev, unsigned long arg);
static long seemp_logk_set_mask(unsigned long arg);
static long seemp_logk_set_mapping(unsigned long arg);
static long seemp_logk_check_filter(unsigned long arg);
static int seemp_logk_rtic_thread(void *data);

void* (*seemp_logk_kernel_begin)(char **buf);

@@ -569,6 +580,15 @@ static int seemp_logk_mmap(struct file *filp,
		}
	}

	if (!rtic_thread && el2_shared_mem) {
		rtic_thread = kthread_run(seemp_logk_rtic_thread,
				NULL, "seemp_logk_rtic_thread");
		if (IS_ERR(rtic_thread)) {
			pr_err("rtic_thread creation failed");
			rtic_thread = NULL;
		}
	}

	return 0;
}

@@ -580,10 +600,59 @@ static const struct file_operations seemp_logk_fops = {
	.mmap = seemp_logk_mmap,
};

static int seemp_logk_rtic_thread(void *data)
{
	struct el2_report_header_t *header;
	__u64 last_sequence_number = 0;
	int last_pos = -1;
	int i;
	int num_entries = (PAGE_SIZE - sizeof(struct el2_report_header_t))
		/ sizeof(struct el2_report_data_t);
	header = (struct el2_report_header_t *) el2_shared_mem;

	while (!kthread_should_stop()) {
		for (i = 1; i < num_entries + 1; i++) {
			struct el2_report_data_t *report;
			int cur_pos = last_pos + i;

			if (cur_pos >= num_entries)
				cur_pos -= num_entries;

			report = el2_shared_mem +
				sizeof(struct el2_report_header_t) +
				cur_pos * sizeof(struct el2_report_data_t);

			/* determine legitimacy of report */
			if (report->report_valid &&
				report->sequence_number <=
					header->num_incidents &&
				(last_sequence_number == 0
					|| report->sequence_number >
						last_sequence_number)) {
				seemp_logk_rtic(report->report_type,
					report->report.incident.actor,
					report->report.incident.asset_id,
					report->report.incident.asset_category,
					report->report.incident.response);
				last_sequence_number = report->sequence_number;
			} else {
				last_pos = cur_pos - 1;
				break;
			}
		}

		/* periodically check el2 report every second */
		ssleep(1);
	}

	return 0;
}

__init int seemp_logk_init(void)
{
	int ret;
	int devno = 0;
	struct scm_desc desc = {0};

	num_sources = 0;
	kmalloc_flag = 0;
@@ -650,6 +719,21 @@ __init int seemp_logk_init(void)
	init_waitqueue_head(&slogk_dev->readers_wq);
	init_waitqueue_head(&slogk_dev->writers_wq);
	rwlock_init(&filter_lock);

	el2_shared_mem = (void *) __get_free_page(GFP_KERNEL);
	if (el2_shared_mem) {
		desc.arginfo = SCM_ARGS(2, SCM_RW, SCM_VAL);
		desc.args[0] = (uint64_t) virt_to_phys(el2_shared_mem);
		desc.args[1] = PAGE_SIZE;
		ret = scm_call2(EL2_SCM_ID, &desc);
		if (ret || desc.ret[0] || desc.ret[1]) {
			pr_err("SCM call failed with ret val = %d %d %d",
				ret, (int)desc.ret[0], (int)desc.ret[1]);
			free_page((unsigned long) el2_shared_mem);
			el2_shared_mem = NULL;
		}
	}

	return 0;
class_destroy_fail:
	class_destroy(cl);
@@ -666,6 +750,11 @@ __exit void seemp_logk_cleanup(void)
{
	dev_t devno = MKDEV(slogk_dev->major, slogk_dev->minor);

	if (rtic_thread) {
		kthread_stop(rtic_thread);
		rtic_thread = NULL;
	}

	seemp_logk_detach();

	cdev_del(&slogk_dev->cdev);
+41 −0
Original line number Diff line number Diff line
@@ -158,4 +158,45 @@ struct seemp_source_mask {
	__u32       hash;
	bool        isOn;
};

/* report region header */
struct el2_report_header_t {
	__u64 report_version;     /* Version of the EL2 report */
	__u64 mp_catalog_version;
		/* Version of MP catalogue used for kernel protection */
	__u8 protection_enabled;  /* Kernel Assets protected by EL2 */
	__u8 pad1;
	__u8 pad2;
	__u8 pad3;
	__u32 pad4;
	__u64 num_incidents;      /* Number of Incidents Observed by EL2 */
};

/* individual report contents */
union el2_report {
	struct {
		__u8 asset_id[0x20]; /* Asset Identifier */
		__u64 actor;
			/* Actor that caused the Incident.  */
		__u8 asset_category; /* Asset Category */
		__u8 response;       /* Response From EL2 */
		__u16 pad1;
		__u32 pad2;
	} incident;
	struct {
		__u64 reserved;      /* TBD */
	} info;
};

/* individual report */
struct el2_report_data_t {
	__u8 report_valid;
		/* Flag to indicate whether report instance is valid */
	__u8 report_type;        /* Report Type */
	__u8 pad1;
	__u8 pad2;
	__u64 sequence_number;   /* Sequence number of the report */
	union el2_report report;       /* Report Contents */
};

#endif
+24 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@

#ifdef CONFIG_SEEMP_CORE
#include <linux/kernel.h>
#include <linux/seemp_api.h>
#include <linux/socket.h>

#define MAX_BUF_SIZE 188

@@ -66,11 +68,33 @@ static inline void seemp_logk_sendto(int fd, void __user *buff, size_t len,

	seemp_logk_kernel_end(blck);
}

static inline void seemp_logk_rtic(__u8 type, __u64 actor, __u8 asset_id[0x20],
		__u8 asset_category, __u8 response)
{
	char *buf = NULL;
	void *blck = NULL;

	blck = seemp_setup_buf(&buf);
	if (!blck)
		return;

	SEEMP_LOGK_RECORD(SEEMP_API_kernel__rtic,
		"app_pid=%llu,rtic_type=%u,asset_id=%s,asset_category=%u,response=%u",
		actor, type, asset_id, asset_category, response);

	seemp_logk_kernel_end(blck);
}
#else
static inline void seemp_logk_sendto(int fd, void __user *buff,
		size_t len, unsigned int flags, struct sockaddr __user *addr,
		int addr_len)
{
}

static inline void seemp_logk_rtic(__u8 type, __u64 actor, __u8 asset_id[0x20],
		__u8 asset_category, __u8 response)
{
}
#endif
#endif
+2 −0
Original line number Diff line number Diff line
#ifndef _SEEMP_API_H_
#define _SEEMP_API_H_

#define SEEMP_API_kernel__rtic                                            100000

#define SEEMP_API_kernel__oom_adjust_write                                     0
#define SEEMP_API_kernel__sendto                                               1
#define SEEMP_API_kernel__recvfrom                                             2
+25 −1
Original line number Diff line number Diff line
@@ -15,7 +15,11 @@
#define PARAM_ID_SENSOR 8
#define PARAM_ID_WINDOW_TYPE 9
#define PARAM_ID_WINDOW_FLAG 10
#define NUM_PARAM_IDS 11
#define PARAM_ID_RTIC_TYPE 11
#define PARAM_ID_RTIC_ASSET_ID 12
#define PARAM_ID_RTIC_ASSET_CATEGORY 13
#define PARAM_ID_RTIC_RESPONSE 14
#define NUM_PARAM_IDS 15

static inline int param_id_index(const char *param, const char *end)
{
@@ -44,6 +48,14 @@ static inline int param_id_index(const char *param, const char *end)
		id = 9;
	else if ((len == 11) && !memcmp(param, "window_flag", 11))
		id = 10;
	else if ((len == 9) && !memcmp(param, "rtic_type", 9))
		id = 11;
	else if ((len == 8) && !memcmp(param, "asset_id", 8))
		id = 12;
	else if ((len == 14) && !memcmp(param, "asset_category", 14))
		id = 13;
	else if ((len == 8) && !memcmp(param, "response", 8))
		id = 14;

	return id;
}
@@ -86,6 +98,18 @@ static inline const char *get_param_id_name(int id)
	case 10:
		name = "window_flag";
		break;
	case 11:
		name = "rtic_type";
		break;
	case 12:
		name = "asset_id";
		break;
	case 13:
		name = "asset_category";
		break;
	case 14:
		name = "response";
		break;
	}
	return name;
}