jls.c (194364) | jls.c (194869) |
---|---|
1/*- 2 * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org> 3 * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org> 4 * Copyright (c) 2009 James Gritton <jamie@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 13 unchanged lines hidden (view full) --- 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 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org> 3 * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org> 4 * Copyright (c) 2009 James Gritton <jamie@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 13 unchanged lines hidden (view full) --- 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 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: head/usr.sbin/jls/jls.c 194364 2009-06-17 14:32:08Z jamie $"); | 30__FBSDID("$FreeBSD: head/usr.sbin/jls/jls.c 194869 2009-06-24 18:18:35Z jamie $"); |
31 32#include <sys/param.h> 33#include <sys/jail.h> 34#include <sys/socket.h> 35#include <sys/sysctl.h> | 31 32#include <sys/param.h> 33#include <sys/jail.h> 34#include <sys/socket.h> 35#include <sys/sysctl.h> |
36#include <sys/uio.h> | |
37 38#include <arpa/inet.h> 39#include <netinet/in.h> 40 41#include <err.h> 42#include <errno.h> | 36 37#include <arpa/inet.h> 38#include <netinet/in.h> 39 40#include <err.h> 41#include <errno.h> |
42#include <jail.h> |
|
43#include <limits.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <unistd.h> 48 | 43#include <limits.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <unistd.h> 48 |
49#define SJPARAM "security.jail.param" 50#define ARRAY_SLOP 5 | 49#define JP_USER 0x01000000 50#define JP_OPT 0x02000000 |
51 | 51 |
52#define CTLTYPE_BOOL (CTLTYPE + 1) 53#define CTLTYPE_NOBOOL (CTLTYPE + 2) 54#define CTLTYPE_IPADDR (CTLTYPE + 3) 55#define CTLTYPE_IP6ADDR (CTLTYPE + 4) 56 57#define PARAM_KEY 0x01 58#define PARAM_USER 0x02 59#define PARAM_ARRAY 0x04 60#define PARAM_OPT 0x08 61#define PARAM_WR 0x10 62 | |
63#define PRINT_DEFAULT 0x01 64#define PRINT_HEADER 0x02 65#define PRINT_NAMEVAL 0x04 66#define PRINT_QUOTED 0x08 67#define PRINT_SKIP 0x10 68#define PRINT_VERBOSE 0x20 69 | 52#define PRINT_DEFAULT 0x01 53#define PRINT_HEADER 0x02 54#define PRINT_NAMEVAL 0x04 55#define PRINT_QUOTED 0x08 56#define PRINT_SKIP 0x10 57#define PRINT_VERBOSE 0x20 58 |
70struct param { 71 char *name; 72 void *value; 73 size_t size; 74 int type; 75 unsigned flags; 76 int noparent; 77}; 78 79struct iovec2 { 80 struct iovec name; 81 struct iovec value; 82}; 83 84static struct param *params; | 59static struct jailparam *params; 60static int *param_noparent; |
85static int nparams; | 61static int nparams; |
86static char errmsg[256]; | |
87 | 62 |
88static int add_param(const char *name, void *value, unsigned flags); 89static int get_param(const char *name, struct param *param); | 63static int add_param(const char *name, void *value, size_t valuelen, 64 struct jailparam *source, unsigned flags); |
90static int sort_param(const void *a, const void *b); 91static char *noname(const char *name); 92static char *nononame(const char *name); 93static int print_jail(int pflags, int jflags); | 65static int sort_param(const void *a, const void *b); 66static char *noname(const char *name); 67static char *nononame(const char *name); 68static int print_jail(int pflags, int jflags); |
94static void quoted_print(char *str, int len); | 69static void quoted_print(char *str); |
95 96int 97main(int argc, char **argv) 98{ 99 char *dot, *ep, *jname, *nname; 100 int c, i, jflags, jid, lastjid, pflags, spc; 101 102 jname = NULL; --- 28 unchanged lines hidden (view full) --- 131 break; 132 default: 133 errx(1, "usage: jls [-dhnqv] [-j jail] [param ...]"); 134 } 135 136 /* Add the parameters to print. */ 137 if (optind == argc) { 138 if (pflags & PRINT_VERBOSE) { | 70 71int 72main(int argc, char **argv) 73{ 74 char *dot, *ep, *jname, *nname; 75 int c, i, jflags, jid, lastjid, pflags, spc; 76 77 jname = NULL; --- 28 unchanged lines hidden (view full) --- 106 break; 107 default: 108 errx(1, "usage: jls [-dhnqv] [-j jail] [param ...]"); 109 } 110 111 /* Add the parameters to print. */ 112 if (optind == argc) { 113 if (pflags & PRINT_VERBOSE) { |
139 add_param("jid", NULL, PARAM_USER); 140 add_param("host.hostname", NULL, PARAM_USER); 141 add_param("path", NULL, PARAM_USER); 142 add_param("name", NULL, PARAM_USER); 143 add_param("dying", NULL, PARAM_USER); 144 add_param("cpuset.id", NULL, PARAM_USER); 145 add_param("ip4.addr", NULL, PARAM_USER); 146 add_param("ip6.addr", NULL, PARAM_USER | PARAM_OPT); | 114 add_param("jid", NULL, (size_t)0, NULL, JP_USER); 115 add_param("host.hostname", NULL, (size_t)0, NULL, 116 JP_USER); 117 add_param("path", NULL, (size_t)0, NULL, JP_USER); 118 add_param("name", NULL, (size_t)0, NULL, JP_USER); 119 add_param("dying", NULL, (size_t)0, NULL, JP_USER); 120 add_param("cpuset.id", NULL, (size_t)0, NULL, JP_USER); 121 add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER); 122 add_param("ip6.addr", NULL, (size_t)0, NULL, 123 JP_USER | JP_OPT); |
147 } else { 148 pflags = (pflags & 149 ~(PRINT_NAMEVAL | PRINT_SKIP | PRINT_VERBOSE)) | 150 PRINT_DEFAULT; | 124 } else { 125 pflags = (pflags & 126 ~(PRINT_NAMEVAL | PRINT_SKIP | PRINT_VERBOSE)) | 127 PRINT_DEFAULT; |
151 add_param("jid", NULL, PARAM_USER); 152 add_param("ip4.addr", NULL, PARAM_USER); 153 add_param("host.hostname", NULL, PARAM_USER); 154 add_param("path", NULL, PARAM_USER); | 128 add_param("jid", NULL, (size_t)0, NULL, JP_USER); 129 add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER); 130 add_param("host.hostname", NULL, (size_t)0, NULL, 131 JP_USER); 132 add_param("path", NULL, (size_t)0, NULL, JP_USER); |
155 } 156 } else 157 while (optind < argc) | 133 } 134 } else 135 while (optind < argc) |
158 add_param(argv[optind++], NULL, PARAM_USER); | 136 add_param(argv[optind++], NULL, (size_t)0, NULL, 137 JP_USER); |
159 160 if (pflags & PRINT_SKIP) { 161 /* Check for parameters with boolean parents. */ 162 for (i = 0; i < nparams; i++) { | 138 139 if (pflags & PRINT_SKIP) { 140 /* Check for parameters with boolean parents. */ 141 for (i = 0; i < nparams; i++) { |
163 if ((params[i].flags & PARAM_USER) && 164 (dot = strchr(params[i].name, '.'))) { | 142 if ((params[i].jp_flags & JP_USER) && 143 (dot = strchr(params[i].jp_name, '.'))) { |
165 *dot = 0; | 144 *dot = 0; |
166 nname = noname(params[i].name); | 145 nname = noname(params[i].jp_name); |
167 *dot = '.'; | 146 *dot = '.'; |
168 params[i].noparent = 169 add_param(nname, NULL, PARAM_OPT); | 147 param_noparent[i] = 148 add_param(nname, NULL, (size_t)0, NULL, 149 JP_OPT); |
170 free(nname); 171 } 172 } 173 } 174 | 150 free(nname); 151 } 152 } 153 } 154 |
175 /* Add the index key and errmsg parameters. */ | 155 /* Add the index key parameters. */ |
176 if (jid != 0) | 156 if (jid != 0) |
177 add_param("jid", &jid, PARAM_KEY); | 157 add_param("jid", &jid, sizeof(jid), NULL, 0); |
178 else if (jname != NULL) | 158 else if (jname != NULL) |
179 add_param("name", jname, PARAM_KEY); | 159 add_param("name", jname, strlen(jname), NULL, 0); |
180 else | 160 else |
181 add_param("lastjid", &lastjid, PARAM_KEY); 182 add_param("errmsg", errmsg, PARAM_KEY); | 161 add_param("lastjid", &lastjid, sizeof(lastjid), NULL, 0); |
183 184 /* Print a header line if requested. */ 185 if (pflags & PRINT_VERBOSE) 186 printf(" JID Hostname Path\n" 187 " Name State\n" 188 " CPUSetID\n" 189 " IP Address(es)\n"); 190 else if (pflags & PRINT_DEFAULT) 191 printf(" JID IP Address " 192 "Hostname Path\n"); 193 else if (pflags & PRINT_HEADER) { 194 for (i = spc = 0; i < nparams; i++) | 162 163 /* Print a header line if requested. */ 164 if (pflags & PRINT_VERBOSE) 165 printf(" JID Hostname Path\n" 166 " Name State\n" 167 " CPUSetID\n" 168 " IP Address(es)\n"); 169 else if (pflags & PRINT_DEFAULT) 170 printf(" JID IP Address " 171 "Hostname Path\n"); 172 else if (pflags & PRINT_HEADER) { 173 for (i = spc = 0; i < nparams; i++) |
195 if (params[i].flags & PARAM_USER) { | 174 if (params[i].jp_flags & JP_USER) { |
196 if (spc) 197 putchar(' '); 198 else 199 spc = 1; | 175 if (spc) 176 putchar(' '); 177 else 178 spc = 1; |
200 fputs(params[i].name, stdout); | 179 fputs(params[i].jp_name, stdout); |
201 } 202 putchar('\n'); 203 } 204 205 /* Fetch the jail(s) and print the paramters. */ 206 if (jid != 0 || jname != NULL) { | 180 } 181 putchar('\n'); 182 } 183 184 /* Fetch the jail(s) and print the paramters. */ 185 if (jid != 0 || jname != NULL) { |
207 if (print_jail(pflags, jflags) < 0) { 208 if (errmsg[0]) 209 errx(1, "%s", errmsg); 210 err(1, "jail_get"); 211 } | 186 if (print_jail(pflags, jflags) < 0) 187 errx(1, "%s", jail_errmsg); |
212 } else { 213 for (lastjid = 0; 214 (lastjid = print_jail(pflags, jflags)) >= 0; ) 215 ; | 188 } else { 189 for (lastjid = 0; 190 (lastjid = print_jail(pflags, jflags)) >= 0; ) 191 ; |
216 if (errno != 0 && errno != ENOENT) { 217 if (errmsg[0]) 218 errx(1, "%s", errmsg); 219 err(1, "jail_get"); 220 } | 192 if (errno != 0 && errno != ENOENT) 193 errx(1, "%s", jail_errmsg); |
221 } 222 223 return (0); 224} 225 226static int | 194 } 195 196 return (0); 197} 198 199static int |
227add_param(const char *name, void *value, unsigned flags) | 200add_param(const char *name, void *value, size_t valuelen, 201 struct jailparam *source, unsigned flags) |
228{ | 202{ |
229 struct param *param; 230 char *nname; 231 size_t mlen1, mlen2, buflen; 232 int mib1[CTL_MAXNAME], mib2[CTL_MAXNAME - 2]; | 203 struct jailparam *param, *tparams; |
233 int i, tnparams; | 204 int i, tnparams; |
234 char buf[MAXPATHLEN]; | |
235 236 static int paramlistsize; 237 238 /* The pseudo-parameter "all" scans the list of available parameters. */ 239 if (!strcmp(name, "all")) { | 205 206 static int paramlistsize; 207 208 /* The pseudo-parameter "all" scans the list of available parameters. */ 209 if (!strcmp(name, "all")) { |
240 tnparams = nparams; 241 mib1[0] = 0; 242 mib1[1] = 2; 243 mlen1 = CTL_MAXNAME - 2; 244 if (sysctlnametomib(SJPARAM, mib1 + 2, &mlen1) < 0) 245 err(1, "sysctlnametomib(" SJPARAM ")"); 246 for (;;) { 247 /* Get the next parameter. */ 248 mlen2 = sizeof(mib2); 249 if (sysctl(mib1, mlen1 + 2, mib2, &mlen2, NULL, 0) < 0) 250 err(1, "sysctl(0.2)"); 251 if (mib2[0] != mib1[2] || mib2[1] != mib1[3] || 252 mib2[2] != mib1[4]) 253 break; 254 /* Convert it to an ascii name. */ 255 memcpy(mib1 + 2, mib2, mlen2); 256 mlen1 = mlen2 / sizeof(int); 257 mib1[1] = 1; 258 buflen = sizeof(buf); 259 if (sysctl(mib1, mlen1 + 2, buf, &buflen, NULL, 0) < 0) 260 err(1, "sysctl(0.1)"); 261 add_param(buf + sizeof(SJPARAM), NULL, flags); 262 /* 263 * Convert nobool parameters to bool if their 264 * counterpart is a node, ortherwise discard them. 265 */ 266 param = ¶ms[nparams - 1]; 267 if (param->type == CTLTYPE_NOBOOL) { 268 nname = nononame(param->name); 269 if (get_param(nname, param) >= 0 && 270 param->type != CTLTYPE_NODE) { 271 free(nname); 272 nparams--; 273 } else { 274 free(param->name); 275 param->name = nname; 276 param->type = CTLTYPE_BOOL; 277 param->size = sizeof(int); 278 param->value = NULL; 279 } 280 } 281 mib1[1] = 2; 282 } 283 284 qsort(params + tnparams, (size_t)(nparams - tnparams), 285 sizeof(struct param), sort_param); | 210 tnparams = jailparam_all(&tparams); 211 if (tnparams < 0) 212 errx(1, "%s", jail_errmsg); 213 qsort(tparams, (size_t)tnparams, sizeof(struct jailparam), 214 sort_param); 215 for (i = 0; i < tnparams; i++) 216 add_param(tparams[i].jp_name, NULL, (size_t)0, 217 tparams + i, flags); 218 free(tparams); |
286 return -1; 287 } 288 289 /* Check for repeat parameters. */ 290 for (i = 0; i < nparams; i++) | 219 return -1; 220 } 221 222 /* Check for repeat parameters. */ 223 for (i = 0; i < nparams; i++) |
291 if (!strcmp(name, params[i].name)) { 292 params[i].value = value; 293 params[i].flags |= flags; | 224 if (!strcmp(name, params[i].jp_name)) { 225 if (value != NULL && jailparam_import_raw(params + i, 226 value, valuelen) < 0) 227 errx(1, "%s", jail_errmsg); 228 params[i].jp_flags |= flags; 229 if (source != NULL) 230 jailparam_free(source, 1); |
294 return i; 295 } 296 297 /* Make sure there is room for the new param record. */ 298 if (!nparams) { 299 paramlistsize = 32; 300 params = malloc(paramlistsize * sizeof(*params)); | 231 return i; 232 } 233 234 /* Make sure there is room for the new param record. */ 235 if (!nparams) { 236 paramlistsize = 32; 237 params = malloc(paramlistsize * sizeof(*params)); |
301 if (params == NULL) | 238 param_noparent = 239 malloc(paramlistsize * sizeof(*param_noparent)); 240 if (params == NULL || param_noparent == NULL) |
302 err(1, "malloc"); 303 } else if (nparams >= paramlistsize) { 304 paramlistsize *= 2; 305 params = realloc(params, paramlistsize * sizeof(*params)); | 241 err(1, "malloc"); 242 } else if (nparams >= paramlistsize) { 243 paramlistsize *= 2; 244 params = realloc(params, paramlistsize * sizeof(*params)); |
306 if (params == NULL) | 245 param_noparent = realloc(param_noparent, 246 paramlistsize * sizeof(*param_noparent)); 247 if (params == NULL || param_noparent == NULL) |
307 err(1, "realloc"); 308 } 309 310 /* Look up the parameter. */ | 248 err(1, "realloc"); 249 } 250 251 /* Look up the parameter. */ |
252 param_noparent[nparams] = -1; |
|
311 param = params + nparams++; | 253 param = params + nparams++; |
312 memset(param, 0, sizeof *param); 313 param->name = strdup(name); 314 if (param->name == NULL) 315 err(1, "strdup"); 316 param->flags = flags; 317 param->noparent = -1; 318 /* We have to know about pseudo-parameters without asking. */ 319 if (!strcmp(param->name, "lastjid")) { 320 param->type = CTLTYPE_INT; 321 param->size = sizeof(int); 322 goto got_type; | 254 if (source != NULL) { 255 *param = *source; 256 param->jp_flags |= flags; 257 return param - params; |
323 } | 258 } |
324 if (!strcmp(param->name, "errmsg")) { 325 param->type = CTLTYPE_STRING; 326 param->size = sizeof(errmsg); 327 goto got_type; 328 } 329 if (get_param(name, param) < 0) { 330 if (errno != ENOENT) 331 err(1, "sysctl(0.3.%s)", name); 332 /* See if this the "no" part of an existing boolean. */ 333 if ((nname = nononame(name))) { 334 i = get_param(nname, param); 335 free(nname); 336 if (i >= 0 && param->type == CTLTYPE_BOOL) { 337 param->type = CTLTYPE_NOBOOL; 338 goto got_type; 339 } 340 } 341 if (flags & PARAM_OPT) { | 259 if (jailparam_init(param, name) < 0) 260 errx(1, "%s", jail_errmsg); 261 param->jp_flags = flags; 262 if ((value != NULL ? jailparam_import_raw(param, value, valuelen) 263 : jailparam_import(param, value)) < 0) { 264 if (flags & JP_OPT) { |
342 nparams--; | 265 nparams--; |
343 return -1; | 266 return (-1); |
344 } | 267 } |
345 errx(1, "unknown parameter: %s", name); | 268 errx(1, "%s", jail_errmsg); |
346 } | 269 } |
347 if (param->type == CTLTYPE_NODE) { 348 /* 349 * A node isn't normally a parameter, but may be a boolean 350 * if its "no" counterpart exists. 351 */ 352 nname = noname(name); 353 i = get_param(nname, param); 354 free(nname); 355 if (i >= 0 && param->type == CTLTYPE_NOBOOL) { 356 param->type = CTLTYPE_BOOL; 357 goto got_type; 358 } 359 errx(1, "unknown parameter: %s", name); 360 } 361 362 got_type: 363 param->value = value; | |
364 return param - params; 365} 366 367static int | 270 return param - params; 271} 272 273static int |
368get_param(const char *name, struct param *param) 369{ 370 char *p; 371 size_t buflen, mlen; 372 int mib[CTL_MAXNAME]; 373 struct { 374 int i; 375 char s[MAXPATHLEN]; 376 } buf; 377 378 /* Look up the MIB. */ 379 mib[0] = 0; 380 mib[1] = 3; 381 snprintf(buf.s, sizeof(buf.s), SJPARAM ".%s", name); 382 mlen = sizeof(mib) - 2 * sizeof(int); 383 if (sysctl(mib, 2, mib + 2, &mlen, buf.s, strlen(buf.s)) < 0) 384 return (-1); 385 /* Get the type and size. */ 386 mib[1] = 4; 387 buflen = sizeof(buf); 388 if (sysctl(mib, (mlen / sizeof(int)) + 2, &buf, &buflen, NULL, 0) < 0) 389 err(1, "sysctl(0.4.%s)", name); 390 param->type = buf.i & CTLTYPE; 391 if (buf.i & (CTLFLAG_WR | CTLFLAG_TUN)) 392 param->flags |= PARAM_WR; 393 p = strchr(buf.s, '\0'); 394 if (p - 2 >= buf.s && !strcmp(p - 2, ",a")) { 395 p[-2] = 0; 396 param->flags |= PARAM_ARRAY; 397 } 398 switch (param->type) { 399 case CTLTYPE_INT: 400 /* An integer parameter might be a boolean. */ 401 if (buf.s[0] == 'B') 402 param->type = buf.s[1] == 'N' 403 ? CTLTYPE_NOBOOL : CTLTYPE_BOOL; 404 case CTLTYPE_UINT: 405 param->size = sizeof(int); 406 break; 407 case CTLTYPE_LONG: 408 case CTLTYPE_ULONG: 409 param->size = sizeof(long); 410 break; 411 case CTLTYPE_STRUCT: 412 if (!strcmp(buf.s, "S,in_addr")) { 413 param->type = CTLTYPE_IPADDR; 414 param->size = sizeof(struct in_addr); 415 } else if (!strcmp(buf.s, "S,in6_addr")) { 416 param->type = CTLTYPE_IP6ADDR; 417 param->size = sizeof(struct in6_addr); 418 } 419 break; 420 case CTLTYPE_STRING: 421 buf.s[0] = 0; 422 sysctl(mib + 2, mlen / sizeof(int), buf.s, &buflen, NULL, 0); 423 param->size = strtoul(buf.s, NULL, 10); 424 if (param->size == 0) 425 param->size = BUFSIZ; 426 } 427 return (0); 428} 429 430static int | |
431sort_param(const void *a, const void *b) 432{ | 274sort_param(const void *a, const void *b) 275{ |
433 const struct param *parama, *paramb; | 276 const struct jailparam *parama, *paramb; |
434 char *ap, *bp; 435 436 /* Put top-level parameters first. */ 437 parama = a; 438 paramb = b; | 277 char *ap, *bp; 278 279 /* Put top-level parameters first. */ 280 parama = a; 281 paramb = b; |
439 ap = strchr(parama->name, '.'); 440 bp = strchr(paramb->name, '.'); | 282 ap = strchr(parama->jp_name, '.'); 283 bp = strchr(paramb->jp_name, '.'); |
441 if (ap && !bp) 442 return (1); 443 if (bp && !ap) 444 return (-1); | 284 if (ap && !bp) 285 return (1); 286 if (bp && !ap) 287 return (-1); |
445 return (strcmp(parama->name, paramb->name)); | 288 return (strcmp(parama->jp_name, paramb->jp_name)); |
446} 447 448static char * 449noname(const char *name) 450{ 451 char *nname, *p; 452 453 nname = malloc(strlen(name) + 3); --- 24 unchanged lines hidden (view full) --- 478 strcpy(nname, name + 2); 479 return nname; 480} 481 482static int 483print_jail(int pflags, int jflags) 484{ 485 char *nname; | 289} 290 291static char * 292noname(const char *name) 293{ 294 char *nname, *p; 295 296 nname = malloc(strlen(name) + 3); --- 24 unchanged lines hidden (view full) --- 321 strcpy(nname, name + 2); 322 return nname; 323} 324 325static int 326print_jail(int pflags, int jflags) 327{ 328 char *nname; |
486 int i, ai, jid, count, sanity, spc; | 329 char **param_values; 330 int i, ai, jid, count, spc; |
487 char ipbuf[INET6_ADDRSTRLEN]; 488 | 331 char ipbuf[INET6_ADDRSTRLEN]; 332 |
489 static struct iovec2 *iov, *aiov; 490 static int narray, nkey; 491 492 /* Set up the parameter list(s) the first time around. */ 493 if (iov == NULL) { 494 iov = malloc(nparams * sizeof(struct iovec2)); 495 if (iov == NULL) 496 err(1, "malloc"); 497 for (i = narray = 0; i < nparams; i++) { 498 iov[i].name.iov_base = params[i].name; 499 iov[i].name.iov_len = strlen(params[i].name) + 1; 500 iov[i].value.iov_base = params[i].value; 501 iov[i].value.iov_len = 502 params[i].type == CTLTYPE_STRING && 503 params[i].value != NULL && 504 ((char *)params[i].value)[0] != '\0' 505 ? strlen(params[i].value) + 1 : params[i].size; 506 if (params[i].flags & (PARAM_KEY | PARAM_ARRAY)) { 507 narray++; 508 if (params[i].flags & PARAM_KEY) 509 nkey++; 510 } 511 } 512 if (narray > nkey) { 513 aiov = malloc(narray * sizeof(struct iovec2)); 514 if (aiov == NULL) 515 err(1, "malloc"); 516 for (i = ai = 0; i < nparams; i++) 517 if (params[i].flags & 518 (PARAM_KEY | PARAM_ARRAY)) 519 aiov[ai++] = iov[i]; 520 } 521 } 522 /* If there are array parameters, find their sizes. */ 523 if (aiov != NULL) { 524 for (ai = 0; ai < narray; ai++) 525 if (aiov[ai].value.iov_base == NULL) 526 aiov[ai].value.iov_len = 0; 527 if (jail_get((struct iovec *)aiov, 2 * narray, jflags) < 0) 528 return (-1); 529 } 530 /* Allocate storage for all parameters. */ 531 for (i = ai = 0; i < nparams; i++) { 532 if (params[i].flags & (PARAM_KEY | PARAM_ARRAY)) { 533 if (params[i].flags & PARAM_ARRAY) { 534 iov[i].value.iov_len = aiov[ai].value.iov_len + 535 ARRAY_SLOP * params[i].size; 536 iov[i].value.iov_base = 537 malloc(iov[i].value.iov_len); 538 } 539 ai++; 540 } else 541 iov[i].value.iov_base = malloc(params[i].size); 542 if (iov[i].value.iov_base == NULL) 543 err(1, "malloc"); 544 if (params[i].value == NULL) 545 memset(iov[i].value.iov_base, 0, iov[i].value.iov_len); 546 } 547 /* 548 * Get the actual prison. If there are array elements, retry a few 549 * times in case the size changed from under us. 550 */ 551 if ((jid = jail_get((struct iovec *)iov, 2 * nparams, jflags)) < 0) { 552 if (errno != EINVAL || aiov == NULL || errmsg[0]) 553 return (-1); 554 for (sanity = 0;; sanity++) { 555 if (sanity == 10) 556 return (-1); 557 for (ai = 0; ai < narray; ai++) 558 if (params[i].flags & PARAM_ARRAY) 559 aiov[ai].value.iov_len = 0; 560 if (jail_get((struct iovec *)iov, 2 * narray, jflags) < 561 0) 562 return (-1); 563 for (i = ai = 0; i < nparams; i++) { 564 if (!(params[i].flags & 565 (PARAM_KEY | PARAM_ARRAY))) 566 continue; 567 if (params[i].flags & PARAM_ARRAY) { 568 iov[i].value.iov_len = 569 aiov[ai].value.iov_len + 570 ARRAY_SLOP * params[i].size; 571 iov[i].value.iov_base = 572 realloc(iov[i].value.iov_base, 573 iov[i].value.iov_len); 574 if (iov[i].value.iov_base == NULL) 575 err(1, "malloc"); 576 } 577 ai++; 578 } 579 } 580 } | 333 jid = jailparam_get(params, nparams, jflags); 334 if (jid < 0) 335 return jid; |
581 if (pflags & PRINT_VERBOSE) { 582 printf("%6d %-29.29s %.74s\n" 583 "%6s %-29.29s %.74s\n" 584 "%6s %-6d\n", | 336 if (pflags & PRINT_VERBOSE) { 337 printf("%6d %-29.29s %.74s\n" 338 "%6s %-29.29s %.74s\n" 339 "%6s %-6d\n", |
585 *(int *)iov[0].value.iov_base, 586 (char *)iov[1].value.iov_base, 587 (char *)iov[2].value.iov_base, | 340 *(int *)params[0].jp_value, 341 (char *)params[1].jp_value, 342 (char *)params[2].jp_value, |
588 "", | 343 "", |
589 (char *)iov[3].value.iov_base, 590 *(int *)iov[4].value.iov_base ? "DYING" : "ACTIVE", | 344 (char *)params[3].jp_value, 345 *(int *)params[4].jp_value ? "DYING" : "ACTIVE", |
591 "", | 346 "", |
592 *(int *)iov[5].value.iov_base); 593 count = iov[6].value.iov_len / sizeof(struct in_addr); | 347 *(int *)params[5].jp_value); 348 count = params[6].jp_valuelen / sizeof(struct in_addr); |
594 for (ai = 0; ai < count; ai++) 595 if (inet_ntop(AF_INET, | 349 for (ai = 0; ai < count; ai++) 350 if (inet_ntop(AF_INET, |
596 &((struct in_addr *)iov[6].value.iov_base)[ai], | 351 &((struct in_addr *)params[6].jp_value)[ai], |
597 ipbuf, sizeof(ipbuf)) == NULL) 598 err(1, "inet_ntop"); 599 else 600 printf("%6s %-15.15s\n", "", ipbuf); | 352 ipbuf, sizeof(ipbuf)) == NULL) 353 err(1, "inet_ntop"); 354 else 355 printf("%6s %-15.15s\n", "", ipbuf); |
601 if (!strcmp(params[7].name, "ip6.addr")) { 602 count = iov[7].value.iov_len / sizeof(struct in6_addr); | 356 if (!strcmp(params[7].jp_name, "ip6.addr")) { 357 count = params[7].jp_valuelen / sizeof(struct in6_addr); |
603 for (ai = 0; ai < count; ai++) | 358 for (ai = 0; ai < count; ai++) |
604 if (inet_ntop(AF_INET6, &((struct in_addr *) 605 iov[7].value.iov_base)[ai], | 359 if (inet_ntop(AF_INET6, 360 &((struct in_addr *)params[7].jp_value)[ai], |
606 ipbuf, sizeof(ipbuf)) == NULL) 607 err(1, "inet_ntop"); 608 else 609 printf("%6s %-15.15s\n", "", ipbuf); 610 } 611 } else if (pflags & PRINT_DEFAULT) 612 printf("%6d %-15.15s %-29.29s %.74s\n", | 361 ipbuf, sizeof(ipbuf)) == NULL) 362 err(1, "inet_ntop"); 363 else 364 printf("%6s %-15.15s\n", "", ipbuf); 365 } 366 } else if (pflags & PRINT_DEFAULT) 367 printf("%6d %-15.15s %-29.29s %.74s\n", |
613 *(int *)iov[0].value.iov_base, 614 iov[1].value.iov_len == 0 ? "-" 615 : inet_ntoa(*(struct in_addr *)iov[1].value.iov_base), 616 (char *)iov[2].value.iov_base, 617 (char *)iov[3].value.iov_base); | 368 *(int *)params[0].jp_value, 369 params[1].jp_valuelen == 0 ? "-" 370 : inet_ntoa(*(struct in_addr *)params[1].jp_value), 371 (char *)params[2].jp_value, 372 (char *)params[3].jp_value); |
618 else { | 373 else { |
374 param_values = alloca(nparams * sizeof(*param_values)); 375 for (i = 0; i < nparams; i++) { 376 if (!(params[i].jp_flags & JP_USER)) 377 continue; 378 param_values[i] = jailparam_export(params + i); 379 if (param_values[i] == NULL) 380 errx(1, "%s", jail_errmsg); 381 } |
|
619 for (i = spc = 0; i < nparams; i++) { | 382 for (i = spc = 0; i < nparams; i++) { |
620 if (!(params[i].flags & PARAM_USER)) | 383 if (!(params[i].jp_flags & JP_USER)) |
621 continue; 622 if ((pflags & PRINT_SKIP) && | 384 continue; 385 if ((pflags & PRINT_SKIP) && |
623 ((!(params[i].flags & PARAM_WR)) || 624 (params[i].noparent >= 0 && 625 *(int *)iov[params[i].noparent].value.iov_base))) | 386 ((!(params[i].jp_ctltype & 387 (CTLFLAG_WR | CTLFLAG_TUN))) || 388 (param_noparent[i] >= 0 && 389 *(int *)params[param_noparent[i]].jp_value))) |
626 continue; 627 if (spc) 628 putchar(' '); 629 else 630 spc = 1; 631 if (pflags & PRINT_NAMEVAL) { 632 /* 633 * Generally "name=value", but for booleans 634 * either "name" or "noname". 635 */ | 390 continue; 391 if (spc) 392 putchar(' '); 393 else 394 spc = 1; 395 if (pflags & PRINT_NAMEVAL) { 396 /* 397 * Generally "name=value", but for booleans 398 * either "name" or "noname". 399 */ |
636 switch (params[i].type) { 637 case CTLTYPE_BOOL: 638 if (*(int *)iov[i].value.iov_base) 639 printf("%s", params[i].name); | 400 if (params[i].jp_flags & 401 (JP_BOOL | JP_NOBOOL)) { 402 if (*(int *)params[i].jp_value) 403 printf("%s", params[i].jp_name); |
640 else { | 404 else { |
641 nname = noname(params[i].name); | 405 nname = (params[i].jp_flags & 406 JP_NOBOOL) ? 407 nononame(params[i].jp_name) 408 : noname(params[i].jp_name); |
642 printf("%s", nname); 643 free(nname); 644 } | 409 printf("%s", nname); 410 free(nname); 411 } |
645 break; 646 case CTLTYPE_NOBOOL: 647 if (*(int *)iov[i].value.iov_base) 648 printf("%s", params[i].name); 649 else { 650 nname = 651 nononame(params[i].name); 652 printf("%s", nname); 653 free(nname); 654 } 655 break; 656 default: 657 printf("%s=", params[i].name); | 412 continue; |
658 } | 413 } |
414 printf("%s=", params[i].jp_name); |
|
659 } | 415 } |
660 count = params[i].flags & PARAM_ARRAY 661 ? iov[i].value.iov_len / params[i].size : 1; 662 if (count == 0) { | 416 if (params[i].jp_valuelen == 0) { |
663 if (pflags & PRINT_QUOTED) 664 printf("\"\""); 665 else if (!(pflags & PRINT_NAMEVAL)) 666 putchar('-'); | 417 if (pflags & PRINT_QUOTED) 418 printf("\"\""); 419 else if (!(pflags & PRINT_NAMEVAL)) 420 putchar('-'); |
667 } 668 for (ai = 0; ai < count; ai++) { 669 if (ai > 0) 670 putchar(','); 671 switch (params[i].type) { 672 case CTLTYPE_INT: 673 printf("%d", ((int *) 674 iov[i].value.iov_base)[ai]); 675 break; 676 case CTLTYPE_UINT: 677 printf("%u", ((int *) 678 iov[i].value.iov_base)[ai]); 679 break; 680 case CTLTYPE_IPADDR: 681 if (inet_ntop(AF_INET, 682 &((struct in_addr *) 683 iov[i].value.iov_base)[ai], 684 ipbuf, sizeof(ipbuf)) == NULL) 685 err(1, "inet_ntop"); 686 else 687 printf("%s", ipbuf); 688 break; 689 case CTLTYPE_IP6ADDR: 690 if (inet_ntop(AF_INET6, 691 &((struct in6_addr *) 692 iov[i].value.iov_base)[ai], 693 ipbuf, sizeof(ipbuf)) == NULL) 694 err(1, "inet_ntop"); 695 else 696 printf("%s", ipbuf); 697 break; 698 case CTLTYPE_LONG: 699 printf("%ld", ((long *) 700 iov[i].value.iov_base)[ai]); 701 case CTLTYPE_ULONG: 702 printf("%lu", ((long *) 703 iov[i].value.iov_base)[ai]); 704 break; 705 case CTLTYPE_STRING: 706 if (pflags & PRINT_QUOTED) 707 quoted_print((char *) 708 iov[i].value.iov_base, 709 params[i].size); 710 else 711 printf("%.*s", 712 (int)params[i].size, 713 (char *) 714 iov[i].value.iov_base); 715 break; 716 case CTLTYPE_BOOL: 717 case CTLTYPE_NOBOOL: 718 if (!(pflags & PRINT_NAMEVAL)) 719 printf(((int *) 720 iov[i].value.iov_base)[ai] 721 ? "true" : "false"); 722 } 723 } | 421 } else 422 quoted_print(param_values[i]); |
724 } 725 putchar('\n'); | 423 } 424 putchar('\n'); |
425 for (i = 0; i < nparams; i++) 426 if (params[i].jp_flags & JP_USER) 427 free(param_values[i]); |
|
726 } 727 for (i = 0; i < nparams; i++) | 428 } 429 for (i = 0; i < nparams; i++) |
728 if (params[i].value == NULL) 729 free(iov[i].value.iov_base); | 430 if (!(params[i].jp_flags & JP_RAWVALUE)) { 431 free(params[i].jp_value); 432 params[i].jp_value = NULL; 433 } |
730 return (jid); 731} 732 733static void | 434 return (jid); 435} 436 437static void |
734quoted_print(char *str, int len) | 438quoted_print(char *str) |
735{ 736 int c, qc; 737 char *p = str; | 439{ 440 int c, qc; 441 char *p = str; |
738 char *ep = str + len; | |
739 740 /* An empty string needs quoting. */ 741 if (!*p) { 742 fputs("\"\"", stdout); 743 return; 744 } 745 746 /* 747 * The value will be surrounded by quotes if it contains spaces 748 * or quotes. 749 */ 750 qc = strchr(p, '\'') ? '"' 751 : strchr(p, '"') ? '\'' 752 : strchr(p, ' ') || strchr(p, '\t') ? '"' 753 : 0; 754 if (qc) 755 putchar(qc); | 442 443 /* An empty string needs quoting. */ 444 if (!*p) { 445 fputs("\"\"", stdout); 446 return; 447 } 448 449 /* 450 * The value will be surrounded by quotes if it contains spaces 451 * or quotes. 452 */ 453 qc = strchr(p, '\'') ? '"' 454 : strchr(p, '"') ? '\'' 455 : strchr(p, ' ') || strchr(p, '\t') ? '"' 456 : 0; 457 if (qc) 458 putchar(qc); |
756 while (p < ep && (c = *p++)) { | 459 while ((c = *p++)) { |
757 if (c == '\\' || c == qc) 758 putchar('\\'); 759 putchar(c); 760 } 761 if (qc) 762 putchar(qc); 763} | 460 if (c == '\\' || c == qc) 461 putchar('\\'); 462 putchar(c); 463 } 464 if (qc) 465 putchar(qc); 466} |