Description:
add option -A <opt> to box. This options allow more argument to be explicitly passed to the program
We have to use this because if the argument we wish to pass to the program is option (in -? format),
box will intepret it as its option and failed accordingly.
be noted that, by the definition of getopt, these options will be put after original argument
(check the code for more info)
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r186:c8d646326d0a - - 1 file changed: 17 inserted, 4 deleted
@@ -1467,281 +1467,294 | |||||
|
1467 | } |
|
1467 | } |
|
1468 | if (WIFSTOPPED(stat)) |
|
1468 | if (WIFSTOPPED(stat)) |
|
1469 | { |
|
1469 | { |
|
1470 | int sig = WSTOPSIG(stat); |
|
1470 | int sig = WSTOPSIG(stat); |
|
1471 | if (sig == SIGTRAP) |
|
1471 | if (sig == SIGTRAP) |
|
1472 | { |
|
1472 | { |
|
1473 | if (verbose > 2) |
|
1473 | if (verbose > 2) |
|
1474 | msg("[ptrace status %08x] ", stat); |
|
1474 | msg("[ptrace status %08x] ", stat); |
|
1475 | static int stop_count; |
|
1475 | static int stop_count; |
|
1476 | if (!stop_count++) /* Traceme request */ |
|
1476 | if (!stop_count++) /* Traceme request */ |
|
1477 | msg(">> Traceme request caught\n"); |
|
1477 | msg(">> Traceme request caught\n"); |
|
1478 | else |
|
1478 | else |
|
1479 | err("SG: Breakpoint"); |
|
1479 | err("SG: Breakpoint"); |
|
1480 | ptrace(PTRACE_SYSCALL, box_pid, 0, 0); |
|
1480 | ptrace(PTRACE_SYSCALL, box_pid, 0, 0); |
|
1481 | } |
|
1481 | } |
|
1482 | else if (sig == (SIGTRAP | 0x80)) |
|
1482 | else if (sig == (SIGTRAP | 0x80)) |
|
1483 | { |
|
1483 | { |
|
1484 | if (verbose > 2) |
|
1484 | if (verbose > 2) |
|
1485 | msg("[ptrace status %08x] ", stat); |
|
1485 | msg("[ptrace status %08x] ", stat); |
|
1486 | struct syscall_args a; |
|
1486 | struct syscall_args a; |
|
1487 | static unsigned int sys_tick, last_act; |
|
1487 | static unsigned int sys_tick, last_act; |
|
1488 | static arg_t last_sys; |
|
1488 | static arg_t last_sys; |
|
1489 | if (++sys_tick & 1) /* Syscall entry */ |
|
1489 | if (++sys_tick & 1) /* Syscall entry */ |
|
1490 | { |
|
1490 | { |
|
1491 | char namebuf[32]; |
|
1491 | char namebuf[32]; |
|
1492 | int act; |
|
1492 | int act; |
|
1493 |
|
1493 | ||
|
1494 | get_syscall_args(&a, 0); |
|
1494 | get_syscall_args(&a, 0); |
|
1495 | arg_t sys = a.sys; |
|
1495 | arg_t sys = a.sys; |
|
1496 | msg(">> Syscall %-12s (%08jx,%08jx,%08jx) ", syscall_name(sys, namebuf), (intmax_t) a.arg1, (intmax_t) a.arg2, (intmax_t) a.arg3); |
|
1496 | msg(">> Syscall %-12s (%08jx,%08jx,%08jx) ", syscall_name(sys, namebuf), (intmax_t) a.arg1, (intmax_t) a.arg2, (intmax_t) a.arg3); |
|
1497 | if (!exec_seen) |
|
1497 | if (!exec_seen) |
|
1498 | { |
|
1498 | { |
|
1499 | msg("[master] "); |
|
1499 | msg("[master] "); |
|
1500 | if (sys == NATIVE_NR_execve) |
|
1500 | if (sys == NATIVE_NR_execve) |
|
1501 | { |
|
1501 | { |
|
1502 | exec_seen = 1; |
|
1502 | exec_seen = 1; |
|
1503 | close_user_mem(); |
|
1503 | close_user_mem(); |
|
1504 | } |
|
1504 | } |
|
1505 | } |
|
1505 | } |
|
1506 | else if ((act = valid_syscall(&a)) >= 0) |
|
1506 | else if ((act = valid_syscall(&a)) >= 0) |
|
1507 | { |
|
1507 | { |
|
1508 | last_act = act; |
|
1508 | last_act = act; |
|
1509 | syscall_count++; |
|
1509 | syscall_count++; |
|
1510 | if (act & A_SAMPLE_MEM) |
|
1510 | if (act & A_SAMPLE_MEM) |
|
1511 | sample_mem_peak(); |
|
1511 | sample_mem_peak(); |
|
1512 | } |
|
1512 | } |
|
1513 | else |
|
1513 | else |
|
1514 | { |
|
1514 | { |
|
1515 | /* |
|
1515 | /* |
|
1516 | * Unfortunately, PTRACE_KILL kills _after_ the syscall completes, |
|
1516 | * Unfortunately, PTRACE_KILL kills _after_ the syscall completes, |
|
1517 | * so we have to change it to something harmless (e.g., an undefined |
|
1517 | * so we have to change it to something harmless (e.g., an undefined |
|
1518 | * syscall) and make the program continue. |
|
1518 | * syscall) and make the program continue. |
|
1519 | */ |
|
1519 | */ |
|
1520 | set_syscall_nr(&a, ~(arg_t)0); |
|
1520 | set_syscall_nr(&a, ~(arg_t)0); |
|
1521 | err("FO: Forbidden syscall %s", syscall_name(sys, namebuf)); |
|
1521 | err("FO: Forbidden syscall %s", syscall_name(sys, namebuf)); |
|
1522 | } |
|
1522 | } |
|
1523 | last_sys = sys; |
|
1523 | last_sys = sys; |
|
1524 | } |
|
1524 | } |
|
1525 | else /* Syscall return */ |
|
1525 | else /* Syscall return */ |
|
1526 | { |
|
1526 | { |
|
1527 | get_syscall_args(&a, 1); |
|
1527 | get_syscall_args(&a, 1); |
|
1528 | if (a.sys == ~(arg_t)0) |
|
1528 | if (a.sys == ~(arg_t)0) |
|
1529 | { |
|
1529 | { |
|
1530 | /* Some syscalls (sigreturn et al.) do not return a value */ |
|
1530 | /* Some syscalls (sigreturn et al.) do not return a value */ |
|
1531 | if (!(last_act & A_NO_RETVAL)) |
|
1531 | if (!(last_act & A_NO_RETVAL)) |
|
1532 | err("XX: Syscall does not return, but it should"); |
|
1532 | err("XX: Syscall does not return, but it should"); |
|
1533 | } |
|
1533 | } |
|
1534 | else |
|
1534 | else |
|
1535 | { |
|
1535 | { |
|
1536 | if (a.sys != last_sys) |
|
1536 | if (a.sys != last_sys) |
|
1537 | err("XX: Mismatched syscall entry/exit"); |
|
1537 | err("XX: Mismatched syscall entry/exit"); |
|
1538 | } |
|
1538 | } |
|
1539 | if (last_act & A_NO_RETVAL) |
|
1539 | if (last_act & A_NO_RETVAL) |
|
1540 | msg("= ?\n"); |
|
1540 | msg("= ?\n"); |
|
1541 | else |
|
1541 | else |
|
1542 | msg("= %jd\n", (intmax_t) a.result); |
|
1542 | msg("= %jd\n", (intmax_t) a.result); |
|
1543 | } |
|
1543 | } |
|
1544 | ptrace(PTRACE_SYSCALL, box_pid, 0, 0); |
|
1544 | ptrace(PTRACE_SYSCALL, box_pid, 0, 0); |
|
1545 | } |
|
1545 | } |
|
1546 | else if (sig == SIGSTOP) |
|
1546 | else if (sig == SIGSTOP) |
|
1547 | { |
|
1547 | { |
|
1548 | msg(">> SIGSTOP\n"); |
|
1548 | msg(">> SIGSTOP\n"); |
|
1549 | if (ptrace(PTRACE_SETOPTIONS, box_pid, NULL, (void *) PTRACE_O_TRACESYSGOOD) < 0) |
|
1549 | if (ptrace(PTRACE_SETOPTIONS, box_pid, NULL, (void *) PTRACE_O_TRACESYSGOOD) < 0) |
|
1550 | die("ptrace(PTRACE_SETOPTIONS): %m"); |
|
1550 | die("ptrace(PTRACE_SETOPTIONS): %m"); |
|
1551 | ptrace(PTRACE_SYSCALL, box_pid, 0, 0); |
|
1551 | ptrace(PTRACE_SYSCALL, box_pid, 0, 0); |
|
1552 | } |
|
1552 | } |
|
1553 | else if (sig != SIGXCPU && sig != SIGXFSZ) |
|
1553 | else if (sig != SIGXCPU && sig != SIGXFSZ) |
|
1554 | { |
|
1554 | { |
|
1555 | msg(">> Signal %d\n", sig); |
|
1555 | msg(">> Signal %d\n", sig); |
|
1556 | sample_mem_peak(); /* Signal might be fatal, so update mem-peak */ |
|
1556 | sample_mem_peak(); /* Signal might be fatal, so update mem-peak */ |
|
1557 | ptrace(PTRACE_SYSCALL, box_pid, 0, sig); |
|
1557 | ptrace(PTRACE_SYSCALL, box_pid, 0, sig); |
|
1558 | } |
|
1558 | } |
|
1559 | else |
|
1559 | else |
|
1560 | { |
|
1560 | { |
|
1561 | meta_printf("exitsig:%d", sig); |
|
1561 | meta_printf("exitsig:%d", sig); |
|
1562 | err("SG: Received signal %d", sig); |
|
1562 | err("SG: Received signal %d", sig); |
|
1563 | } |
|
1563 | } |
|
1564 | } |
|
1564 | } |
|
1565 | else |
|
1565 | else |
|
1566 | die("wait4: unknown status %x, giving up!", stat); |
|
1566 | die("wait4: unknown status %x, giving up!", stat); |
|
1567 | } |
|
1567 | } |
|
1568 | } |
|
1568 | } |
|
1569 |
|
1569 | ||
|
1570 | static void |
|
1570 | static void |
|
1571 | box_inside(int argc, char **argv) |
|
1571 | box_inside(int argc, char **argv) |
|
1572 | { |
|
1572 | { |
|
1573 | struct rlimit rl; |
|
1573 | struct rlimit rl; |
|
1574 | char *args[argc+1]; |
|
1574 | char *args[argc+1]; |
|
1575 |
|
1575 | ||
|
1576 | memcpy(args, argv, argc * sizeof(char *)); |
|
1576 | memcpy(args, argv, argc * sizeof(char *)); |
|
1577 | args[argc] = NULL; |
|
1577 | args[argc] = NULL; |
|
1578 | if (set_cwd && chdir(set_cwd)) |
|
1578 | if (set_cwd && chdir(set_cwd)) |
|
1579 | die("chdir: %m"); |
|
1579 | die("chdir: %m"); |
|
1580 | if (redir_stdin) |
|
1580 | if (redir_stdin) |
|
1581 | { |
|
1581 | { |
|
1582 | close(0); |
|
1582 | close(0); |
|
1583 | if (open(redir_stdin, O_RDONLY) != 0) |
|
1583 | if (open(redir_stdin, O_RDONLY) != 0) |
|
1584 | die("open(\"%s\"): %m", redir_stdin); |
|
1584 | die("open(\"%s\"): %m", redir_stdin); |
|
1585 | } |
|
1585 | } |
|
1586 | if (redir_stdout) |
|
1586 | if (redir_stdout) |
|
1587 | { |
|
1587 | { |
|
1588 | close(1); |
|
1588 | close(1); |
|
1589 | if (open(redir_stdout, O_WRONLY | O_CREAT | O_TRUNC, 0666) != 1) |
|
1589 | if (open(redir_stdout, O_WRONLY | O_CREAT | O_TRUNC, 0666) != 1) |
|
1590 | die("open(\"%s\"): %m", redir_stdout); |
|
1590 | die("open(\"%s\"): %m", redir_stdout); |
|
1591 | } |
|
1591 | } |
|
1592 | if (redir_stderr) |
|
1592 | if (redir_stderr) |
|
1593 | { |
|
1593 | { |
|
1594 | close(2); |
|
1594 | close(2); |
|
1595 | if (open(redir_stderr, O_WRONLY | O_CREAT | O_TRUNC, 0666) != 2) |
|
1595 | if (open(redir_stderr, O_WRONLY | O_CREAT | O_TRUNC, 0666) != 2) |
|
1596 | die("open(\"%s\"): %m", redir_stderr); |
|
1596 | die("open(\"%s\"): %m", redir_stderr); |
|
1597 | } |
|
1597 | } |
|
1598 | else |
|
1598 | else |
|
1599 | dup2(1, 2); |
|
1599 | dup2(1, 2); |
|
1600 | setpgrp(); |
|
1600 | setpgrp(); |
|
1601 |
|
1601 | ||
|
1602 | if (memory_limit) |
|
1602 | if (memory_limit) |
|
1603 | { |
|
1603 | { |
|
1604 | rl.rlim_cur = rl.rlim_max = memory_limit * 1024; |
|
1604 | rl.rlim_cur = rl.rlim_max = memory_limit * 1024; |
|
1605 | if (setrlimit(RLIMIT_AS, &rl) < 0) |
|
1605 | if (setrlimit(RLIMIT_AS, &rl) < 0) |
|
1606 | die("setrlimit(RLIMIT_AS): %m"); |
|
1606 | die("setrlimit(RLIMIT_AS): %m"); |
|
1607 | } |
|
1607 | } |
|
1608 |
|
1608 | ||
|
1609 | rl.rlim_cur = rl.rlim_max = (stack_limit ? (rlim_t)stack_limit * 1024 : RLIM_INFINITY); |
|
1609 | rl.rlim_cur = rl.rlim_max = (stack_limit ? (rlim_t)stack_limit * 1024 : RLIM_INFINITY); |
|
1610 | if (setrlimit(RLIMIT_STACK, &rl) < 0) |
|
1610 | if (setrlimit(RLIMIT_STACK, &rl) < 0) |
|
1611 | die("setrlimit(RLIMIT_STACK): %m"); |
|
1611 | die("setrlimit(RLIMIT_STACK): %m"); |
|
1612 |
|
1612 | ||
|
1613 | rl.rlim_cur = rl.rlim_max = 64; |
|
1613 | rl.rlim_cur = rl.rlim_max = 64; |
|
1614 | if (setrlimit(RLIMIT_NOFILE, &rl) < 0) |
|
1614 | if (setrlimit(RLIMIT_NOFILE, &rl) < 0) |
|
1615 | die("setrlimit(RLIMIT_NOFILE): %m"); |
|
1615 | die("setrlimit(RLIMIT_NOFILE): %m"); |
|
1616 |
|
1616 | ||
|
1617 | char **env = setup_environment(); |
|
1617 | char **env = setup_environment(); |
|
1618 | if (filter_syscalls) |
|
1618 | if (filter_syscalls) |
|
1619 | { |
|
1619 | { |
|
1620 | if (ptrace(PTRACE_TRACEME) < 0) |
|
1620 | if (ptrace(PTRACE_TRACEME) < 0) |
|
1621 | die("ptrace(PTRACE_TRACEME): %m"); |
|
1621 | die("ptrace(PTRACE_TRACEME): %m"); |
|
1622 | /* Trick: Make sure that we are stopped until the boxkeeper wakes up. */ |
|
1622 | /* Trick: Make sure that we are stopped until the boxkeeper wakes up. */ |
|
1623 | raise(SIGSTOP); |
|
1623 | raise(SIGSTOP); |
|
1624 | } |
|
1624 | } |
|
1625 | execve(args[0], args, env); |
|
1625 | execve(args[0], args, env); |
|
1626 | die("execve(\"%s\"): %m", args[0]); |
|
1626 | die("execve(\"%s\"): %m", args[0]); |
|
1627 | } |
|
1627 | } |
|
1628 |
|
1628 | ||
|
1629 | static void |
|
1629 | static void |
|
1630 | usage(void) |
|
1630 | usage(void) |
|
1631 | { |
|
1631 | { |
|
1632 | fprintf(stderr, "Invalid arguments!\n"); |
|
1632 | fprintf(stderr, "Invalid arguments!\n"); |
|
1633 | printf("\ |
|
1633 | printf("\ |
|
1634 | Usage: box [<options>] -- <command> <arguments>\n\ |
|
1634 | Usage: box [<options>] -- <command> <arguments>\n\ |
|
1635 | \n\ |
|
1635 | \n\ |
|
1636 | Options:\n\ |
|
1636 | Options:\n\ |
|
1637 | -a <level>\tSet file access level (0=none, 1=cwd, 2=/etc,/lib,..., 3=whole fs, 9=no checks; needs -f)\n\ |
|
1637 | -a <level>\tSet file access level (0=none, 1=cwd, 2=/etc,/lib,..., 3=whole fs, 9=no checks; needs -f)\n\ |
|
1638 | -c <dir>\tChange directory to <dir> first\n\ |
|
1638 | -c <dir>\tChange directory to <dir> first\n\ |
|
1639 | -e\t\tInherit full environment of the parent process\n\ |
|
1639 | -e\t\tInherit full environment of the parent process\n\ |
|
1640 | -E <var>\tInherit the environment variable <var> from the parent process\n\ |
|
1640 | -E <var>\tInherit the environment variable <var> from the parent process\n\ |
|
1641 | -E <var>=<val>\tSet the environment variable <var> to <val>; unset it if <var> is empty\n\ |
|
1641 | -E <var>=<val>\tSet the environment variable <var> to <val>; unset it if <var> is empty\n\ |
|
1642 | -f\t\tFilter system calls (-ff=very restricted)\n\ |
|
1642 | -f\t\tFilter system calls (-ff=very restricted)\n\ |
|
1643 | -i <file>\tRedirect stdin from <file>\n\ |
|
1643 | -i <file>\tRedirect stdin from <file>\n\ |
|
1644 | -k <size>\tLimit stack size to <size> KB (default: 0=unlimited)\n\ |
|
1644 | -k <size>\tLimit stack size to <size> KB (default: 0=unlimited)\n\ |
|
1645 | -m <size>\tLimit address space to <size> KB\n\ |
|
1645 | -m <size>\tLimit address space to <size> KB\n\ |
|
1646 | -M <file>\tOutput process information to <file> (name:value)\n\ |
|
1646 | -M <file>\tOutput process information to <file> (name:value)\n\ |
|
1647 | -o <file>\tRedirect stdout to <file>\n\ |
|
1647 | -o <file>\tRedirect stdout to <file>\n\ |
|
1648 | -p <path>\tPermit access to the specified path (or subtree if it ends with a `/')\n\ |
|
1648 | -p <path>\tPermit access to the specified path (or subtree if it ends with a `/')\n\ |
|
1649 | -p <path>=<act>\tDefine action for the specified path (<act>=yes/no)\n\ |
|
1649 | -p <path>=<act>\tDefine action for the specified path (<act>=yes/no)\n\ |
|
1650 | -r <file>\tRedirect stderr to <file>\n\ |
|
1650 | -r <file>\tRedirect stderr to <file>\n\ |
|
1651 | -s <sys>\tPermit the specified syscall (be careful)\n\ |
|
1651 | -s <sys>\tPermit the specified syscall (be careful)\n\ |
|
1652 | -s <sys>=<act>\tDefine action for the specified syscall (<act>=yes/no/file)\n\ |
|
1652 | -s <sys>=<act>\tDefine action for the specified syscall (<act>=yes/no/file)\n\ |
|
1653 | -t <time>\tSet run time limit (seconds, fractions allowed)\n\ |
|
1653 | -t <time>\tSet run time limit (seconds, fractions allowed)\n\ |
|
1654 | -T\t\tAllow syscalls for measuring run time\n\ |
|
1654 | -T\t\tAllow syscalls for measuring run time\n\ |
|
1655 | -v\t\tBe verbose (use multiple times for even more verbosity)\n\ |
|
1655 | -v\t\tBe verbose (use multiple times for even more verbosity)\n\ |
|
1656 | -w <time>\tSet wall clock time limit (seconds, fractions allowed)\n\ |
|
1656 | -w <time>\tSet wall clock time limit (seconds, fractions allowed)\n\ |
|
1657 | -x <time>\tSet extra timeout, before which a timing-out program is not yet killed,\n\ |
|
1657 | -x <time>\tSet extra timeout, before which a timing-out program is not yet killed,\n\ |
|
1658 | \t\tso that its real execution time is reported (seconds, fractions allowed)\n\ |
|
1658 | \t\tso that its real execution time is reported (seconds, fractions allowed)\n\ |
|
|
1659 | + -A <opt>\tPass <opt> as additional argument to the <command>\n\ | ||
|
|
1660 | + \t\tBe noted that this option will be appended after <arguments> respectively\n\ | ||
|
1659 | "); |
|
1661 | "); |
|
1660 | exit(2); |
|
1662 | exit(2); |
|
1661 | } |
|
1663 | } |
|
1662 |
|
1664 | ||
|
1663 | int |
|
1665 | int |
|
1664 | main(int argc, char **argv) |
|
1666 | main(int argc, char **argv) |
|
1665 | { |
|
1667 | { |
|
1666 | int c; |
|
1668 | int c; |
|
1667 | uid_t uid; |
|
1669 | uid_t uid; |
|
|
1670 | + char **prog_argv = xmalloc(sizeof(char*) * argc); | ||
|
|
1671 | + int prog_argc = 0; | ||
|
1668 |
|
1672 | ||
|
1669 | - while ((c = getopt(argc, argv, "a:c:eE:fi:k:m:M:o:p:r:s:t:Tvw:x:")) >= 0) |
|
1673 | + while ((c = getopt(argc, argv, "a:c:eE:fi:k:m:M:o:p:r:s:t:Tvw:x:A:")) >= 0) |
|
1670 | switch (c) |
|
1674 | switch (c) |
|
1671 | { |
|
1675 | { |
|
1672 | case 'a': |
|
1676 | case 'a': |
|
1673 | file_access = atol(optarg); |
|
1677 | file_access = atol(optarg); |
|
1674 | break; |
|
1678 | break; |
|
1675 | case 'c': |
|
1679 | case 'c': |
|
1676 | set_cwd = optarg; |
|
1680 | set_cwd = optarg; |
|
1677 | break; |
|
1681 | break; |
|
1678 | case 'e': |
|
1682 | case 'e': |
|
1679 | pass_environ = 1; |
|
1683 | pass_environ = 1; |
|
1680 | break; |
|
1684 | break; |
|
1681 | case 'E': |
|
1685 | case 'E': |
|
1682 | if (!set_env_action(optarg)) |
|
1686 | if (!set_env_action(optarg)) |
|
1683 | usage(); |
|
1687 | usage(); |
|
1684 | break; |
|
1688 | break; |
|
1685 | case 'f': |
|
1689 | case 'f': |
|
1686 | filter_syscalls++; |
|
1690 | filter_syscalls++; |
|
1687 | break; |
|
1691 | break; |
|
1688 | case 'k': |
|
1692 | case 'k': |
|
1689 | stack_limit = atol(optarg); |
|
1693 | stack_limit = atol(optarg); |
|
1690 | break; |
|
1694 | break; |
|
1691 | case 'i': |
|
1695 | case 'i': |
|
1692 | redir_stdin = optarg; |
|
1696 | redir_stdin = optarg; |
|
1693 | break; |
|
1697 | break; |
|
1694 | case 'm': |
|
1698 | case 'm': |
|
1695 | memory_limit = atol(optarg); |
|
1699 | memory_limit = atol(optarg); |
|
1696 | break; |
|
1700 | break; |
|
1697 | case 'M': |
|
1701 | case 'M': |
|
1698 | meta_open(optarg); |
|
1702 | meta_open(optarg); |
|
1699 | break; |
|
1703 | break; |
|
1700 | case 'o': |
|
1704 | case 'o': |
|
1701 | redir_stdout = optarg; |
|
1705 | redir_stdout = optarg; |
|
1702 | break; |
|
1706 | break; |
|
1703 | case 'p': |
|
1707 | case 'p': |
|
1704 | if (!set_path_action(optarg)) |
|
1708 | if (!set_path_action(optarg)) |
|
1705 | usage(); |
|
1709 | usage(); |
|
1706 | break; |
|
1710 | break; |
|
1707 | case 'r': |
|
1711 | case 'r': |
|
1708 | redir_stderr = optarg; |
|
1712 | redir_stderr = optarg; |
|
1709 | break; |
|
1713 | break; |
|
1710 | case 's': |
|
1714 | case 's': |
|
1711 | if (!set_syscall_action(optarg)) |
|
1715 | if (!set_syscall_action(optarg)) |
|
1712 | usage(); |
|
1716 | usage(); |
|
1713 | break; |
|
1717 | break; |
|
1714 | case 't': |
|
1718 | case 't': |
|
1715 | timeout = 1000*atof(optarg); |
|
1719 | timeout = 1000*atof(optarg); |
|
1716 | break; |
|
1720 | break; |
|
1717 | case 'T': |
|
1721 | case 'T': |
|
1718 | syscall_action[__NR_times] = A_YES; |
|
1722 | syscall_action[__NR_times] = A_YES; |
|
1719 | break; |
|
1723 | break; |
|
1720 | case 'v': |
|
1724 | case 'v': |
|
1721 | verbose++; |
|
1725 | verbose++; |
|
1722 | break; |
|
1726 | break; |
|
1723 | case 'w': |
|
1727 | case 'w': |
|
1724 | wall_timeout = 1000*atof(optarg); |
|
1728 | wall_timeout = 1000*atof(optarg); |
|
1725 | break; |
|
1729 | break; |
|
1726 | case 'x': |
|
1730 | case 'x': |
|
1727 | extra_timeout = 1000*atof(optarg); |
|
1731 | extra_timeout = 1000*atof(optarg); |
|
|
1732 | + case 'A': | ||
|
|
1733 | + prog_argv[prog_argc++] = strdup(optarg); | ||
|
|
1734 | + break; | ||
|
1728 | break; |
|
1735 | break; |
|
1729 | default: |
|
1736 | default: |
|
1730 | usage(); |
|
1737 | usage(); |
|
1731 | } |
|
1738 | } |
|
1732 | if (optind >= argc) |
|
1739 | if (optind >= argc) |
|
1733 | usage(); |
|
1740 | usage(); |
|
1734 |
|
1741 | ||
|
1735 | sanity_check(); |
|
1742 | sanity_check(); |
|
1736 | uid = geteuid(); |
|
1743 | uid = geteuid(); |
|
1737 | if (setreuid(uid, uid) < 0) |
|
1744 | if (setreuid(uid, uid) < 0) |
|
1738 | die("setreuid: %m"); |
|
1745 | die("setreuid: %m"); |
|
1739 | box_pid = fork(); |
|
1746 | box_pid = fork(); |
|
1740 | if (box_pid < 0) |
|
1747 | if (box_pid < 0) |
|
1741 | die("fork: %m"); |
|
1748 | die("fork: %m"); |
|
1742 | - if (!box_pid) |
|
1749 | + if (!box_pid) { |
|
1743 | - box_inside(argc-optind, argv+optind); |
|
1750 | + int real_argc = prog_argc + argc - optind; |
|
1744 | - else |
|
1751 | + char **real_argv = xmalloc(sizeof(char*) * (real_argc)); |
|
|
1752 | + for (int i = 0;i < argc-optind;i++) | ||
|
|
1753 | + real_argv[i] = strdup(argv[i+optind]); | ||
|
|
1754 | + for (int i = 0;i < prog_argc;i++) | ||
|
|
1755 | + real_argv[argc - optind + i] = strdup(prog_argv[i]); | ||
|
|
1756 | + box_inside(real_argc, real_argv); | ||
|
|
1757 | + } else | ||
|
1745 | boxkeeper(); |
|
1758 | boxkeeper(); |
|
1746 | die("Internal error: fell over edge of the world"); |
|
1759 | die("Internal error: fell over edge of the world"); |
|
1747 | } |
|
1760 | } |
You need to be logged in to leave comments.
Login now