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