]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/proccontrol/proccontrol.c
bluetooth: Fix a mandoc related issues
[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         MODE_PROTMAX,
47         MODE_STACKGAP,
48 #ifdef PROC_KPTI_CTL
49         MODE_KPTI,
50 #endif
51 #ifdef PROC_LA_CTL
52         MODE_LA57,
53         MODE_LA48,
54 #endif
55 };
56
57 static pid_t
58 str2pid(const char *str)
59 {
60         pid_t res;
61         char *tail;
62
63         res = strtol(str, &tail, 0);
64         if (*tail != '\0') {
65                 warnx("non-numeric pid");
66                 return (-1);
67         }
68         return (res);
69 }
70
71 #ifdef PROC_KPTI_CTL
72 #define KPTI_USAGE "|kpti"
73 #else
74 #define KPTI_USAGE
75 #endif
76 #ifdef PROC_LA_CTL
77 #define LA_USAGE "|la48|la57"
78 #else
79 #define LA_USAGE
80 #endif
81
82 static void __dead2
83 usage(void)
84 {
85
86         fprintf(stderr, "Usage: proccontrol -m (aslr|protmax|trace|trapcap|"
87             "stackgap"KPTI_USAGE LA_USAGE") [-q] "
88             "[-s (enable|disable)] [-p pid | command]\n");
89         exit(1);
90 }
91
92 int
93 main(int argc, char *argv[])
94 {
95         int arg, ch, error, mode;
96         pid_t pid;
97         bool enable, do_command, query;
98
99         mode = MODE_INVALID;
100         enable = true;
101         pid = -1;
102         query = false;
103         while ((ch = getopt(argc, argv, "m:qs:p:")) != -1) {
104                 switch (ch) {
105                 case 'm':
106                         if (strcmp(optarg, "aslr") == 0)
107                                 mode = MODE_ASLR;
108                         else if (strcmp(optarg, "protmax") == 0)
109                                 mode = MODE_PROTMAX;
110                         else if (strcmp(optarg, "trace") == 0)
111                                 mode = MODE_TRACE;
112                         else if (strcmp(optarg, "trapcap") == 0)
113                                 mode = MODE_TRAPCAP;
114                         else if (strcmp(optarg, "stackgap") == 0)
115                                 mode = MODE_STACKGAP;
116 #ifdef PROC_KPTI_CTL
117                         else if (strcmp(optarg, "kpti") == 0)
118                                 mode = MODE_KPTI;
119 #endif
120 #ifdef PROC_LA_CTL
121                         else if (strcmp(optarg, "la57") == 0)
122                                 mode = MODE_LA57;
123                         else if (strcmp(optarg, "la48") == 0)
124                                 mode = MODE_LA48;
125 #endif
126                         else
127                                 usage();
128                         break;
129                 case 's':
130                         if (strcmp(optarg, "enable") == 0)
131                                 enable = true;
132                         else if (strcmp(optarg, "disable") == 0)
133                                 enable = false;
134                         else
135                                 usage();
136                         break;
137                 case 'p':
138                         pid = str2pid(optarg);
139                         break;
140                 case 'q':
141                         query = true;
142                         break;
143                 case '?':
144                 default:
145                         usage();
146                         break;
147                 }
148         }
149         argc -= optind;
150         argv += optind;
151         do_command = argc != 0;
152         if (do_command) {
153                 if (pid != -1 || query)
154                         usage();
155                 pid = getpid();
156         } else if (pid == -1) {
157                 pid = getpid();
158         }
159
160         if (query) {
161                 switch (mode) {
162                 case MODE_ASLR:
163                         error = procctl(P_PID, pid, PROC_ASLR_STATUS, &arg);
164                         break;
165                 case MODE_TRACE:
166                         error = procctl(P_PID, pid, PROC_TRACE_STATUS, &arg);
167                         break;
168                 case MODE_TRAPCAP:
169                         error = procctl(P_PID, pid, PROC_TRAPCAP_STATUS, &arg);
170                         break;
171                 case MODE_PROTMAX:
172                         error = procctl(P_PID, pid, PROC_PROTMAX_STATUS, &arg);
173                         break;
174                 case MODE_STACKGAP:
175                         error = procctl(P_PID, pid, PROC_STACKGAP_STATUS, &arg);
176                         break;
177 #ifdef PROC_KPTI_CTL
178                 case MODE_KPTI:
179                         error = procctl(P_PID, pid, PROC_KPTI_STATUS, &arg);
180                         break;
181 #endif
182 #ifdef PROC_LA_CTL
183                 case MODE_LA57:
184                 case MODE_LA48:
185                         error = procctl(P_PID, pid, PROC_LA_STATUS, &arg);
186                         break;
187 #endif
188                 default:
189                         usage();
190                         break;
191                 }
192                 if (error != 0)
193                         err(1, "procctl status");
194                 switch (mode) {
195                 case MODE_ASLR:
196                         switch (arg & ~PROC_ASLR_ACTIVE) {
197                         case PROC_ASLR_FORCE_ENABLE:
198                                 printf("force enabled");
199                                 break;
200                         case PROC_ASLR_FORCE_DISABLE:
201                                 printf("force disabled");
202                                 break;
203                         case PROC_ASLR_NOFORCE:
204                                 printf("not forced");
205                                 break;
206                         }
207                         if ((arg & PROC_ASLR_ACTIVE) != 0)
208                                 printf(", active\n");
209                         else
210                                 printf(", not active\n");
211                         break;
212                 case MODE_TRACE:
213                         if (arg == -1)
214                                 printf("disabled\n");
215                         else if (arg == 0)
216                                 printf("enabled, no debugger\n");
217                         else
218                                 printf("enabled, traced by %d\n", arg);
219                         break;
220                 case MODE_TRAPCAP:
221                         switch (arg) {
222                         case PROC_TRAPCAP_CTL_ENABLE:
223                                 printf("enabled\n");
224                                 break;
225                         case PROC_TRAPCAP_CTL_DISABLE:
226                                 printf("disabled\n");
227                                 break;
228                         }
229                         break;
230                 case MODE_PROTMAX:
231                         switch (arg & ~PROC_PROTMAX_ACTIVE) {
232                         case PROC_PROTMAX_FORCE_ENABLE:
233                                 printf("force enabled");
234                                 break;
235                         case PROC_PROTMAX_FORCE_DISABLE:
236                                 printf("force disabled");
237                                 break;
238                         case PROC_PROTMAX_NOFORCE:
239                                 printf("not forced");
240                                 break;
241                         }
242                         if ((arg & PROC_PROTMAX_ACTIVE) != 0)
243                                 printf(", active\n");
244                         else
245                                 printf(", not active\n");
246                         break;
247                 case MODE_STACKGAP:
248                         switch (arg & (PROC_STACKGAP_ENABLE |
249                             PROC_STACKGAP_DISABLE)) {
250                         case PROC_STACKGAP_ENABLE:
251                                 printf("enabled\n");
252                                 break;
253                         case PROC_STACKGAP_DISABLE:
254                                 printf("disabled\n");
255                                 break;
256                         }
257                         switch (arg & (PROC_STACKGAP_ENABLE_EXEC |
258                             PROC_STACKGAP_DISABLE_EXEC)) {
259                         case PROC_STACKGAP_ENABLE_EXEC:
260                                 printf("enabled after exec\n");
261                                 break;
262                         case PROC_STACKGAP_DISABLE_EXEC:
263                                 printf("disabled after exec\n");
264                                 break;
265                         }
266                         break;
267 #ifdef PROC_KPTI_CTL
268                 case MODE_KPTI:
269                         switch (arg & ~PROC_KPTI_STATUS_ACTIVE) {
270                         case PROC_KPTI_CTL_ENABLE_ON_EXEC:
271                                 printf("enabled");
272                                 break;
273                         case PROC_KPTI_CTL_DISABLE_ON_EXEC:
274                                 printf("disabled");
275                                 break;
276                         }
277                         if ((arg & PROC_KPTI_STATUS_ACTIVE) != 0)
278                                 printf(", active\n");
279                         else
280                                 printf(", not active\n");
281                         break;
282 #endif
283 #ifdef PROC_LA_CTL
284                 case MODE_LA57:
285                 case MODE_LA48:
286                         switch (arg & ~(PROC_LA_STATUS_LA48 |
287                             PROC_LA_STATUS_LA57)) {
288                         case PROC_LA_CTL_LA48_ON_EXEC:
289                                 printf("la48 on exec");
290                                 break;
291                         case PROC_LA_CTL_LA57_ON_EXEC:
292                                 printf("la57 on exec");
293                                 break;
294                         case PROC_LA_CTL_DEFAULT_ON_EXEC:
295                                 printf("default on exec");
296                                 break;
297                         }
298                         if ((arg & PROC_LA_STATUS_LA48) != 0)
299                                 printf(", la48 active\n");
300                         else if ((arg & PROC_LA_STATUS_LA57) != 0)
301                                 printf(", la57 active\n");
302                         break;
303 #endif
304                 }
305         } else {
306                 switch (mode) {
307                 case MODE_ASLR:
308                         arg = enable ? PROC_ASLR_FORCE_ENABLE :
309                             PROC_ASLR_FORCE_DISABLE;
310                         error = procctl(P_PID, pid, PROC_ASLR_CTL, &arg);
311                         break;
312                 case MODE_TRACE:
313                         arg = enable ? PROC_TRACE_CTL_ENABLE :
314                             PROC_TRACE_CTL_DISABLE;
315                         error = procctl(P_PID, pid, PROC_TRACE_CTL, &arg);
316                         break;
317                 case MODE_TRAPCAP:
318                         arg = enable ? PROC_TRAPCAP_CTL_ENABLE :
319                             PROC_TRAPCAP_CTL_DISABLE;
320                         error = procctl(P_PID, pid, PROC_TRAPCAP_CTL, &arg);
321                         break;
322                 case MODE_PROTMAX:
323                         arg = enable ? PROC_PROTMAX_FORCE_ENABLE :
324                             PROC_PROTMAX_FORCE_DISABLE;
325                         error = procctl(P_PID, pid, PROC_PROTMAX_CTL, &arg);
326                         break;
327                 case MODE_STACKGAP:
328                         arg = enable ? PROC_STACKGAP_ENABLE_EXEC :
329                             (PROC_STACKGAP_DISABLE |
330                             PROC_STACKGAP_DISABLE_EXEC);
331                         error = procctl(P_PID, pid, PROC_STACKGAP_CTL, &arg);
332                         break;
333 #ifdef PROC_KPTI_CTL
334                 case MODE_KPTI:
335                         arg = enable ? PROC_KPTI_CTL_ENABLE_ON_EXEC :
336                             PROC_KPTI_CTL_DISABLE_ON_EXEC;
337                         error = procctl(P_PID, pid, PROC_KPTI_CTL, &arg);
338                         break;
339 #endif
340 #ifdef PROC_LA_CTL
341                 case MODE_LA57:
342                         arg = enable ? PROC_LA_CTL_LA57_ON_EXEC :
343                             PROC_LA_CTL_DEFAULT_ON_EXEC;
344                         error = procctl(P_PID, pid, PROC_LA_CTL, &arg);
345                         break;
346                 case MODE_LA48:
347                         arg = enable ? PROC_LA_CTL_LA48_ON_EXEC :
348                             PROC_LA_CTL_DEFAULT_ON_EXEC;
349                         error = procctl(P_PID, pid, PROC_LA_CTL, &arg);
350                         break;
351 #endif
352                 default:
353                         usage();
354                         break;
355                 }
356                 if (error != 0)
357                         err(1, "procctl ctl");
358                 if (do_command) {
359                         error = execvp(argv[0], argv);
360                         err(1, "exec");
361                 }
362         }
363         exit(0);
364 }