2 * Copyright (c) 2016 The FreeBSD Foundation
4 * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
5 * under sponsorship from the FreeBSD Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/param.h>
30 #include <sys/procctl.h>
60 { MODE_ASLR
, "aslr" },
61 { MODE_TRACE
, "trace" },
62 { MODE_TRAPCAP
, "trapcap" },
63 { MODE_PROTMAX
, "protmax" },
64 { MODE_STACKGAP
, "stackgap" },
65 { MODE_NO_NEW_PRIVS
, "nonewprivs" },
66 { MODE_WXMAP
, "wxmap" },
68 { MODE_KPTI
, "kpti" },
71 { MODE_LA57
, "la57" },
72 { MODE_LA48
, "la48" },
77 str2pid(const char *str
)
82 res
= strtol(str
, &tail
, 0);
84 warnx("non-numeric pid");
93 fprintf(stderr
, "Usage:\n");
94 fprintf(stderr
, " proccontrol -m mode -s (enable|disable) "
95 "(-p pid | command)\n");
96 fprintf(stderr
, " proccontrol -m mode -q [-p pid]\n");
97 fprintf(stderr
, "Modes: ");
98 for (size_t i
= 0; i
< nitems(modes
); i
++)
99 fprintf(stderr
, "%s%s", i
== 0 ? "" : "|", modes
[i
].name
);
100 fprintf(stderr
, "\n");
105 main(int argc
, char *argv
[])
107 int arg
, ch
, error
, mode
;
109 bool enable
, do_command
, query
;
115 while ((ch
= getopt(argc
, argv
, "m:qs:p:")) != -1) {
118 if (mode
!= MODE_INVALID
)
120 for (size_t i
= 0; i
< nitems(modes
); i
++) {
121 if (strcmp(optarg
, modes
[i
].name
) == 0) {
122 mode
= modes
[i
].mode
;
126 if (mode
== MODE_INVALID
)
130 if (strcmp(optarg
, "enable") == 0)
132 else if (strcmp(optarg
, "disable") == 0)
138 pid
= str2pid(optarg
);
151 do_command
= argc
!= 0;
153 if (pid
!= -1 || query
)
156 } else if (pid
== -1) {
165 error
= procctl(P_PID
, pid
, PROC_ASLR_STATUS
, &arg
);
168 error
= procctl(P_PID
, pid
, PROC_TRACE_STATUS
, &arg
);
171 error
= procctl(P_PID
, pid
, PROC_TRAPCAP_STATUS
, &arg
);
174 error
= procctl(P_PID
, pid
, PROC_PROTMAX_STATUS
, &arg
);
177 error
= procctl(P_PID
, pid
, PROC_STACKGAP_STATUS
, &arg
);
179 case MODE_NO_NEW_PRIVS
:
180 error
= procctl(P_PID
, pid
, PROC_NO_NEW_PRIVS_STATUS
,
184 error
= procctl(P_PID
, pid
, PROC_WXMAP_STATUS
, &arg
);
188 error
= procctl(P_PID
, pid
, PROC_KPTI_STATUS
, &arg
);
194 error
= procctl(P_PID
, pid
, PROC_LA_STATUS
, &arg
);
202 err(1, "procctl status");
205 switch (arg
& ~PROC_ASLR_ACTIVE
) {
206 case PROC_ASLR_FORCE_ENABLE
:
207 printf("force enabled");
209 case PROC_ASLR_FORCE_DISABLE
:
210 printf("force disabled");
212 case PROC_ASLR_NOFORCE
:
213 printf("not forced");
216 if ((arg
& PROC_ASLR_ACTIVE
) != 0)
217 printf(", active\n");
219 printf(", not active\n");
223 printf("disabled\n");
225 printf("enabled, no debugger\n");
227 printf("enabled, traced by %d\n", arg
);
231 case PROC_TRAPCAP_CTL_ENABLE
:
234 case PROC_TRAPCAP_CTL_DISABLE
:
235 printf("disabled\n");
240 switch (arg
& ~PROC_PROTMAX_ACTIVE
) {
241 case PROC_PROTMAX_FORCE_ENABLE
:
242 printf("force enabled");
244 case PROC_PROTMAX_FORCE_DISABLE
:
245 printf("force disabled");
247 case PROC_PROTMAX_NOFORCE
:
248 printf("not forced");
251 if ((arg
& PROC_PROTMAX_ACTIVE
) != 0)
252 printf(", active\n");
254 printf(", not active\n");
257 switch (arg
& (PROC_STACKGAP_ENABLE
|
258 PROC_STACKGAP_DISABLE
)) {
259 case PROC_STACKGAP_ENABLE
:
262 case PROC_STACKGAP_DISABLE
:
263 printf("disabled\n");
266 switch (arg
& (PROC_STACKGAP_ENABLE_EXEC
|
267 PROC_STACKGAP_DISABLE_EXEC
)) {
268 case PROC_STACKGAP_ENABLE_EXEC
:
269 printf("enabled after exec\n");
271 case PROC_STACKGAP_DISABLE_EXEC
:
272 printf("disabled after exec\n");
276 case MODE_NO_NEW_PRIVS
:
278 case PROC_NO_NEW_PRIVS_ENABLE
:
281 case PROC_NO_NEW_PRIVS_DISABLE
:
282 printf("disabled\n");
287 if ((arg
& PROC_WX_MAPPINGS_PERMIT
) != 0)
291 if ((arg
& PROC_WX_MAPPINGS_DISALLOW_EXEC
) != 0)
292 printf(", disabled on exec");
293 if ((arg
& PROC_WXORX_ENFORCE
) != 0)
294 printf(", wxorx enforced");
299 switch (arg
& ~PROC_KPTI_STATUS_ACTIVE
) {
300 case PROC_KPTI_CTL_ENABLE_ON_EXEC
:
303 case PROC_KPTI_CTL_DISABLE_ON_EXEC
:
307 if ((arg
& PROC_KPTI_STATUS_ACTIVE
) != 0)
308 printf(", active\n");
310 printf(", not active\n");
316 switch (arg
& ~(PROC_LA_STATUS_LA48
|
317 PROC_LA_STATUS_LA57
)) {
318 case PROC_LA_CTL_LA48_ON_EXEC
:
319 printf("la48 on exec");
321 case PROC_LA_CTL_LA57_ON_EXEC
:
322 printf("la57 on exec");
324 case PROC_LA_CTL_DEFAULT_ON_EXEC
:
325 printf("default on exec");
328 if ((arg
& PROC_LA_STATUS_LA48
) != 0)
329 printf(", la48 active\n");
330 else if ((arg
& PROC_LA_STATUS_LA57
) != 0)
331 printf(", la57 active\n");
338 arg
= enable
? PROC_ASLR_FORCE_ENABLE
:
339 PROC_ASLR_FORCE_DISABLE
;
340 error
= procctl(P_PID
, pid
, PROC_ASLR_CTL
, &arg
);
343 arg
= enable
? PROC_TRACE_CTL_ENABLE
:
344 PROC_TRACE_CTL_DISABLE
;
345 error
= procctl(P_PID
, pid
, PROC_TRACE_CTL
, &arg
);
348 arg
= enable
? PROC_TRAPCAP_CTL_ENABLE
:
349 PROC_TRAPCAP_CTL_DISABLE
;
350 error
= procctl(P_PID
, pid
, PROC_TRAPCAP_CTL
, &arg
);
353 arg
= enable
? PROC_PROTMAX_FORCE_ENABLE
:
354 PROC_PROTMAX_FORCE_DISABLE
;
355 error
= procctl(P_PID
, pid
, PROC_PROTMAX_CTL
, &arg
);
358 arg
= enable
? PROC_STACKGAP_ENABLE_EXEC
:
359 (PROC_STACKGAP_DISABLE
|
360 PROC_STACKGAP_DISABLE_EXEC
);
361 error
= procctl(P_PID
, pid
, PROC_STACKGAP_CTL
, &arg
);
363 case MODE_NO_NEW_PRIVS
:
364 arg
= enable
? PROC_NO_NEW_PRIVS_ENABLE
:
365 PROC_NO_NEW_PRIVS_DISABLE
;
366 error
= procctl(P_PID
, pid
, PROC_NO_NEW_PRIVS_CTL
,
370 arg
= enable
? PROC_WX_MAPPINGS_PERMIT
:
371 PROC_WX_MAPPINGS_DISALLOW_EXEC
;
372 error
= procctl(P_PID
, pid
, PROC_WXMAP_CTL
, &arg
);
376 arg
= enable
? PROC_KPTI_CTL_ENABLE_ON_EXEC
:
377 PROC_KPTI_CTL_DISABLE_ON_EXEC
;
378 error
= procctl(P_PID
, pid
, PROC_KPTI_CTL
, &arg
);
383 arg
= enable
? PROC_LA_CTL_LA57_ON_EXEC
:
384 PROC_LA_CTL_DEFAULT_ON_EXEC
;
385 error
= procctl(P_PID
, pid
, PROC_LA_CTL
, &arg
);
388 arg
= enable
? PROC_LA_CTL_LA48_ON_EXEC
:
389 PROC_LA_CTL_DEFAULT_ON_EXEC
;
390 error
= procctl(P_PID
, pid
, PROC_LA_CTL
, &arg
);
398 err(1, "procctl ctl");
400 error
= execvp(argv
[0], argv
);