1255708Sjhb/*-
2255708Sjhb * Copyright (c) 2013 Advanced Computing Technologies LLC
3255708Sjhb * Written by: John H. Baldwin <jhb@FreeBSD.org>
4255708Sjhb * All rights reserved.
5255708Sjhb *
6255708Sjhb * Redistribution and use in source and binary forms, with or without
7255708Sjhb * modification, are permitted provided that the following conditions
8255708Sjhb * are met:
9255708Sjhb * 1. Redistributions of source code must retain the above copyright
10255708Sjhb *    notice, this list of conditions and the following disclaimer.
11255708Sjhb * 2. Redistributions in binary form must reproduce the above copyright
12255708Sjhb *    notice, this list of conditions and the following disclaimer in the
13255708Sjhb *    documentation and/or other materials provided with the distribution.
14255708Sjhb *
15255708Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16255708Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17255708Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18255708Sjhb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19255708Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20255708Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21255708Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22255708Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23255708Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24255708Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25255708Sjhb * SUCH DAMAGE.
26255708Sjhb */
27255708Sjhb
28255708Sjhb#include <sys/cdefs.h>
29255708Sjhb__FBSDID("$FreeBSD$");
30255708Sjhb
31255708Sjhb#include <sys/procctl.h>
32255708Sjhb#include <sys/types.h>
33255708Sjhb#include <sys/mman.h>
34255708Sjhb#include <err.h>
35255708Sjhb#include <errno.h>
36255708Sjhb#include <stdbool.h>
37255708Sjhb#include <stdio.h>
38255708Sjhb#include <stdlib.h>
39255708Sjhb#include <unistd.h>
40255708Sjhb
41255708Sjhbstatic void
42255708Sjhbusage(void)
43255708Sjhb{
44255708Sjhb
45255708Sjhb	fprintf(stderr, "usage: protect [-i] command\n");
46255708Sjhb	fprintf(stderr, "       protect [-cdi] -g pgrp | -p pid\n");
47255708Sjhb	exit(1);
48255708Sjhb}
49255708Sjhb
50255708Sjhbstatic id_t
51255708Sjhbparse_id(char *id)
52255708Sjhb{
53255708Sjhb	static bool first = true;
54255708Sjhb	long value;
55255708Sjhb	char *ch;
56255708Sjhb
57255708Sjhb	if (!first) {
58255708Sjhb		warnx("only one -g or -p flag is permitted");
59255708Sjhb		usage();
60255708Sjhb	}
61255708Sjhb	value = strtol(id, &ch, 0);
62255708Sjhb	if (*ch != '\0') {
63255708Sjhb		warnx("invalid process id");
64255708Sjhb		usage();
65255708Sjhb	}
66255708Sjhb	return (value);
67255708Sjhb}
68255708Sjhb
69255708Sjhbint
70255708Sjhbmain(int argc, char *argv[])
71255708Sjhb{
72255708Sjhb	idtype_t idtype;
73255708Sjhb	id_t id;
74255708Sjhb	int ch, flags;
75255708Sjhb	bool descend, inherit, idset;
76255708Sjhb
77255708Sjhb	idtype = P_PID;
78255708Sjhb	id = getpid();
79255708Sjhb	flags = PPROT_SET;
80255708Sjhb	descend = inherit = idset = false;
81255708Sjhb	while ((ch = getopt(argc, argv, "cdig:p:")) != -1)
82255708Sjhb		switch (ch) {
83255708Sjhb		case 'c':
84255708Sjhb			flags = PPROT_CLEAR;
85255708Sjhb			break;
86255708Sjhb		case 'd':
87255708Sjhb			descend = true;
88255708Sjhb			break;
89255708Sjhb		case 'i':
90255708Sjhb			inherit = true;
91255708Sjhb			break;
92255708Sjhb		case 'g':
93255708Sjhb			idtype = P_PGID;
94255708Sjhb			id = parse_id(optarg);
95255708Sjhb			idset = true;
96255708Sjhb			break;
97255708Sjhb		case 'p':
98255708Sjhb			idtype = P_PID;
99255708Sjhb			id = parse_id(optarg);
100255708Sjhb			idset = true;
101255708Sjhb			break;
102255708Sjhb		}
103255708Sjhb	argc -= optind;
104255708Sjhb	argv += optind;
105255708Sjhb
106255708Sjhb	if ((idset && argc != 0) || (!idset && (argc == 0 || descend)))
107255708Sjhb		usage();
108255708Sjhb
109255708Sjhb	if (descend)
110255708Sjhb		flags |= PPROT_DESCEND;
111255708Sjhb	if (inherit)
112255708Sjhb		flags |= PPROT_INHERIT;
113255708Sjhb	if (procctl(idtype, id, PROC_SPROTECT, &flags) == -1)
114255708Sjhb		err(1, "procctl");
115255708Sjhb
116255708Sjhb	if (argc != 0) {
117255708Sjhb		errno = 0;
118255708Sjhb		execvp(*argv, argv);
119255708Sjhb		err(errno == ENOENT ? 127 : 126, "%s", *argv);
120255708Sjhb	}
121255708Sjhb	return (0);
122255708Sjhb}
123