// $Id: reducecap.c 2279 2006-01-22 19:31:53Z ensc $ // Copyright (C) 2003 Enrico Scholz // based on reducecap.cc by Jacques Gelinas // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef HAVE_CONFIG_H # include #endif #include "util.h" #include "vserver.h" #include #include #include #include #include #include #include #define ENSC_WRAPPERS_PREFIX "reducecap: " #define ENSC_WRAPPERS_VSERVER 1 #define ENSC_WRAPPERS_UNISTD 1 #include #undef _POSIX_SOURCE #include "capability-compat.h" #define CMD_HELP 0x1000 #define CMD_VERSION 0x1001 #define CMD_SHOW 0x2000 #define CMD_PID 0x2001 #define CMD_CAP 0x4000 #define CMD_FLAG 0x4004 #define CMD_SECURE 0x4006 #ifdef VC_ENABLE_API_LEGACY # define CMD_OBSOLETE_CHOWN 0x8000 # define CMD_OBSOLETE_DAC_OVERRIDE 0x8001 # define CMD_OBSOLETE_DAC_READ_SEARCH 0x8002 # define CMD_OBSOLETE_FOWNER 0x8003 # define CMD_OBSOLETE_FSETID 0x8004 # define CMD_OBSOLETE_KILL 0x8005 # define CMD_OBSOLETE_SETGID 0x8006 # define CMD_OBSOLETE_SETUID 0x8007 # define CMD_OBSOLETE_SETPCAP 0x8008 # define CMD_OBSOLETE_SYS_TTY_CONFIG 0x8009 # define CMD_OBSOLETE_LEASE 0x800a # define CMD_OBSOLETE_SYS_CHROOT 0x800b # define CMD_OBSOLETE_X_LINUX_IMMUTABLE 0x800c # define CMD_OBSOLETE_X_NET_BIND_SERVICE 0x800d # define CMD_OBSOLETE_X_NET_BROADCAST 0x800e # define CMD_OBSOLETE_X_NET_ADMIN 0x800f # define CMD_OBSOLETE_X_NET_RAW 0x8010 # define CMD_OBSOLETE_X_IPC_LOCK 0x8011 # define CMD_OBSOLETE_X_IPC_OWNER 0x8012 # define CMD_OBSOLETE_X_SYS_MODULE 0x8013 # define CMD_OBSOLETE_X_SYS_RAWIO 0x8014 # define CMD_OBSOLETE_X_SYS_PACCT 0x8015 # define CMD_OBSOLETE_X_SYS_ADMIN 0x8016 # define CMD_OBSOLETE_X_SYS_BOOT 0x8017 # define CMD_OBSOLETE_X_SYS_NICE 0x8018 # define CMD_OBSOLETE_X_SYS_RESOURCE 0x8019 # define CMD_OBSOLETE_X_SYS_TIME 0x801a # define CMD_OBSOLETE_X_MKNOD 0x801b # define CMD_OBSOLETE_X_QUOTACTL 0x801c static char const * const OBSOLETE_MAPPING[] = { // 0 1 2 3 "CHOWN", "DAC_OVERRIDE", "DAC_READ_SEARCH", "FOWNER", "FSETID", "KILL", "SETGID", "SETUID", "SETPCAP", "SYS_TTY_CONFIG", "LEASE", "SYS_CHROOT", "LINUX_IMMUTABLE", "NET_BIND_SERVICE", "NET_BROADCAST", "NET_ADMIN", "NET_RAW", "IPC_LOCK", "IPC_OWNER", "SYS_MODULE", "SYS_RAWIO", "SYS_PACCT", "SYS_ADMIN", "SYS_BOOT", "SYS_NICE", "SYS_RESOURCE", "SYS_TIME", "MKNOD", "QUOTACTL" }; #endif struct option const CMDLINE_OPTIONS[] = { { "help", no_argument, 0, CMD_HELP }, { "version", no_argument, 0, CMD_VERSION }, { "cap", required_argument, 0, CMD_CAP }, { "flag", required_argument, 0, CMD_FLAG }, { "secure", no_argument, 0, CMD_SECURE }, { "show", no_argument, 0, CMD_SHOW }, { "pid", required_argument, 0, CMD_PID }, #ifdef VC_ENABLE_API_LEGACY { "CAP_CHOWN", no_argument, 0, CMD_OBSOLETE_CHOWN }, { "CAP_DAC_OVERRIDE", no_argument, 0, CMD_OBSOLETE_DAC_OVERRIDE }, { "CAP_DAC_READ_SEARCH", no_argument, 0, CMD_OBSOLETE_DAC_READ_SEARCH }, { "CAP_FOWNER", no_argument, 0, CMD_OBSOLETE_FOWNER }, { "CAP_FSETID", no_argument, 0, CMD_OBSOLETE_FSETID }, { "CAP_KILL", no_argument, 0, CMD_OBSOLETE_KILL }, { "CAP_SETGID", no_argument, 0, CMD_OBSOLETE_SETGID }, { "CAP_SETUID", no_argument, 0, CMD_OBSOLETE_SETUID }, { "CAP_SETPCAP", no_argument, 0, CMD_OBSOLETE_SETPCAP }, { "CAP_SYS_TTY_CONFIG", no_argument, 0, CMD_OBSOLETE_SYS_TTY_CONFIG }, { "CAP_LEASE", no_argument, 0, CMD_OBSOLETE_LEASE }, { "CAP_SYS_CHROOT", no_argument, 0, CMD_OBSOLETE_SYS_CHROOT }, { "--CAP_LINUX_IMMUTABLE", no_argument, 0, CMD_OBSOLETE_X_LINUX_IMMUTABLE }, { "--CAP_NET_BIND_SERVICE", no_argument, 0, CMD_OBSOLETE_X_NET_BIND_SERVICE }, { "--CAP_NET_BROADCAST", no_argument, 0, CMD_OBSOLETE_X_NET_BROADCAST }, { "--CAP_NET_ADMIN", no_argument, 0, CMD_OBSOLETE_X_NET_ADMIN }, { "--CAP_NET_RAW", no_argument, 0, CMD_OBSOLETE_X_NET_RAW }, { "--CAP_IPC_LOCK", no_argument, 0, CMD_OBSOLETE_X_IPC_LOCK }, { "--CAP_IPC_OWNER", no_argument, 0, CMD_OBSOLETE_X_IPC_OWNER }, { "--CAP_SYS_MODULE", no_argument, 0, CMD_OBSOLETE_X_SYS_MODULE }, { "--CAP_SYS_RAWIO", no_argument, 0, CMD_OBSOLETE_X_SYS_RAWIO }, { "--CAP_SYS_PACCT", no_argument, 0, CMD_OBSOLETE_X_SYS_PACCT }, { "--CAP_SYS_ADMIN", no_argument, 0, CMD_OBSOLETE_X_SYS_ADMIN }, { "--CAP_SYS_BOOT", no_argument, 0, CMD_OBSOLETE_X_SYS_BOOT }, { "--CAP_SYS_NICE", no_argument, 0, CMD_OBSOLETE_X_SYS_NICE }, { "--CAP_SYS_RESOURCE", no_argument, 0, CMD_OBSOLETE_X_SYS_RESOURCE }, { "--CAP_SYS_TIME", no_argument, 0, CMD_OBSOLETE_X_SYS_TIME }, { "--CAP_MKNOD", no_argument, 0, CMD_OBSOLETE_X_MKNOD }, { "--CAP_QUOTACTL", no_argument, 0, CMD_OBSOLETE_X_QUOTACTL }, #endif { 0,0,0,0 } }; int wrapper_exit_code = 255; static void showHelp(int fd, char const *cmd, int res) { #if !defined(VC_ENABLE_API_COMPAT) && !defined(VC_ENABLE_API_LEGACY) WRITE_MSG(1, "ERROR: tools were built without legacy API support; reducecap will not work!\n\n"); #endif WRITE_MSG(fd, "Usage:\n "); WRITE_STR(fd, cmd); WRITE_MSG(fd, " [--show] [--secure] [--flag ] [--cap ] [--] *\n "); WRITE_STR(fd, cmd); WRITE_MSG(fd, " --show [--pid ]\n\n" "Please report bugs to " PACKAGE_BUGREPORT "\n"); exit(res); } static void showVersion() { WRITE_MSG(1, "reducecap " VERSION " -- starts programs with reduced capabilities\n" "This program is part of " PACKAGE_STRING "\n\n" "Copyright (C) 2003,2004 Enrico Scholz\n" VERSION_COPYRIGHT_DISCLAIMER); exit(0); } static void printReducecap(struct __user_cap_data_struct *user) { int i; WRITE_MSG(1, " Capability Effective Permitted Inheritable\n"); for (i=0;; ++i) { size_t const len = 23 + 10*2 + 4+2; char const * text = vc_cap2text(i); int bit = 1<effective & bit) ? 'X' : ' '; buf[23 + 10*1 + 4] = (user->permitted & bit) ? 'X' : ' '; buf[23 + 10*2 + 4] = (user->inheritable & bit) ? 'X' : ' '; Vwrite(1, buf, len); } } static void show(pid_t pid) { struct __user_cap_header_struct header; struct __user_cap_data_struct user; header.version = _LINUX_CAPABILITY_VERSION; header.pid = pid; if (capget(&header,&user)==-1){ perror ("reducecap: capget()"); exit(wrapper_exit_code); } printReducecap(&user); } #if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_LEGACY) static uint32_t getCap(char const *cap) { int bit = vc_text2cap(cap); if (bit!=0) { WRITE_MSG(2, "Unknown capability '"); WRITE_STR(2, optarg); WRITE_MSG(2, "'; try '--help' for more information\n"); exit(wrapper_exit_code); } return (1<=CMD_OBSOLETE_CHOWN && c<=CMD_OBSOLETE_X_QUOTACTL) { if (show_obsolete_warning) { WRITE_MSG(2, "reducecap: warning, obsolete CLI used\n"); show_obsolete_warning = false; } remove = getCap(OBSOLETE_MAPPING[c-CMD_OBSOLETE_CHOWN]); continue; } #endif switch (c) { case CMD_HELP : showHelp(1, argv[0], 0); case CMD_VERSION : showVersion(); case CMD_SHOW : do_show = true; break; case CMD_PID : pid = atoi(optarg); break; #if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_LEGACY) case CMD_SECURE : remove = vc_get_insecurebcaps(); break; case CMD_CAP : remove = getCap(optarg); break; case CMD_FLAG : { struct vc_err_listparser err; flags = vc_list2cflag_compat(optarg, 0, &err); if (err.ptr!=0) { WRITE_MSG(2, "Unknown flag '"); Vwrite(2, err.ptr, err.len); WRITE_MSG(2, "'\n"); exit(wrapper_exit_code); } break; } #else case CMD_SECURE : case CMD_CAP : case CMD_FLAG : flags = 0; remove = 0; break; #endif } } if (!do_show && optind==argc) { WRITE_MSG(2, "No command given; use '--help' for more information\n"); exit(wrapper_exit_code); } if (!do_show && pid!=0) { WRITE_MSG(2, "A pid can be specified in '--show' mode only; use '--help' for more information\n"); exit(wrapper_exit_code); } if (do_show && optind==argc) show(pid); #if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_LEGACY) else { Evc_new_s_context(VC_SAMECTX, remove, flags); if (do_show) show(pid); WRITE_MSG(2, "Executing\n"); Eexecvp(argv[optind], argv+optind); } #else else if (do_show) show(pid); else { WRITE_MSG(2, "reducecap: tools were built without legacy API support; can not continue\n"); exit(wrapper_exit_code); } #endif return EXIT_SUCCESS; }