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

Commit 31c09dc0 authored by Naresh Maradana's avatar Naresh Maradana Committed by Preeti Nagar
Browse files

seemp: Port changes from 4.9 to 4.14



This patch include these changes:
- seemp: clean up stale code and add proper headers
- seemp: check array index range
- seemp: read hypervisor rooting detections
- seemp: adjust hypervisor rooting report format
- seemp: adjust interpretation of rooting report
- seemp: check validity of task struct pointer
- seemp: fix minor issues

Change-Id: I1419b583b1c2d1ba13e9661a721c5dee95484e2d
Signed-off-by: default avatarNaresh Maradana <nmardana@codeaurora.org>
parent 84932aaa
Loading
Loading
Loading
Loading
+127 −6
Original line number Diff line number Diff line
@@ -13,6 +13,12 @@

#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 <linux/sched/signal.h>

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

@@ -24,6 +30,10 @@
#define FOUR_MB 4
#define YEAR_BASE 1900

#define EL2_SCM_ID 0x02001902
#define KP_EL2_REPORT_REVISION 0x01000101
#define INVALID_PID -1

static struct seemp_logk_dev *slogk_dev;

static unsigned int ring_sz = FOUR_MB;
@@ -49,11 +59,16 @@ 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 pid_t seemp_logk_get_pid(struct task_struct *t);
static int seemp_logk_rtic_thread(void *data);

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

@@ -289,7 +304,7 @@ static bool seemp_logk_get_bit_from_vector(__u8 *pVec, __u32 index)
	unsigned int bit_num = index%8;
	unsigned char byte;

	if (DIV_ROUND_UP(index, 8) > MASK_BUFFER_SIZE)
	if (byte_num >= MASK_BUFFER_SIZE)
		return false;

	byte = pVec[byte_num];
@@ -332,10 +347,12 @@ static long seemp_logk_ioctl(struct file *filp, unsigned int cmd,
		return seemp_logk_set_mapping(arg);
	} else if (cmd == SEEMP_CMD_CHECK_FILTER) {
		return seemp_logk_check_filter(arg);
	}
	} else {
		pr_err("Invalid Request %X\n", cmd);
		return -ENOIOCTLCMD;
	}
	return 0;
}

static long seemp_logk_reserve_rdblks(
		struct seemp_logk_dev *sdev, unsigned long arg)
@@ -569,6 +586,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\n");
			rtic_thread = NULL;
		}
	}

	return 0;
}

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

static pid_t seemp_logk_get_pid(struct task_struct *t)
{
	struct task_struct *task;
	pid_t pid;

	if (t == NULL)
		return INVALID_PID;

	rcu_read_lock();
	for_each_process(task) {
		if (task == t) {
			pid = task->pid;
			rcu_read_unlock();
			return pid;
		}
	}
	rcu_read_unlock();
	return INVALID_PID;
}

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;

	if (header->report_version < KP_EL2_REPORT_REVISION)
		return -EINVAL;

	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 &&
				(last_sequence_number == 0
					|| report->sequence_number >
						last_sequence_number)) {
				seemp_logk_rtic(report->report_type,
					seemp_logk_get_pid(
						(struct task_struct *)
						report->actor),
					/* leave this empty until
					 * asset id is provided
					 */
					"",
					report->asset_category,
					report->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;
@@ -628,12 +729,12 @@ __init int seemp_logk_init(void)

	cl = class_create(THIS_MODULE, seemp_LOGK_DEV_NAME);
	if (cl == NULL) {
		pr_err("class create failed");
		pr_err("class create failed\n");
		goto cdev_fail;
	}
	if (device_create(cl, NULL, devno, NULL,
			seemp_LOGK_DEV_NAME) == NULL) {
		pr_err("device create failed");
		pr_err("device create failed\n");
		goto class_destroy_fail;
	}
	cdev_init(&(slogk_dev->cdev), &seemp_logk_fops);
@@ -641,7 +742,7 @@ __init int seemp_logk_init(void)
	slogk_dev->cdev.owner = THIS_MODULE;
	ret = cdev_add(&(slogk_dev->cdev), MKDEV(slogk_dev->major, 0), 1);
	if (ret) {
		pr_err("cdev_add failed with ret = %d", ret);
		pr_err("cdev_add failed with ret = %d\n", ret);
		goto class_destroy_fail;
	}

@@ -650,6 +751,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\n",
				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 +782,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);
+25 −0
Original line number Diff line number Diff line
@@ -158,4 +158,29 @@ 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 */
	__u64 num_incidents;      /* Number of Incidents Observed by EL2 */
	__u8 protection_enabled;  /* Kernel Assets protected by EL2 */
	__u8 pad1;
	__u8 pad2;
	__u8 pad3;
	__u32 pad4;
};

/* individual report */
struct el2_report_data_t {
	__u64 sequence_number; /* Sequence number of the report */
	__u64 actor; /* Actor that caused the Incident.  */
	__u8 report_valid;
		/* Flag to indicate whether report instance is valid */
	__u8 report_type;        /* Report Type */
	__u8 asset_category; /* Asset Category */
	__u8 response;       /* Response From EL2 */
};

#endif
+9 −65
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

@@ -67,68 +69,22 @@ static inline void seemp_logk_sendto(int fd, void __user *buff, size_t len,
	seemp_logk_kernel_end(blck);
}

/*
 * NOTE: only recvfrom is going to be instrumented
 * since recv sys call internally calls recvfrom
 * with 2 extra parameters
 */
static inline void seemp_logk_recvfrom(int fd, void __user *ubuf,
		size_t size, unsigned int flags, struct sockaddr __user *addr,
		int __user *addr_len)
{
	char *buf = NULL;
	void *blck = NULL;

	/*sets up buf and blck correctly*/
	blck = seemp_setup_buf(&buf);
	if (!blck)
		return;

	/*fill the buf*/
	SEEMP_LOGK_RECORD(SEEMP_API_kernel__recvfrom, "size=%u,fd=%d",
			(unsigned int)size, fd);

	seemp_logk_kernel_end(blck);
}

static inline void seemp_logk_oom_adjust_write(pid_t pid,
					kuid_t uid, int oom_adj)
{
	char *buf = NULL;
	void *blck = NULL;

	/*sets up buf and blck correctly*/
	blck = seemp_setup_buf(&buf);
	if (!blck)
		return;

	/*fill the buf*/
	SEEMP_LOGK_RECORD(SEEMP_API_kernel__oom_adjust_write,
			 "app_uid=%d,app_pid=%d,oom_adj=%d",
			uid.val, pid, oom_adj);

	seemp_logk_kernel_end(blck);
}

static inline void seemp_logk_oom_score_adj_write(pid_t pid, kuid_t uid,
					int oom_adj_score)
static inline void seemp_logk_rtic(__u8 type, pid_t pid, __u8 asset_id[0x20],
		__u8 asset_category, __u8 response)
{
	char *buf = NULL;
	void *blck = NULL;

	/*sets up buf and blck correctly*/
	blck = seemp_setup_buf(&buf);
	if (!blck)
		return;

	/*fill the buf*/
	snprintf(buf, MAX_BUF_SIZE,
		"-1|kernel|oom_score_adj_write|app_uid=%d,app_pid=%d,oom_adj=%d|--end",
		uid.val, pid, oom_adj_score);
	SEEMP_LOGK_RECORD(SEEMP_API_kernel__rtic,
		"app_pid=%d,rtic_type=%u,asset_id=%s,asset_category=%u,response=%u",
		pid, 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,
@@ -136,20 +92,8 @@ static inline void seemp_logk_sendto(int fd, void __user *buff,
{
}

static inline void seemp_logk_recvfrom
		(int fd, void __user *ubuf, size_t size,
		unsigned int flags, struct sockaddr __user *addr,
		int __user *addr_len)
{
}

static inline void seemp_logk_oom_adjust_write
		(pid_t pid, kuid_t uid, int oom_adj)
{
}

static inline void seemp_logk_oom_score_adj_write
		(pid_t pid, kuid_t uid, int oom_adj_score)
static inline void seemp_logk_rtic(__u8 type, __u64 actor, __u8 asset_id[0x20],
		__u8 asset_category, __u8 response)
{
}
#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
+28 −1
Original line number Diff line number Diff line
#ifndef _PARAM_ID_H_
#define _PARAM_ID_H_

#include <linux/string.h>
#include <linux/types.h>

#define PARAM_ID_LEN 0
#define PARAM_ID_OOM_ADJ 1
#define PARAM_ID_APP_UID 2
@@ -12,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)
{
@@ -41,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;
}
@@ -83,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;
}