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:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

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