1d2a70789SRichard Lowe /*
2d2a70789SRichard Lowe  * This file and its contents are supplied under the terms of the
3d2a70789SRichard Lowe  * Common Development and Distribution License ("CDDL"), version 1.0.
4d2a70789SRichard Lowe  * You may only use this file in accordance with the terms of version
5d2a70789SRichard Lowe  * 1.0 of the CDDL.
6d2a70789SRichard Lowe  *
7d2a70789SRichard Lowe  * A full copy of the text of the CDDL should have accompanied this
8d2a70789SRichard Lowe  * source.  A copy of the CDDL is also available via the Internet at
9d2a70789SRichard Lowe  * http://www.illumos.org/license/CDDL.
10d2a70789SRichard Lowe  */
11d2a70789SRichard Lowe 
12d2a70789SRichard Lowe /* Copyright 2015, Richard Lowe. */
13d2a70789SRichard Lowe 
14d2a70789SRichard Lowe #include <err.h>
15d2a70789SRichard Lowe #include <errno.h>
16d2a70789SRichard Lowe #include <grp.h>
17d2a70789SRichard Lowe #include <libintl.h>
18d2a70789SRichard Lowe #include <procfs.h>
19d2a70789SRichard Lowe #include <project.h>
20d2a70789SRichard Lowe #include <pwd.h>
21d2a70789SRichard Lowe #include <stdio.h>
22d2a70789SRichard Lowe #include <stdlib.h>
23d2a70789SRichard Lowe #include <string.h>
24d2a70789SRichard Lowe #include <sys/secflags.h>
25d2a70789SRichard Lowe #include <sys/types.h>
26d2a70789SRichard Lowe 
27d2a70789SRichard Lowe #include <libproc.h>
28d2a70789SRichard Lowe #include <libzonecfg.h>
29d2a70789SRichard Lowe 
30d2a70789SRichard Lowe extern const char *__progname;
31d2a70789SRichard Lowe 
32d2a70789SRichard Lowe static void
print_flags(const char * set,secflagset_t flags)33d2a70789SRichard Lowe print_flags(const char *set, secflagset_t flags)
34d2a70789SRichard Lowe {
35d2a70789SRichard Lowe 	char buf[1024];
36d2a70789SRichard Lowe 
37d2a70789SRichard Lowe 	secflags_to_str(flags, buf, sizeof (buf));
38d2a70789SRichard Lowe 	(void) printf("\t%s:\t%s\n", set, buf);
39d2a70789SRichard Lowe }
40d2a70789SRichard Lowe 
41d2a70789SRichard Lowe /*
42d2a70789SRichard Lowe  * Structure defining idtypes known to the priocntl command
43d2a70789SRichard Lowe  * along with the corresponding names.
44d2a70789SRichard Lowe  * The idtype values themselves are defined in <sys/procset.h>.
45d2a70789SRichard Lowe  */
46d2a70789SRichard Lowe static struct idtypes {
47d2a70789SRichard Lowe 	idtype_t	type;
48d2a70789SRichard Lowe 	char		*name;
49d2a70789SRichard Lowe } idtypes [] = {
50d2a70789SRichard Lowe 	{ P_ALL,	"all"		},
51d2a70789SRichard Lowe 	{ P_CTID,	"contract"	},
52d2a70789SRichard Lowe 	{ P_CTID,	"ctid"		},
53d2a70789SRichard Lowe 	{ P_GID,	"gid"		},
54d2a70789SRichard Lowe 	{ P_GID,	"group"		},
55d2a70789SRichard Lowe 	{ P_PGID,	"pgid"		},
56d2a70789SRichard Lowe 	{ P_PID,	"pid"		},
57d2a70789SRichard Lowe 	{ P_PPID,	"ppid"		},
58d2a70789SRichard Lowe 	{ P_PROJID,	"project"	},
59d2a70789SRichard Lowe 	{ P_PROJID,	"projid"	},
60d2a70789SRichard Lowe 	{ P_SID,	"session",	},
61d2a70789SRichard Lowe 	{ P_SID,	"sid"		},
62d2a70789SRichard Lowe 	{ P_SID,	"sid"		},
63d2a70789SRichard Lowe 	{ P_TASKID,	"taskid"	},
64d2a70789SRichard Lowe 	{ P_UID,	"uid"		},
65d2a70789SRichard Lowe 	{ P_UID,	"user"		},
66d2a70789SRichard Lowe 	{ P_ZONEID,	"zone"		},
67d2a70789SRichard Lowe 	{ P_ZONEID,	"zoneid"	},
68*6b1325cfSRobert Mustacchi 	{ 0,		NULL		}
69d2a70789SRichard Lowe };
70d2a70789SRichard Lowe 
71d2a70789SRichard Lowe static int
str2idtype(char * idtypnm,idtype_t * idtypep)72d2a70789SRichard Lowe str2idtype(char *idtypnm, idtype_t *idtypep)
73d2a70789SRichard Lowe {
74d2a70789SRichard Lowe 	struct idtypes	*curp;
75d2a70789SRichard Lowe 
76d2a70789SRichard Lowe 	for (curp = idtypes; curp->name != NULL; curp++) {
77d2a70789SRichard Lowe 		if (strncasecmp(curp->name, idtypnm,
78d2a70789SRichard Lowe 		    strlen(curp->name)) == 0) {
79d2a70789SRichard Lowe 			*idtypep = curp->type;
80d2a70789SRichard Lowe 			return (0);
81d2a70789SRichard Lowe 		}
82d2a70789SRichard Lowe 	}
83d2a70789SRichard Lowe 	return (-1);
84d2a70789SRichard Lowe }
85d2a70789SRichard Lowe 
86d2a70789SRichard Lowe static id_t
getid(idtype_t type,char * value)87d2a70789SRichard Lowe getid(idtype_t type, char *value)
88d2a70789SRichard Lowe {
89d2a70789SRichard Lowe 	struct passwd *pwd;
90d2a70789SRichard Lowe 	struct group *grp;
91d2a70789SRichard Lowe 	id_t ret;
92d2a70789SRichard Lowe 	char *endp;
93d2a70789SRichard Lowe 
94d2a70789SRichard Lowe 	switch (type) {
95d2a70789SRichard Lowe 	case P_UID:
96d2a70789SRichard Lowe 		if ((pwd = getpwnam(value)) != NULL)
97d2a70789SRichard Lowe 			return (pwd->pw_uid);
98d2a70789SRichard Lowe 		break;
99d2a70789SRichard Lowe 	case P_GID:
100d2a70789SRichard Lowe 		if ((grp = getgrnam(value)) != NULL)
101d2a70789SRichard Lowe 			return (grp->gr_gid);
102d2a70789SRichard Lowe 		break;
103d2a70789SRichard Lowe 	case P_PROJID:
104d2a70789SRichard Lowe 		if ((ret = getprojidbyname(value)) != (id_t)-1)
105d2a70789SRichard Lowe 			return (ret);
106d2a70789SRichard Lowe 		break;
107d2a70789SRichard Lowe 	case P_ZONEID:
108d2a70789SRichard Lowe 		if (zone_get_id(value, &ret) == 0)
109d2a70789SRichard Lowe 			return (ret);
110d2a70789SRichard Lowe 		break;
111d2a70789SRichard Lowe 	default:
112d2a70789SRichard Lowe 		break;
113d2a70789SRichard Lowe 	}
114d2a70789SRichard Lowe 
115d2a70789SRichard Lowe 	errno = 0;
116d2a70789SRichard Lowe 
117d2a70789SRichard Lowe 	ret = (id_t)strtoul(value, &endp, 10);
118d2a70789SRichard Lowe 
119d2a70789SRichard Lowe 	if ((errno != 0) || (*endp != '\0'))
120d2a70789SRichard Lowe 		return ((id_t)-1);
121d2a70789SRichard Lowe 
122d2a70789SRichard Lowe 	return (ret);
123d2a70789SRichard Lowe }
124d2a70789SRichard Lowe 
125d2a70789SRichard Lowe int
main(int argc,char ** argv)126d2a70789SRichard Lowe main(int argc, char **argv)
127d2a70789SRichard Lowe {
128d2a70789SRichard Lowe 	secflagdelta_t act;
129d2a70789SRichard Lowe 	psecflagwhich_t which = PSF_INHERIT;
130d2a70789SRichard Lowe 	int ret = 0;
131d2a70789SRichard Lowe 	int pgrab_flags = PGRAB_RDONLY;
132d2a70789SRichard Lowe 	int opt;
133d2a70789SRichard Lowe 	char *idtypename = NULL;
134d2a70789SRichard Lowe 	idtype_t idtype = P_PID;
135d2a70789SRichard Lowe 	boolean_t usage = B_FALSE;
136d2a70789SRichard Lowe 	boolean_t e_flag = B_FALSE;
137d2a70789SRichard Lowe 	boolean_t l_flag = B_FALSE;
138d2a70789SRichard Lowe 	boolean_t s_flag = B_FALSE;
139d2a70789SRichard Lowe 	int errc = 0;
140d2a70789SRichard Lowe 
141d2a70789SRichard Lowe 	while ((opt = getopt(argc, argv, "eFi:ls:")) != -1) {
142d2a70789SRichard Lowe 		switch (opt) {
143d2a70789SRichard Lowe 		case 'e':
144d2a70789SRichard Lowe 			e_flag = B_TRUE;
145d2a70789SRichard Lowe 			break;
146d2a70789SRichard Lowe 		case 'F':
147d2a70789SRichard Lowe 			pgrab_flags |= PGRAB_FORCE;
148d2a70789SRichard Lowe 			break;
149d2a70789SRichard Lowe 		case 'i':
150d2a70789SRichard Lowe 			idtypename = optarg;
151d2a70789SRichard Lowe 			break;
152d2a70789SRichard Lowe 		case 's':
153d2a70789SRichard Lowe 			s_flag = B_TRUE;
154d2a70789SRichard Lowe 			if ((strlen(optarg) >= 2) &&
155d2a70789SRichard Lowe 			    ((optarg[1] == '='))) {
156d2a70789SRichard Lowe 				switch (optarg[0]) {
157d2a70789SRichard Lowe 				case 'L':
158d2a70789SRichard Lowe 					which = PSF_LOWER;
159d2a70789SRichard Lowe 					break;
160d2a70789SRichard Lowe 				case 'U':
161d2a70789SRichard Lowe 					which = PSF_UPPER;
162d2a70789SRichard Lowe 					break;
163d2a70789SRichard Lowe 				case 'I':
164d2a70789SRichard Lowe 					which = PSF_INHERIT;
165d2a70789SRichard Lowe 					break;
166d2a70789SRichard Lowe 				case 'E':
167d2a70789SRichard Lowe 					errx(1, "the effective flags cannot "
168*6b1325cfSRobert Mustacchi 					    "be changed");
169d2a70789SRichard Lowe 				default:
170d2a70789SRichard Lowe 					errx(1, "unknown security flag "
171d2a70789SRichard Lowe 					    "set: '%c'", optarg[0]);
172d2a70789SRichard Lowe 				}
173d2a70789SRichard Lowe 
174d2a70789SRichard Lowe 				optarg += 2;
175d2a70789SRichard Lowe 			}
176d2a70789SRichard Lowe 
177d2a70789SRichard Lowe 			if (secflags_parse(NULL, optarg, &act) == -1)
178d2a70789SRichard Lowe 				errx(1, "couldn't parse security flags: %s",
179d2a70789SRichard Lowe 				    optarg);
180d2a70789SRichard Lowe 			break;
181d2a70789SRichard Lowe 		case 'l':
182d2a70789SRichard Lowe 			l_flag = B_TRUE;
183d2a70789SRichard Lowe 			break;
184d2a70789SRichard Lowe 		default:
185d2a70789SRichard Lowe 			usage = B_TRUE;
186d2a70789SRichard Lowe 			break;
187d2a70789SRichard Lowe 		}
188d2a70789SRichard Lowe 	}
189d2a70789SRichard Lowe 
190d2a70789SRichard Lowe 	argc -= optind;
191d2a70789SRichard Lowe 	argv += optind;
192d2a70789SRichard Lowe 
193d2a70789SRichard Lowe 	if (l_flag && ((idtypename != NULL) || s_flag || (argc != 0)))
194d2a70789SRichard Lowe 		usage = B_TRUE;
195d2a70789SRichard Lowe 	if ((idtypename != NULL) && !s_flag)
196d2a70789SRichard Lowe 		usage = B_TRUE;
197d2a70789SRichard Lowe 	if (e_flag && !s_flag)
198d2a70789SRichard Lowe 		usage = B_TRUE;
199d2a70789SRichard Lowe 	if (!l_flag && argc <= 0)
200d2a70789SRichard Lowe 		usage = B_TRUE;
201d2a70789SRichard Lowe 
202d2a70789SRichard Lowe 	if (usage) {
203d2a70789SRichard Lowe 		(void) fprintf(stderr,
204d2a70789SRichard Lowe 		    gettext("usage:\t%s [-F] { pid | core } ...\n"),
205d2a70789SRichard Lowe 		    __progname);
206d2a70789SRichard Lowe 		(void) fprintf(stderr,
207d2a70789SRichard Lowe 		    gettext("\t%s -s spec [-i idtype] id ...\n"),
208d2a70789SRichard Lowe 		    __progname);
209d2a70789SRichard Lowe 		(void) fprintf(stderr,
210d2a70789SRichard Lowe 		    gettext("\t%s -s spec -e command [arg]...\n"),
211d2a70789SRichard Lowe 		    __progname);
212d2a70789SRichard Lowe 		(void) fprintf(stderr, gettext("\t%s -l\n"), __progname);
213d2a70789SRichard Lowe 		return (2);
214d2a70789SRichard Lowe 	}
215d2a70789SRichard Lowe 
216d2a70789SRichard Lowe 	if (l_flag) {
217d2a70789SRichard Lowe 		secflag_t i;
218d2a70789SRichard Lowe 		const char *name;
219d2a70789SRichard Lowe 
220d2a70789SRichard Lowe 		for (i = 0; (name = secflag_to_str(i)) != NULL; i++)
221d2a70789SRichard Lowe 			(void) printf("%s\n", name);
222d2a70789SRichard Lowe 		return (0);
223d2a70789SRichard Lowe 	} else if (s_flag && e_flag) {
224d2a70789SRichard Lowe 		/*
225d2a70789SRichard Lowe 		 * Don't use the strerror() message for EPERM, "Not Owner"
226d2a70789SRichard Lowe 		 * which is misleading.
227d2a70789SRichard Lowe 		 */
228d2a70789SRichard Lowe 		errc = psecflags(P_PID, P_MYID, which, &act);
229d2a70789SRichard Lowe 		switch (errc) {
230d2a70789SRichard Lowe 		case 0:
231d2a70789SRichard Lowe 			break;
232d2a70789SRichard Lowe 		case EPERM:
233d2a70789SRichard Lowe 			errx(1, gettext("failed setting "
234d2a70789SRichard Lowe 			    "security-flags: Permission denied"));
235d2a70789SRichard Lowe 			break;
236d2a70789SRichard Lowe 		default:
237d2a70789SRichard Lowe 			err(1, gettext("failed setting security-flags"));
238d2a70789SRichard Lowe 		}
239d2a70789SRichard Lowe 
240d2a70789SRichard Lowe 		(void) execvp(argv[0], &argv[0]);
241d2a70789SRichard Lowe 		err(1, "%s", argv[0]);
242d2a70789SRichard Lowe 	} else if (s_flag) {
243d2a70789SRichard Lowe 		int i;
244d2a70789SRichard Lowe 		id_t id;
245d2a70789SRichard Lowe 
246d2a70789SRichard Lowe 		if (idtypename != NULL)
247d2a70789SRichard Lowe 			if (str2idtype(idtypename, &idtype) == -1)
248d2a70789SRichard Lowe 				errx(1, gettext("No such id type: '%s'"),
249d2a70789SRichard Lowe 				    idtypename);
250d2a70789SRichard Lowe 
251d2a70789SRichard Lowe 		for (i = 0; i < argc; i++) {
252d2a70789SRichard Lowe 			if ((id = getid(idtype, argv[i])) == (id_t)-1) {
253d2a70789SRichard Lowe 				errx(1, gettext("invalid or non-existent "
254d2a70789SRichard Lowe 				    "identifier: '%s'"), argv[i]);
255d2a70789SRichard Lowe 			}
256d2a70789SRichard Lowe 
257d2a70789SRichard Lowe 			/*
258d2a70789SRichard Lowe 			 * Don't use the strerror() message for EPERM, "Not
259d2a70789SRichard Lowe 			 * Owner" which is misleading.
260d2a70789SRichard Lowe 			 */
261d2a70789SRichard Lowe 			if (psecflags(idtype, id, which, &act) != 0) {
262d2a70789SRichard Lowe 				switch (errno) {
263d2a70789SRichard Lowe 				case EPERM:
264d2a70789SRichard Lowe 					errx(1, gettext("failed setting "
265d2a70789SRichard Lowe 					    "security-flags: "
266d2a70789SRichard Lowe 					    "Permission denied"));
267d2a70789SRichard Lowe 					break;
268d2a70789SRichard Lowe 				default:
269d2a70789SRichard Lowe 					err(1, gettext("failed setting "
270d2a70789SRichard Lowe 					    "security-flags"));
271d2a70789SRichard Lowe 				}
272d2a70789SRichard Lowe 			}
273d2a70789SRichard Lowe 		}
274d2a70789SRichard Lowe 
275d2a70789SRichard Lowe 		return (0);
276d2a70789SRichard Lowe 	}
277d2a70789SRichard Lowe 
278d2a70789SRichard Lowe 	/* Display the flags for the given pids */
279d2a70789SRichard Lowe 	while (argc-- > 0) {
280d2a70789SRichard Lowe 		struct ps_prochandle *Pr;
281d2a70789SRichard Lowe 		const char *arg;
282d2a70789SRichard Lowe 		psinfo_t psinfo;
283d2a70789SRichard Lowe 		prsecflags_t *psf;
284d2a70789SRichard Lowe 		int gcode;
285d2a70789SRichard Lowe 
286d2a70789SRichard Lowe 		if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY,
287d2a70789SRichard Lowe 		    pgrab_flags, &gcode)) == NULL) {
288d2a70789SRichard Lowe 			warnx(gettext("cannot examine %s: %s"),
289d2a70789SRichard Lowe 			    arg, Pgrab_error(gcode));
290d2a70789SRichard Lowe 			ret = 1;
291d2a70789SRichard Lowe 			continue;
292d2a70789SRichard Lowe 		}
293d2a70789SRichard Lowe 
294d2a70789SRichard Lowe 		(void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t));
295d2a70789SRichard Lowe 		proc_unctrl_psinfo(&psinfo);
296d2a70789SRichard Lowe 
297d2a70789SRichard Lowe 		if (Pstate(Pr) == PS_DEAD) {
298d2a70789SRichard Lowe 			(void) printf(gettext("core '%s' of %d:\t%.70s\n"),
299d2a70789SRichard Lowe 			    arg, (int)psinfo.pr_pid, psinfo.pr_psargs);
300d2a70789SRichard Lowe 		} else {
301d2a70789SRichard Lowe 			(void) printf("%d:\t%.70s\n",
302d2a70789SRichard Lowe 			    (int)psinfo.pr_pid, psinfo.pr_psargs);
303d2a70789SRichard Lowe 		}
304d2a70789SRichard Lowe 
305d2a70789SRichard Lowe 		if (Psecflags(Pr, &psf) != 0)
306d2a70789SRichard Lowe 			err(1, gettext("cannot read secflags of %s"), arg);
307d2a70789SRichard Lowe 
308d2a70789SRichard Lowe 		print_flags("E", psf->pr_effective);
309d2a70789SRichard Lowe 		print_flags("I", psf->pr_inherit);
310d2a70789SRichard Lowe 		print_flags("L", psf->pr_lower);
311d2a70789SRichard Lowe 		print_flags("U", psf->pr_upper);
312d2a70789SRichard Lowe 
313d2a70789SRichard Lowe 		Psecflags_free(psf);
314d2a70789SRichard Lowe 		Prelease(Pr, 0);
315d2a70789SRichard Lowe 	}
316d2a70789SRichard Lowe 
317d2a70789SRichard Lowe 	return (ret);
318d2a70789SRichard Lowe }
319