]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/proccontrol/proccontrol.c
Add two missing eventhandler.h headers
[FreeBSD/FreeBSD.git] / usr.bin / proccontrol / proccontrol.c
1 /*-
2  * Copyright (c) 2016 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
6  * under sponsorship from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/procctl.h>
34 #include <err.h>
35 #include <stdbool.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 enum {
42         MODE_ASLR,
43         MODE_INVALID,
44         MODE_TRACE,
45         MODE_TRAPCAP,
46 #ifdef PROC_KPTI_CTL
47         MODE_KPTI,
48 #endif
49 };
50
51 static pid_t
52 str2pid(const char *str)
53 {
54         pid_t res;
55         char *tail;
56
57         res = strtol(str, &tail, 0);
58         if (*tail != '\0') {
59                 warnx("non-numeric pid");
60                 return (-1);
61         }
62         return (res);
63 }
64
65 #ifdef PROC_KPTI_CTL
66 #define KPTI_USAGE "|kpti"
67 #else
68 #define KPTI_USAGE
69 #endif
70
71 static void __dead2
72 usage(void)
73 {
74
75         fprintf(stderr, "Usage: proccontrol -m (aslr|trace|trapcap"
76             KPTI_USAGE") [-q] "
77             "[-s (enable|disable)] [-p pid | command]\n");
78         exit(1);
79 }
80
81 int
82 main(int argc, char *argv[])
83 {
84         int arg, ch, error, mode;
85         pid_t pid;
86         bool enable, do_command, query;
87
88         mode = MODE_INVALID;
89         enable = true;
90         pid = -1;
91         query = false;
92         while ((ch = getopt(argc, argv, "m:qs:p:")) != -1) {
93                 switch (ch) {
94                 case 'm':
95                         if (strcmp(optarg, "aslr") == 0)
96                                 mode = MODE_ASLR;
97                         else if (strcmp(optarg, "trace") == 0)
98                                 mode = MODE_TRACE;
99                         else if (strcmp(optarg, "trapcap") == 0)
100                                 mode = MODE_TRAPCAP;
101 #ifdef PROC_KPTI_CTL
102                         else if (strcmp(optarg, "kpti") == 0)
103                                 mode = MODE_KPTI;
104 #endif
105                         else
106                                 usage();
107                         break;
108                 case 's':
109                         if (strcmp(optarg, "enable") == 0)
110                                 enable = true;
111                         else if (strcmp(optarg, "disable") == 0)
112                                 enable = false;
113                         else
114                                 usage();
115                         break;
116                 case 'p':
117                         pid = str2pid(optarg);
118                         break;
119                 case 'q':
120                         query = true;
121                         break;
122                 case '?':
123                 default:
124                         usage();
125                         break;
126                 }
127         }
128         argc -= optind;
129         argv += optind;
130         do_command = argc != 0;
131         if (do_command) {
132                 if (pid != -1 || query)
133                         usage();
134                 pid = getpid();
135         } else if (pid == -1) {
136                 pid = getpid();
137         }
138
139         if (query) {
140                 switch (mode) {
141                 case MODE_ASLR:
142                         error = procctl(P_PID, pid, PROC_ASLR_STATUS, &arg);
143                         break;
144                 case MODE_TRACE:
145                         error = procctl(P_PID, pid, PROC_TRACE_STATUS, &arg);
146                         break;
147                 case MODE_TRAPCAP:
148                         error = procctl(P_PID, pid, PROC_TRAPCAP_STATUS, &arg);
149                         break;
150 #ifdef PROC_KPTI_CTL
151                 case MODE_KPTI:
152                         error = procctl(P_PID, pid, PROC_KPTI_STATUS, &arg);
153                         break;
154 #endif
155                 default:
156                         usage();
157                         break;
158                 }
159                 if (error != 0)
160                         err(1, "procctl status");
161                 switch (mode) {
162                 case MODE_ASLR:
163                         switch (arg & ~PROC_ASLR_ACTIVE) {
164                         case PROC_ASLR_FORCE_ENABLE:
165                                 printf("force enabled");
166                                 break;
167                         case PROC_ASLR_FORCE_DISABLE:
168                                 printf("force disabled");
169                                 break;
170                         case PROC_ASLR_NOFORCE:
171                                 printf("not forced");
172                                 break;
173                         }
174                         if ((arg & PROC_ASLR_ACTIVE) != 0)
175                                 printf(", active\n");
176                         else
177                                 printf(", not active\n");
178                         break;
179                 case MODE_TRACE:
180                         if (arg == -1)
181                                 printf("disabled\n");
182                         else if (arg == 0)
183                                 printf("enabled, no debugger\n");
184                         else
185                                 printf("enabled, traced by %d\n", arg);
186                         break;
187                 case MODE_TRAPCAP:
188                         switch (arg) {
189                         case PROC_TRAPCAP_CTL_ENABLE:
190                                 printf("enabled\n");
191                                 break;
192                         case PROC_TRAPCAP_CTL_DISABLE:
193                                 printf("disabled\n");
194                                 break;
195                         }
196                         break;
197 #ifdef PROC_KPTI_CTL
198                 case MODE_KPTI:
199                         switch (arg & ~PROC_KPTI_STATUS_ACTIVE) {
200                         case PROC_KPTI_CTL_ENABLE_ON_EXEC:
201                                 printf("enabled");
202                                 break;
203                         case PROC_KPTI_CTL_DISABLE_ON_EXEC:
204                                 printf("disabled");
205                                 break;
206                         }
207                         if ((arg & PROC_KPTI_STATUS_ACTIVE) != 0)
208                                 printf(", active\n");
209                         else
210                                 printf(", not active\n");
211                         break;
212 #endif
213                 }
214         } else {
215                 switch (mode) {
216                 case MODE_ASLR:
217                         arg = enable ? PROC_ASLR_FORCE_ENABLE :
218                             PROC_ASLR_FORCE_DISABLE;
219                         error = procctl(P_PID, pid, PROC_ASLR_CTL, &arg);
220                         break;
221                 case MODE_TRACE:
222                         arg = enable ? PROC_TRACE_CTL_ENABLE :
223                             PROC_TRACE_CTL_DISABLE;
224                         error = procctl(P_PID, pid, PROC_TRACE_CTL, &arg);
225                         break;
226                 case MODE_TRAPCAP:
227                         arg = enable ? PROC_TRAPCAP_CTL_ENABLE :
228                             PROC_TRAPCAP_CTL_DISABLE;
229                         error = procctl(P_PID, pid, PROC_TRAPCAP_CTL, &arg);
230                         break;
231 #ifdef PROC_KPTI_CTL
232                 case MODE_KPTI:
233                         arg = enable ? PROC_KPTI_CTL_ENABLE_ON_EXEC :
234                             PROC_KPTI_CTL_DISABLE_ON_EXEC;
235                         error = procctl(P_PID, pid, PROC_KPTI_CTL, &arg);
236                         break;
237 #endif
238                 default:
239                         usage();
240                         break;
241                 }
242                 if (error != 0)
243                         err(1, "procctl ctl");
244                 if (do_command) {
245                         error = execvp(argv[0], argv);
246                         err(1, "exec");
247                 }
248         }
249         exit(0);
250 }