summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuren Baghdasaryan <surenb@google.com>2019-07-12 20:13:17 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-07-12 20:13:17 +0000
commite818cccd58f3c550ef92c8e0e9ddffbf8916c336 (patch)
tree46f66fc3c34a7f615b65721722079172a07f0756
parentc9aff9869d8cb2efbfa24bf76f431337cd957bd0 (diff)
parentc68cf6fe656d4f6e82d7831ae0615f8d2a883eac (diff)
downloadcore-e818cccd58f3c550ef92c8e0e9ddffbf8916c336.tar.gz
Merge "lmkd: Prevent non-main threads being registered or killed by lmkd" into qt-r1-dev
-rw-r--r--lmkd/lmkd.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index c2ee061e9..7c5a466ca 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -79,6 +79,7 @@
#define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes"
#define ZONEINFO_PATH "/proc/zoneinfo"
#define MEMINFO_PATH "/proc/meminfo"
+#define PROC_STATUS_TGID_FIELD "Tgid:"
#define LINE_MAX 128
/* Android Logger event logtags (see event.logtags) */
@@ -551,6 +552,49 @@ static inline long get_time_diff_ms(struct timespec *from,
(to->tv_nsec - from->tv_nsec) / (long)NS_PER_MS;
}
+static int proc_get_tgid(int pid) {
+ char path[PATH_MAX];
+ char buf[PAGE_SIZE];
+ int fd;
+ ssize_t size;
+ char *pos;
+ int64_t tgid = -1;
+
+ snprintf(path, PATH_MAX, "/proc/%d/status", pid);
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (fd < 0) {
+ return -1;
+ }
+
+ size = read_all(fd, buf, sizeof(buf) - 1);
+ if (size < 0) {
+ goto out;
+ }
+ buf[size] = 0;
+
+ pos = buf;
+ while (true) {
+ pos = strstr(pos, PROC_STATUS_TGID_FIELD);
+ /* Stop if TGID tag not found or found at the line beginning */
+ if (pos == NULL || pos == buf || pos[-1] == '\n') {
+ break;
+ }
+ pos++;
+ }
+
+ if (pos == NULL) {
+ goto out;
+ }
+
+ pos += strlen(PROC_STATUS_TGID_FIELD);
+ while (*pos == ' ') pos++;
+ parse_int64(pos, &tgid);
+
+out:
+ close(fd);
+ return (int)tgid;
+}
+
static void cmd_procprio(LMKD_CTRL_PACKET packet) {
struct proc *procp;
char path[80];
@@ -559,6 +603,7 @@ static void cmd_procprio(LMKD_CTRL_PACKET packet) {
struct lmk_procprio params;
bool is_system_server;
struct passwd *pwdrec;
+ int tgid;
lmkd_pack_get_procprio(packet, &params);
@@ -568,6 +613,14 @@ static void cmd_procprio(LMKD_CTRL_PACKET packet) {
return;
}
+ /* Check if registered process is a thread group leader */
+ tgid = proc_get_tgid(params.pid);
+ if (tgid >= 0 && tgid != params.pid) {
+ ALOGE("Attempt to register a task that is not a thread group leader (tid %d, tgid %d)",
+ params.pid, tgid);
+ return;
+ }
+
/* gid containing AID_READPROC required */
/* CAP_SYS_RESOURCE required */
/* CAP_DAC_OVERRIDE required */
@@ -1332,6 +1385,7 @@ static int last_killed_pid = -1;
static int kill_one_process(struct proc* procp, int min_oom_score) {
int pid = procp->pid;
uid_t uid = procp->uid;
+ int tgid;
char *taskname;
int tasksize;
int r;
@@ -1345,6 +1399,12 @@ static int kill_one_process(struct proc* procp, int min_oom_score) {
(void)(min_oom_score);
#endif
+ tgid = proc_get_tgid(pid);
+ if (tgid >= 0 && tgid != pid) {
+ ALOGE("Possible pid reuse detected (pid %d, tgid %d)!", pid, tgid);
+ goto out;
+ }
+
taskname = proc_get_name(pid);
if (!taskname) {
goto out;