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