|  | 
| 65 | 65 | #include <linux/mm.h> | 
| 66 | 66 | #include <linux/swap.h> | 
| 67 | 67 | #include <linux/rcupdate.h> | 
|  | 68 | +#include <linux/wait.h> | 
|  | 69 | +#include <linux/list.h> | 
| 68 | 70 | #include <linux/kallsyms.h> | 
| 69 | 71 | #include <linux/stacktrace.h> | 
| 70 | 72 | #include <linux/resource.h> | 
| 71 | 73 | #include <linux/module.h> | 
| 72 | 74 | #include <linux/mount.h> | 
| 73 | 75 | #include <linux/security.h> | 
| 74 |  | -#include <linux/ptrace.h> | 
| 75 | 76 | #include <linux/tracehook.h> | 
| 76 | 77 | #include <linux/cgroup.h> | 
| 77 | 78 | #include <linux/cpuset.h> | 
| @@ -209,16 +210,8 @@ static struct mm_struct *__check_mem_permission(struct task_struct *task) | 
| 209 | 210 | if (task == current) | 
| 210 | 211 | return mm; | 
| 211 | 212 | 
 | 
| 212 |  | -/* | 
| 213 |  | - * If current is actively ptrace'ing, and would also be | 
| 214 |  | - * permitted to freshly attach with ptrace now, permit it. | 
| 215 |  | - */ | 
| 216 | 213 | if (task_is_stopped_or_traced(task)) { | 
| 217 |  | -int match; | 
| 218 |  | -rcu_read_lock(); | 
| 219 |  | -match = (ptrace_parent(task) == current); | 
| 220 |  | -rcu_read_unlock(); | 
| 221 |  | -if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH)) | 
|  | 214 | +if (ptrace_may_access(task, PTRACE_MODE_ATTACH)) | 
| 222 | 215 | return mm; | 
| 223 | 216 | } | 
| 224 | 217 | 
 | 
| @@ -966,6 +959,83 @@ static const struct file_operations proc_mem_operations = { | 
| 966 | 959 | .open= mem_open, | 
| 967 | 960 | }; | 
| 968 | 961 | 
 | 
|  | 962 | +static int ctl_stop(struct task_struct *task) | 
|  | 963 | +{ | 
|  | 964 | +printk("PROCTRACE stopping %d task with %d\n", task->pid, current->pid); | 
|  | 965 | +send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); | 
|  | 966 | +return 0; | 
|  | 967 | +} | 
|  | 968 | + | 
|  | 969 | +static int ctl_start(struct task_struct *task) { | 
|  | 970 | +printk("PROCTRACE continuing %d task with %d\n", task->pid, current->pid); | 
|  | 971 | +wake_up_process(task); | 
|  | 972 | +return 0; | 
|  | 973 | +} | 
|  | 974 | + | 
|  | 975 | +static int ctl_waitsignal(struct task_struct *task, int sigmask) { | 
|  | 976 | +struct sig_wait_queue_struct *sig_wait; | 
|  | 977 | +DEFINE_WAIT(wait); | 
|  | 978 | +int retval = 0; | 
|  | 979 | + | 
|  | 980 | +printk("PROCTRACE waiting %d task with %d. sigmask %d\n", task->pid, current->pid, sigmask); | 
|  | 981 | + | 
|  | 982 | +printk("Allocating new signal wait queue\n"); | 
|  | 983 | +sig_wait = kmalloc(sizeof(struct sig_wait_queue_struct), GFP_KERNEL); | 
|  | 984 | +if (!sig_wait) { | 
|  | 985 | +retval = -ENOMEM; | 
|  | 986 | +goto done; | 
|  | 987 | +} | 
|  | 988 | +sig_wait->sigmask = sigmask; | 
|  | 989 | +init_waitqueue_head(&sig_wait->wait_queue); | 
|  | 990 | + | 
|  | 991 | +write_lock(&tasklist_lock); | 
|  | 992 | +list_add(&sig_wait->list, &task->sig_wait_list); | 
|  | 993 | +write_unlock(&tasklist_lock); | 
|  | 994 | + | 
|  | 995 | +prepare_to_wait(&sig_wait->wait_queue, &wait, TASK_INTERRUPTIBLE); | 
|  | 996 | +schedule(); | 
|  | 997 | +finish_wait(&sig_wait->wait_queue, &wait); | 
|  | 998 | + | 
|  | 999 | +write_lock(&tasklist_lock); | 
|  | 1000 | +list_del(&sig_wait->list); | 
|  | 1001 | +write_unlock(&tasklist_lock); | 
|  | 1002 | + | 
|  | 1003 | +kfree(sig_wait); | 
|  | 1004 | + | 
|  | 1005 | +done: | 
|  | 1006 | +return retval; | 
|  | 1007 | +} | 
|  | 1008 | + | 
|  | 1009 | +static ssize_t ctl_write(struct file * file, const char __user *buf, | 
|  | 1010 | + size_t count, loff_t *ppos) | 
|  | 1011 | +{ | 
|  | 1012 | +int tmp, i; | 
|  | 1013 | +struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); | 
|  | 1014 | + | 
|  | 1015 | +if (strncmp(buf, "stop", 4) == 0) { | 
|  | 1016 | +ctl_stop(task); | 
|  | 1017 | +} else if (strncmp(buf, "start", 5) == 0) { | 
|  | 1018 | +ctl_start(task); | 
|  | 1019 | +} else if (strncmp(buf, "waitsignal", 10) == 0) { | 
|  | 1020 | +tmp = 0; | 
|  | 1021 | +for (i = 11; i < count; ++i) { | 
|  | 1022 | +if (buf[i] == '1' || buf[i] == '0') { | 
|  | 1023 | +tmp = tmp * 2 + (int)(buf[i]-'0'); | 
|  | 1024 | +} else if (buf[i] != ' ') { | 
|  | 1025 | +break; | 
|  | 1026 | +} | 
|  | 1027 | +} | 
|  | 1028 | + | 
|  | 1029 | +ctl_waitsignal(task, tmp); | 
|  | 1030 | +} | 
|  | 1031 | + | 
|  | 1032 | +return count; | 
|  | 1033 | +} | 
|  | 1034 | + | 
|  | 1035 | +static const struct file_operations proc_ctl_operations = { | 
|  | 1036 | +.write= ctl_write, | 
|  | 1037 | +}; | 
|  | 1038 | + | 
| 969 | 1039 | static ssize_t environ_read(struct file *file, char __user *buf, | 
| 970 | 1040 | size_t count, loff_t *ppos) | 
| 971 | 1041 | { | 
| @@ -2813,6 +2883,7 @@ static const struct pid_entry tgid_base_stuff[] = { | 
| 2813 | 2883 | REG("numa_maps", S_IRUGO, proc_numa_maps_operations), | 
| 2814 | 2884 | #endif | 
| 2815 | 2885 | REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations), | 
|  | 2886 | +REG("ctl", S_IWUSR, proc_ctl_operations), | 
| 2816 | 2887 | LNK("cwd", proc_cwd_link), | 
| 2817 | 2888 | LNK("root", proc_root_link), | 
| 2818 | 2889 | LNK("exe", proc_exe_link), | 
|  | 
0 commit comments