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