Merge "lmkd: Track processes using pidfds"

This commit is contained in:
Suren Baghdasaryan 2019-10-09 17:46:14 +00:00 committed by Gerrit Code Review
commit d11c6f7fd8

View file

@ -144,6 +144,11 @@ static inline int sys_pidfd_open(pid_t pid, unsigned int flags) {
return syscall(__NR_pidfd_open, pid, flags); return syscall(__NR_pidfd_open, pid, flags);
} }
static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
unsigned int flags) {
return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
}
/* default to old in-kernel interface if no memory pressure events */ /* default to old in-kernel interface if no memory pressure events */
static bool use_inkernel_interface = true; static bool use_inkernel_interface = true;
static bool has_inkernel_module; static bool has_inkernel_module;
@ -482,6 +487,7 @@ struct adjslot_list {
struct proc { struct proc {
struct adjslot_list asl; struct adjslot_list asl;
int pid; int pid;
int pidfd;
uid_t uid; uid_t uid;
int oomadj; int oomadj;
struct proc *pidhash_next; struct proc *pidhash_next;
@ -698,6 +704,13 @@ static int pid_remove(int pid) {
prevp->pidhash_next = procp->pidhash_next; prevp->pidhash_next = procp->pidhash_next;
proc_unslot(procp); proc_unslot(procp);
/*
* Close pidfd here if we are not waiting for corresponding process to die,
* in which case stop_wait_for_proc_kill() will close the pidfd later
*/
if (procp->pidfd >= 0 && procp->pidfd != last_kill_pid_or_fd) {
close(procp->pidfd);
}
free(procp); free(procp);
return 0; return 0;
} }
@ -922,16 +935,27 @@ static void cmd_procprio(LMKD_CTRL_PACKET packet) {
procp = pid_lookup(params.pid); procp = pid_lookup(params.pid);
if (!procp) { if (!procp) {
procp = malloc(sizeof(struct proc)); int pidfd = -1;
if (!procp) {
// Oh, the irony. May need to rebuild our state. if (pidfd_supported) {
pidfd = TEMP_FAILURE_RETRY(sys_pidfd_open(params.pid, 0));
if (pidfd < 0) {
ALOGE("pidfd_open for pid %d failed; errno=%d", params.pid, errno);
return; return;
} }
}
procp->pid = params.pid; procp = calloc(1, sizeof(struct proc));
procp->uid = params.uid; if (!procp) {
procp->oomadj = params.oomadj; // Oh, the irony. May need to rebuild our state.
proc_insert(procp); return;
}
procp->pid = params.pid;
procp->pidfd = pidfd;
procp->uid = params.uid;
procp->oomadj = params.oomadj;
proc_insert(procp);
} else { } else {
proc_unslot(procp); proc_unslot(procp);
procp->oomadj = params.oomadj; procp->oomadj = params.oomadj;
@ -1733,7 +1757,7 @@ static void kill_done_handler(int data __unused, uint32_t events __unused,
poll_params->update = POLLING_RESUME; poll_params->update = POLLING_RESUME;
} }
static void start_wait_for_proc_kill(int pid) { static void start_wait_for_proc_kill(int pid_or_fd) {
static struct event_handler_info kill_done_hinfo = { 0, kill_done_handler }; static struct event_handler_info kill_done_hinfo = { 0, kill_done_handler };
struct epoll_event epev; struct epoll_event epev;
@ -1743,15 +1767,10 @@ static void start_wait_for_proc_kill(int pid) {
stop_wait_for_proc_kill(false); stop_wait_for_proc_kill(false);
} }
if (!pidfd_supported) { last_kill_pid_or_fd = pid_or_fd;
/* If pidfd is not supported store PID of the process being killed */
last_kill_pid_or_fd = pid;
return;
}
last_kill_pid_or_fd = TEMP_FAILURE_RETRY(sys_pidfd_open(pid, 0)); if (!pidfd_supported) {
if (last_kill_pid_or_fd < 0) { /* If pidfd is not supported just store PID and exit */
ALOGE("pidfd_open for process pid %d failed; errno=%d", pid, errno);
return; return;
} }
@ -1770,6 +1789,7 @@ static void start_wait_for_proc_kill(int pid) {
static int kill_one_process(struct proc* procp, int min_oom_score, int kill_reason, static int kill_one_process(struct proc* procp, int min_oom_score, int kill_reason,
const char *kill_desc, union meminfo *mi, struct timespec *tm) { const char *kill_desc, union meminfo *mi, struct timespec *tm) {
int pid = procp->pid; int pid = procp->pid;
int pidfd = procp->pidfd;
uid_t uid = procp->uid; uid_t uid = procp->uid;
int tgid; int tgid;
char *taskname; char *taskname;
@ -1799,11 +1819,14 @@ static int kill_one_process(struct proc* procp, int min_oom_score, int kill_reas
TRACE_KILL_START(pid); TRACE_KILL_START(pid);
/* Have to start waiting before sending SIGKILL to make sure pid is valid */
start_wait_for_proc_kill(pid);
/* CAP_KILL required */ /* CAP_KILL required */
r = kill(pid, SIGKILL); if (pidfd < 0) {
start_wait_for_proc_kill(pid);
r = kill(pid, SIGKILL);
} else {
start_wait_for_proc_kill(pidfd);
r = sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
}
TRACE_KILL_END(); TRACE_KILL_END();