Index: bin/dd/dd.c =================================================================== --- bin/dd/dd.c +++ bin/dd/dd.c @@ -48,8 +48,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -58,9 +60,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -92,6 +96,10 @@ jcl(argv); setup(); + (void)catopen("libc", NL_CAT_LOCALE); + if (cap_enter() == -1 && errno != ENOSYS) + err(1, "unable to enter capability mode"); + (void)signal(SIGINFO, siginfo_handler); (void)signal(SIGINT, terminate); @@ -125,6 +133,9 @@ setup(void) { u_int cnt; + cap_rights_t rights, std_rights; + unsigned long std_cmds[] = { TIOCGETA, TIOCGWINSZ }; + unsigned long tape_cmds[] = { FIODTYPE, MTIOCTOP }; if (in.name == NULL) { in.name = "stdin"; @@ -133,13 +144,26 @@ in.fd = open(in.name, O_RDONLY, 0); if (in.fd == -1) err(1, "%s", in.name); + cap_rights_init(&std_rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, CAP_READ); + if (cap_rights_limit(STDIN_FILENO, &std_rights) < 0 && errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (cap_ioctls_limit(STDIN_FILENO, std_cmds, nitems(std_cmds)) == -1 && + errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (cap_fcntls_limit(STDIN_FILENO, CAP_FCNTL_GETFL) == -1 && errno != ENOSYS) + err(1, "unable to limit capability rights"); } getfdtype(&in); + cap_rights_init(&rights, CAP_READ, CAP_SEEK); + if (cap_rights_limit(in.fd, &rights) == -1 && errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (files_cnt > 1 && !(in.flags & ISTAPE)) errx(1, "files is not supported for non-tape devices"); + cap_rights_set(&rights, CAP_FTRUNCATE, CAP_IOCTL, CAP_WRITE); if (out.name == NULL) { /* No way to check for read access here. */ out.fd = STDOUT_FILENO; @@ -156,13 +180,39 @@ if (out.fd == -1) { out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE); out.flags |= NOREAD; + cap_rights_clear(&rights, CAP_READ); } if (out.fd == -1) err(1, "%s", out.name); + cap_rights_init(&std_rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, CAP_WRITE); + if (cap_rights_limit(STDOUT_FILENO, &std_rights) < 0 && errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (cap_ioctls_limit(STDOUT_FILENO, std_cmds, nitems(std_cmds)) == -1 && + errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (cap_fcntls_limit(STDOUT_FILENO, CAP_FCNTL_GETFL) == -1 && errno != ENOSYS) + err(1, "unable to limit capability rights"); } getfdtype(&out); + if (cap_rights_limit(out.fd, &rights) == -1 && errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (cap_ioctls_limit(out.fd, tape_cmds, nitems(tape_cmds)) == -1 && + errno != ENOSYS) + err(1, "unable to limit capability rights"); + + if (in.fd != STDERR_FILENO && out.fd != STDERR_FILENO) { + cap_rights_init(&std_rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, CAP_WRITE); + if (cap_rights_limit(STDERR_FILENO, &std_rights) < 0 && errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (cap_ioctls_limit(STDERR_FILENO, std_cmds, nitems(std_cmds)) == -1 && + errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (cap_fcntls_limit(STDERR_FILENO, CAP_FCNTL_GETFL) == -1 && errno != ENOSYS) + err(1, "unable to limit capability rights"); + } + /* * Allocate space for the input and output buffers. If not doing * record oriented I/O, only need a single buffer.