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 #include <err.h> 13 #include <errno.h> 14 #include <grp.h> 15 #include <libintl.h> 16 #include <procfs.h> 17 #include <project.h> 18 #include <pwd.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 #include <libproc.h> 24 #include <libzonecfg.h> 25 26 extern const char *__progname; 27 extern int psecflags(idtype_t, id_t, psecflags_cmd_t, uint_t); 28 29 struct flagdesc { 30 uint_t value; 31 char *name; 32 } flagdescs[] = { 33 { PROC_SEC_ASLR, "aslr" }, 34 { 0x0, NULL } 35 }; 36 37 void 38 print_flags(char *set, uint_t flags) 39 { 40 char *buf; 41 size_t buflen = 13; /* 0x + 8 digits + comma + space + NUL */ 42 struct flagdesc *fd; 43 44 if (flags == 0) { 45 (void) printf(gettext("\t%s:\tnone\n"), set); 46 return; 47 } 48 49 for (fd = flagdescs; fd->value != 0x0; fd++) 50 buflen += strlen(fd->name) + 2; /* + comma, space */ 51 52 if ((buf = calloc(buflen, sizeof (char))) == NULL) 53 err(1, gettext("allocation failed")); 54 55 for (fd = flagdescs; fd->value != 0; fd++) { 56 if (flags & fd->value) 57 (void) snprintf(buf, buflen, "%s, %s", buf, fd->name); 58 flags &= ~fd->value; 59 } 60 61 if (flags != 0) /* Contained unknown flags */ 62 (void) snprintf(buf, buflen, "%s, 0x%08x", buf, flags); 63 64 buf += 2; /* Skip the comma on the first entry */ 65 66 (void) printf("\t%s:\t%s\n", set, buf); 67 free(buf); 68 } 69 70 typedef struct { 71 psecflags_cmd_t cmd; 72 uint_t value; 73 } act_arg_t; 74 75 act_arg_t * 76 parse_secflags(const char *spec) 77 { 78 char *flag = NULL; 79 char *s; 80 struct flagdesc *fd; 81 boolean_t fail = B_FALSE; 82 act_arg_t *ret; 83 84 if ((ret = malloc(sizeof (act_arg_t))) == NULL) 85 err(1, gettext("allocation failed")); 86 87 if ((s = strdup(spec)) == NULL) 88 err(1, gettext("allocation failed")); 89 90 if (s[0] == '+') { 91 ret->cmd = PSECFLAGS_ENABLE; 92 s++; 93 } else if (s[0] == '-') { 94 ret->cmd = PSECFLAGS_DISABLE; 95 s++; 96 } else { 97 ret->cmd = PSECFLAGS_SET; 98 } 99 100 if (strncasecmp("none", s, strlen(s)) == 0) { 101 if (ret->cmd != PSECFLAGS_SET) 102 errx(1, gettext("'none' is only valid with set, not " 103 "enable or disable")); 104 ret->value = 0x0; 105 free(s); 106 return (ret); 107 } 108 109 next: 110 while ((flag = strsep(&s, ",")) != NULL) { 111 for (fd = flagdescs; fd->value != 0x0; fd++) { 112 if (strncasecmp(flag, fd->name, 113 strlen(fd->name)) == 0) { 114 ret->value |= fd->value; 115 goto next; 116 } 117 } 118 119 if (strncasecmp("none", flag, strlen(flag)) == 0) { 120 (void) fprintf(stderr, gettext("%s: 'none' is not " 121 "valid with other flags\n"), __progname); 122 } else { 123 (void) fprintf(stderr, gettext("%s: invalid " 124 "security-flag: '%s'\n"), 125 __progname, flag); 126 } 127 fail = B_TRUE; 128 } 129 130 free(s); 131 132 if (fail) 133 exit(1); 134 135 return (ret); 136 } 137 138 /* 139 * Structure defining idtypes known to the priocntl command 140 * along with the corresponding names and a liberal guess 141 * of the max number of procs sharing any given ID of that type. 142 * The idtype values themselves are defined in <sys/procset.h>. 143 */ 144 static struct idtypes { 145 idtype_t type; 146 char *name; 147 } idtypes [] = { 148 { P_ALL, "all" }, 149 { P_CTID, "contract" }, 150 { P_CTID, "ctid" }, 151 { P_GID, "gid" }, 152 { P_GID, "group" }, 153 { P_PGID, "pgid" }, 154 { P_PID, "pid" }, 155 { P_PPID, "ppid" }, 156 { P_PROJID, "project" }, 157 { P_PROJID, "projid" }, 158 { P_SID, "session", }, 159 { P_SID, "sid" }, 160 { P_SID, "sid" }, 161 { P_TASKID, "taskid" }, 162 { P_UID, "uid" }, 163 { P_UID, "user" }, 164 { P_ZONEID, "zone" }, 165 { P_ZONEID, "zoneid" }, 166 { 0, NULL } 167 }; 168 169 int 170 str2idtype(char *idtypnm, idtype_t *idtypep) 171 { 172 struct idtypes *curp; 173 174 for (curp = idtypes; curp->name != NULL; curp++) { 175 if (strncasecmp(curp->name, idtypnm, 176 strlen(curp->name)) == 0) { 177 *idtypep = curp->type; 178 return (0); 179 } 180 } 181 return (-1); 182 } 183 184 id_t 185 getid(idtype_t type, char *value) 186 { 187 struct passwd *pwd; 188 struct group *grp; 189 id_t ret; 190 char *endp; 191 192 switch (type) { 193 case P_UID: 194 if ((pwd = getpwnam(value)) != NULL) 195 return (pwd->pw_uid); 196 break; 197 case P_GID: 198 if ((grp = getgrnam(value)) != NULL) 199 return (grp->gr_gid); 200 break; 201 case P_PROJID: 202 if ((ret = getprojidbyname(value)) != (id_t)-1) 203 return (ret); 204 break; 205 case P_ZONEID: 206 if (zone_get_id(value, &ret) == 0) 207 return (ret); 208 break; 209 default: 210 break; 211 } 212 213 ret = (id_t)strtoul(value, &endp, 10); 214 if (errno || *endp != '\0') 215 return ((id_t)-1); 216 217 return (ret); 218 } 219 220 int 221 main(int argc, char **argv) 222 { 223 act_arg_t *act = NULL; 224 int ret = 0; 225 int pgrab_flags = PGRAB_RDONLY; 226 int opt; 227 char *idtypename = NULL; 228 idtype_t idtype = P_PID; 229 boolean_t usage = B_FALSE; 230 boolean_t e_flag = B_FALSE; 231 boolean_t l_flag = B_FALSE; 232 233 while ((opt = getopt(argc, argv, "eFi:ls:")) != -1) { 234 switch (opt) { 235 case 'e': 236 e_flag = B_TRUE; 237 break; 238 case 'F': 239 pgrab_flags |= PGRAB_FORCE; 240 break; 241 case 'i': 242 idtypename = optarg; 243 break; 244 case 's': 245 act = parse_secflags(optarg); 246 break; 247 case 'l': 248 l_flag = B_TRUE; 249 break; 250 default: 251 usage = B_TRUE; 252 break; 253 } 254 } 255 256 argc -= optind; 257 argv += optind; 258 259 if (l_flag && ((idtypename != NULL) || (act != NULL) || (argc != 0))) 260 usage = B_TRUE; 261 if ((idtypename != NULL) && (act == NULL)) 262 usage = B_TRUE; 263 if (e_flag && (act == NULL)) 264 usage = B_TRUE; 265 if (!l_flag && argc <= 0) 266 usage = B_TRUE; 267 268 if (usage) { 269 (void) fprintf(stderr, 270 gettext("usage:\t%s [-F] { pid | core } ...\n"), 271 __progname); 272 (void) fprintf(stderr, 273 gettext("\t%s -s [-+]flags [-i idtype] id ...\n"), 274 __progname); 275 (void) fprintf(stderr, 276 gettext("\t%s -s [-+]flags -e command [arg]...\n"), 277 __progname); 278 (void) fprintf(stderr, gettext("\t%s -l\n"), __progname); 279 return (2); 280 } 281 282 if (l_flag) { 283 struct flagdesc *fd; 284 285 for (fd = flagdescs; fd->value != 0x0; fd++) { 286 (void) printf("%s\n", fd->name); 287 } 288 return (0); 289 } else if ((act != NULL) && e_flag) { 290 if (psecflags(P_PID, P_MYID, act->cmd, act->value) != 0) 291 err(1, gettext("failed setting security-flags")); 292 293 (void) execvp(argv[0], &argv[0]); 294 err(1, "%s", argv[0]); 295 } else if (act != NULL) { 296 int i; 297 id_t id; 298 299 if (idtypename != NULL) 300 if (str2idtype(idtypename, &idtype) == -1) 301 errx(1, gettext("No such id type: '%s'"), 302 idtypename); 303 304 for (i = 0; i < argc; i++) { 305 if ((id = getid(idtype, argv[i])) == (id_t)-1) { 306 errx(1, gettext("invalid or non-existent " 307 "identifier: '%s'"), argv[i]); 308 } 309 310 if (psecflags(idtype, id, act->cmd, act->value) != 0) 311 err(1, gettext("failed setting " 312 "security-flags")); 313 } 314 315 return (0); 316 } 317 318 /* Display the flags for the given pids */ 319 while (argc-- > 0) { 320 struct ps_prochandle *Pr; 321 const char *arg; 322 psinfo_t psinfo; 323 int gcode; 324 325 if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY, 326 pgrab_flags, &gcode)) == NULL) { 327 warnx(gettext("cannot examine %s: %s"), 328 arg, Pgrab_error(gcode)); 329 ret = 1; 330 continue; 331 } 332 333 (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t)); 334 proc_unctrl_psinfo(&psinfo); 335 336 if (Pstate(Pr) == PS_DEAD) { 337 (void) printf(gettext("core '%s' of %d:\t%.70s\n"), 338 arg, (int)psinfo.pr_pid, psinfo.pr_psargs); 339 } else { 340 (void) printf("%d:\t%.70s\n", 341 (int)psinfo.pr_pid, psinfo.pr_psargs); 342 } 343 344 print_flags("E", Pstatus(Pr)->pr_secflags.psf_effective); 345 print_flags("I", Pstatus(Pr)->pr_secflags.psf_inherit); 346 347 Prelease(Pr, 0); 348 } 349 350 return (ret); 351 }