#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include "compat.h"
+
+#include "vserver.h"
+#include "util.h"
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
-#include <netinet/in.h>
#include <net/if.h>
#include <unistd.h>
#include <errno.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
-#include "vserver.h"
+#define ENSC_WRAPPERS_IO 1
+#define ENSC_WRAPPERS_UNISTD 1
+#include "wrappers.h"
+
+#define CMD_HELP 0x1000
+#define CMD_VERSION 0x1001
+
+#define CMD_SILENT 0x2000
+#define CMD_IP 0x2001
+#define CMD_BCAST 0x2002
+
+int wrapper_exit_code = 255;
+
+
+static struct option const
+CMDLINE_OPTIONS[] = {
+ { "help", no_argument, 0, CMD_HELP },
+ { "version", no_argument, 0, CMD_VERSION },
+ { "silent", no_argument, 0, CMD_SILENT },
+ { "ip", required_argument, 0, CMD_IP },
+ { "bcast", required_argument, 0, CMD_BCAST },
+ { 0,0,0,0 }
+};
+
+static void
+showHelp(int fd, char const *cmd, int res)
+{
+ WRITE_MSG(fd, "Usage:\n ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " [--silent] [--ip <ip_num>[/<mask>]] [--bcast <broadcast>] [--] <commands> <args>*\n\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+
+ exit(res);
+}
-static void usage()
+static void
+showVersion()
{
- fprintf (stderr,"chbind version %s\n",VERSION);
- fprintf (stderr,"chbind [ --silent ] [ --ip ip_num[/mask] ] [ --bcast broadcast ] command argument\n");
- exit (-1);
+ WRITE_MSG(1,
+ "chbind " VERSION " -- bind to an ip and execute a program\n"
+ "This program is part of " PACKAGE_STRING "\n\n"
+ "Copyright (C) 2003,2004 Enrico Scholz\n"
+ VERSION_COPYRIGHT_DISCLAIMER);
+ exit(0);
}
/*
Return != 0 if the device exist.
*/
-static int chbind_devexist (const char *dev)
+static bool
+existsDevice(char const *dev_raw)
{
- int ret = 0;
- FILE *fin = fopen ("/proc/net/dev","r");
- if (fin != NULL){
- int len = strlen(dev);
- char buf[1000];
- fgets(buf,sizeof(buf)-1,fin); // Skip one line
- while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
- const char *pt = strstr(buf,dev);
- if (pt != NULL && pt[len] == ':'){
- ret = 1;
- break;
- }
- }
- fclose (fin);
- }
- return ret;
-}
+ size_t buf_size=8192;
+ char dev[strlen(dev_raw)+2];
+
+ strcpy(dev, dev_raw);
+ strcat(dev, ":");
+ for (;;) {
+ char buf[buf_size];
+ char * pos;
+ bool too_small;
+ int fd=open("/proc/net/dev", O_RDONLY);
+
+ if (fd==-1) return false;
+ too_small = EreadAll(fd, buf, buf_size);
+ close(fd);
+ if (too_small) {
+ buf_size *= 2;
+ continue;
+ }
+
+ pos = strstr(buf, dev);
+ return (pos && (pos==buf || pos[-1]==' ' || pos[-1]=='\n'));
+ }
+}
static int ifconfig_ioctl(
int fd,
*/
int ifconfig_getaddr (
const char *ifname,
- unsigned long *addr,
- unsigned long *mask,
- unsigned long *bcast)
+ uint32_t *addr,
+ uint32_t *mask,
+ uint32_t *bcast)
{
int ret = -1;
- if (chbind_devexist(ifname)){
+ if (existsDevice(ifname)){
int skfd = socket(AF_INET, SOCK_DGRAM, 0);
*addr = 0;
*bcast = 0xffffffff;
return ret;
}
+static void
+readIP(char const *str, struct vc_ip_mask_pair *ip, uint32_t *bcast)
+{
+ if (ifconfig_getaddr(str, &ip->ip, &ip->mask, bcast)==-1) {
+ char *pt;
+ char tmpopt[strlen(str)+1];
+ struct hostent *h;
+
+ strcpy(tmpopt,str);
+ pt = strchr(tmpopt,'/');
+
+ if (pt==0)
+ ip->mask = ntohl(0xffffff00);
+ else {
+ *pt++ = '\0';
+
+ // Ok, we have a network size, not a netmask
+ if (strchr(pt,'.')==0) {
+ int sz = atoi(pt);
+ ;
+ for (ip->mask = 0; sz>0; --sz) {
+ ip->mask >>= 1;
+ ip->mask |= 0x80000000;
+ }
+ ip->mask = ntohl(ip->mask);
+ }
+ else {
+ struct hostent *h = gethostbyname (pt);
+ if (h==0) {
+ WRITE_MSG(2, "Invalid netmask '");
+ WRITE_STR(2, pt);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+
+ memcpy (&ip->mask, h->h_addr, sizeof(ip->mask));
+ }
+ }
+ h = gethostbyname (tmpopt);
+ if (h==0) {
+ WRITE_MSG(2, "Invalid IP number or host name '");
+ WRITE_STR(2, tmpopt);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+ memcpy (&ip->ip, h->h_addr,sizeof(ip->ip));
+ }
+}
+
+static void
+readBcast(char const *str, uint32_t *bcast)
+{
+ uint32_t tmp;
+ if (ifconfig_getaddr(str, &tmp, &tmp, bcast)==-1){
+ struct hostent *h = gethostbyname (str);
+ if (h==0){
+ WRITE_MSG(2, "Invalid broadcast number '");
+ WRITE_STR(2, optarg);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+ memcpy (bcast, h->h_addr,sizeof(*bcast));
+ }
+}
int main (int argc, char *argv[])
{
- int ret = -1;
- int silent = 0;
- int i;
- struct vc_ip_mask_pair ips[16];
- int nbaddrs = 0;
- unsigned long bcast = 0xffffffff;
- for (i=1; i<argc; i++){
- const char *arg = argv[i];
- const char *opt = argv[i+1];
- if (strcmp(arg,"--ip")==0){
- unsigned long addr,mask;
- if (nbaddrs == 16){
- fprintf (stderr,"Too many IP numbers, max 16, ignored\n");
-
- }else if (ifconfig_getaddr(opt,&addr,&mask,&bcast)==-1){
- unsigned long mask = 0x00ffffff;
- const char *pt = strchr(opt,'/');
- char tmpopt[strlen(opt)+1];
- struct hostent *h;
-
- if (pt != NULL){
- strcpy (tmpopt,opt);
- tmpopt[pt-opt] = '\0';
- opt = tmpopt;
- pt++;
- if (strchr(pt,'.')==NULL){
- // Ok, we have a network size, not a netmask
- int size = atoi(pt);
- int i;
- mask = 0;
- for (i=0; i<size; i++){
- mask = mask >> 1;
- mask |= 0x80000000;
- }
- mask = ntohl(mask);
- }else{
- struct hostent *h = gethostbyname (pt);
- if (h != NULL){
- memcpy (&mask,h->h_addr,sizeof(mask));
- }else{
- fprintf (stderr,"Invalid netmask: %s\n",pt);
- usage();
- }
- }
-
- }
-
- h = gethostbyname (opt);
- if (h == NULL){
- fprintf (stderr,"Invalid IP number or host name: %s\n",opt);
- usage();
- }else{
- memcpy (&addr,h->h_addr,sizeof(addr));
- ips[nbaddrs].ip = addr;
- ips[nbaddrs].mask = mask;
- ++nbaddrs;
- }
- }else{
- ips[nbaddrs].ip = addr;
- ips[nbaddrs].mask = mask;
- ++nbaddrs;
- }
- i++;
- }else if (strcmp(arg,"--bcast")==0){
- unsigned long tmp;
- if (ifconfig_getaddr(opt,&tmp,&tmp,&bcast)==-1){
- struct hostent *h = gethostbyname (opt);
- if (h == NULL){
- fprintf (stderr,"Invalid broadcast number: %s\n",opt);
- usage();
- }else{
- memcpy (&bcast,h->h_addr,sizeof(bcast));
- }
- }
- i++;
- }else if (strcmp(arg,"--silent")==0){
- silent = 1;
- }else{
- break;
- }
- }
- if (i == argc){
- usage();
- }else if (argv[i][0] == '-'){
- usage();
- }else{
- if (vc_set_ipv4root(bcast,nbaddrs,ips)==0){
- if (!silent){
- int i;
- printf ("ipv4root is now");
- for (i=0; i<nbaddrs; i++){
- unsigned long hostaddr = ntohl(ips[i].ip);
- printf (" %ld.%ld.%ld.%ld"
- ,hostaddr>>24
- ,(hostaddr>>16)&0xff
- ,(hostaddr>>8)&0xff
- ,hostaddr &0xff);
- }
- printf ("\n");
- }
- execvp (argv[i],argv+i);
- fprintf (stderr,"Can't exec %s (%s)\n",argv[i],strerror(errno));
- }else{
- fprintf (stderr,"Can't set the ipv4 root (%s)\n",strerror(errno));
- }
+ bool is_silent = false;
+ struct vc_ip_mask_pair ips[16];
+ size_t nbaddrs = 0;
+ uint32_t bcast = 0xffffffff;
+
+ while (1) {
+ int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
+ if (c==-1) break;
+
+ switch (c) {
+ case CMD_HELP : showHelp(1, argv[0], 0);
+ case CMD_VERSION : showVersion();
+ case CMD_SILENT : is_silent = true; break;
+ case CMD_BCAST : readBcast(optarg, &bcast); break;
+ case CMD_IP :
+ if (nbaddrs>=16) {
+ WRITE_MSG(2, "Too many IP numbers, max 16\n");
+ exit(wrapper_exit_code);
}
- return ret;
+ readIP(optarg, ips+nbaddrs, &bcast);
+ ++nbaddrs;
+ break;
+ default :
+ WRITE_MSG(2, "Try '");
+ WRITE_STR(2, argv[0]);
+ WRITE_MSG(2, " --help\" for more information.\n");
+ exit(wrapper_exit_code);
+ break;
+ }
+ }
+
+ if (optind==argc) {
+ WRITE_MSG(2, "No command given; try '--help' for more information\n");
+ exit(wrapper_exit_code);
+ }
+
+
+ if (vc_set_ipv4root(bcast,nbaddrs,ips)!=0) {
+ perror("vc_set_ipv4root()");
+ exit(wrapper_exit_code);
+ }
+
+ if (!is_silent) {
+ size_t i;
+
+ WRITE_MSG(1, "ipv4root is now");
+ for (i=0; i<nbaddrs; ++i) {
+ WRITE_MSG(1, " ");
+ WRITE_STR(1, inet_ntoa(*reinterpret_cast(struct in_addr *)(&ips[i].ip)));
+ }
+ WRITE_MSG(1, "\n");
+ }
+
+ Eexecvp (argv[optind],argv+optind);
+ return EXIT_SUCCESS;
}
+#ifdef ENSC_TESTSUITE
+#include <assert.h>
+void test()
+{
+ struct vc_ip_mask_pair ip;
+ uint32_t bcast;
+
+ bcast = 0;
+ readIP("1.2.3.4", &ip, &bcast);
+ assert(ip.ip==ntohl(0x01020304) && ip.mask==ntohl(0xffffff00) && bcast==0);
+
+ readIP("1.2.3.4/8", &ip, &bcast);
+ assert(ip.ip==ntohl(0x01020304) && ip.mask==ntohl(0xff000000) && bcast==0);
+
+ readIP("1.2.3.4/255.255.0.0", &ip, &bcast);
+ assert(ip.ip==ntohl(0x01020304) && ip.mask==ntohl(0xffff0000) && bcast==0);
+
+ readIP("localhost", &ip, &bcast);
+ assert(ip.ip==ntohl(0x7f000001) && ip.mask==ntohl(0xffffff00) && bcast==0);
+
+ readIP("lo", &ip, &bcast);
+ assert(ip.ip==ntohl(0x7f000001) && ip.mask==ntohl(0xff000000) && bcast==ntohl(0x7fffffff));
+}
+#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include "compat.h"
+
+#include "util.h"
+#include "vserver.h"
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#include <getopt.h>
+#include <sys/param.h>
-#include "vserver.h"
#include "linuxcaps.h"
-#ifndef CAP_QUOTACTL
-# define CAP_QUOTACTL VC_CAP_QUOTACTL
+#define ENSC_WRAPPERS_VSERVER 1
+#define ENSC_WRAPPERS_UNISTD 1
+#include <wrappers.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;
extern int capget (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
extern int capset (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
-static void usage()
+static void
+showHelp(int fd, char const *cmd, int res)
{
- fprintf (stderr,"reducecap version %s\n",VERSION);
- fprintf (stderr,"reducecap [ options ] command argument\n");
- exit (-1);
+ WRITE_MSG(fd, "Usage:\n ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " [--show] [--secure] [--flag <flag>] [--cap <capability>] [--] <cmd> <args>*\n ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " --show [--pid <pid>]\n\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+
+ exit(res);
}
-static void reducecap_print(struct __user_cap_data_struct *user)
+static void
+showVersion()
{
- int i;
- printf ("%22s %9s %9s %9s\n","Capability","Effective","Permitted"
- ,"Inheritable");
- for (i=0;; ++i) {
- char const * text = vc_cap2text(i);
- int bit = 1<<i;
- if (text==0) break;
-
- printf ("%-22s %9s %9s %9s\n"
- ,text
- ,(user->effective & bit) ? "X " : " "
- ,(user->permitted & bit) ? "X " : " "
- ,(user->inheritable & bit) ? "X " : " ");
- }
+ 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 reducecap_show()
+static void
+printReducecap(struct __user_cap_data_struct *user)
{
- struct __user_cap_header_struct header;
- struct __user_cap_data_struct user;
- header.version = _LINUX_CAPABILITY_VERSION;
- header.pid = getpid();
- if (capget(&header,&user)==-1){
- perror ("capget");
- }else{
- reducecap_print (&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<<i;
+ size_t l;
+ char buf[len];
+ if (text==0) break;
+
+ memset(buf, ' ', sizeof buf);
+ buf[len-1] = '\n';
+ l = MIN(strlen(text), 22);
+ memcpy(buf, text, l);
+ buf[23 + 10*0 + 4] = (user->effective & bit) ? 'X' : ' ';
+ buf[23 + 10*1 + 4] = (user->permitted & bit) ? 'X' : ' ';
+ buf[23 + 10*2 + 4] = (user->inheritable & bit) ? 'X' : ' ';
+ write(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 ("capget");
+ exit(wrapper_exit_code);
+ }
+
+ printReducecap(&user);
}
+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<<bit);
+}
int main (int argc, char *argv[])
{
- int ret = -1;
- unsigned long remove = 0;
- int show = 0;
- int flags = 0;
- unsigned long secure = (1<<CAP_LINUX_IMMUTABLE)
- |(1<<CAP_NET_BROADCAST)
- |(1<<CAP_NET_ADMIN)
- |(1<<CAP_NET_RAW)
- |(1<<CAP_IPC_LOCK)
- |(1<<CAP_IPC_OWNER)
- |(1<<CAP_SYS_MODULE)
- |(1<<CAP_SYS_RAWIO)
- |(1<<CAP_SYS_PACCT)
- |(1<<CAP_SYS_ADMIN)
- |(1<<CAP_SYS_BOOT)
- |(1<<CAP_SYS_NICE)
- |(1<<CAP_SYS_RESOURCE)
- |(1<<CAP_SYS_TIME)
- |(1<<CAP_MKNOD)
- |(1<<CAP_QUOTACTL);
- int i;
- for (i=1; i<argc; i++){
- const char *arg = argv[i];
- const char *opt = argv[i+1];
- if (strcmp(arg,"--secure")==0){
- remove = secure;
- }else if (strcmp(arg,"--show")==0){
- show = 1;
- }else if (strcmp(arg,"--flag")==0){
- if (strcmp(opt,"lock")==0){
- flags |= 1;
- }else if (strcmp(opt,"sched")==0){
- flags |= 2;
- }else if (strcmp(opt,"nproc")==0){
- flags |= 4;
- }else if (strcmp(opt,"private")==0){
- flags |= 8;
- }else if (strcmp(opt,"hideinfo")==0){
- flags |= 32;
- }else{
- fprintf (stderr,"Unknown flag %s\n",opt);
- }
- i++;
- }else if (arg[0] == '-' && arg[1] == '-'){
- static struct {
- const char *option;
- int bit;
- }tbcap[]={
- // The following capabilities are normally available
- // to vservers administrator, but are place for
- // completeness
- {"CAP_CHOWN",CAP_CHOWN},
- {"CAP_DAC_OVERRIDE",CAP_DAC_OVERRIDE},
- {"CAP_DAC_READ_SEARCH",CAP_DAC_READ_SEARCH},
- {"CAP_FOWNER",CAP_FOWNER},
- {"CAP_FSETID",CAP_FSETID},
- {"CAP_KILL",CAP_KILL},
- {"CAP_SETGID",CAP_SETGID},
- {"CAP_SETUID",CAP_SETUID},
- {"CAP_SETPCAP",CAP_SETPCAP},
- {"CAP_SYS_TTY_CONFIG",CAP_SYS_TTY_CONFIG},
- {"CAP_LEASE",CAP_LEASE},
- {"CAP_SYS_CHROOT",CAP_SYS_CHROOT},
-
- // Those capabilities are not normally available
- // to vservers because they are not needed and
- // may represent a security risk
- {"--LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE},
- {"--NET_BIND_SERVICE",CAP_NET_BIND_SERVICE},
- {"--NET_BROADCAST",CAP_NET_BROADCAST},
- {"--NET_ADMIN", CAP_NET_ADMIN},
- {"--NET_RAW", CAP_NET_RAW},
- {"--IPC_LOCK", CAP_IPC_LOCK},
- {"--IPC_OWNER", CAP_IPC_OWNER},
- {"--SYS_MODULE",CAP_SYS_MODULE},
- {"--SYS_RAWIO", CAP_SYS_RAWIO},
- {"--SYS_PACCT", CAP_SYS_PACCT},
- {"--SYS_ADMIN", CAP_SYS_ADMIN},
- {"--SYS_BOOT", CAP_SYS_BOOT},
- {"--SYS_NICE", CAP_SYS_NICE},
- {"--SYS_RESOURCE",CAP_SYS_RESOURCE},
- {"--SYS_TIME", CAP_SYS_TIME},
- {"--MKNOD", CAP_MKNOD},
- {"--QUOTACTL", CAP_QUOTACTL},
- {NULL,0}
- };
- int j;
- for (j=0; tbcap[j].option != NULL; j++){
- if (strcasecmp(tbcap[j].option,arg)==0){
- remove |= (1<<tbcap[j].bit);
- break;
- }
- }
- if (tbcap[j].option != NULL){
- usage();
- }
- }else{
- break;
- }
- }
- if (i == argc){
- if (show){
- reducecap_show();
- }else{
- usage();
- }
- }else if (argv[i][0] == '-'){
- usage();
- }else{
- struct __user_cap_header_struct header;
- struct __user_cap_data_struct user;
- header.version = _LINUX_CAPABILITY_VERSION;
- header.pid = 0;
- if (capget(&header,&user)==-1){
- perror ("capget");
- }else{
- if (show){
- reducecap_print (&user);
- }
- if (vc_new_s_context(VC_SAMECTX,remove,flags)==VC_NOCTX){
- perror ("new_s_context -2");
- }else{
- fprintf (stderr,"Executing\n");
- execvp (argv[i],argv+i);
- fprintf (stderr,"Can't execute command %s\n",argv[i]);
- }
- }
+ uint32_t remove = 0;
+ bool do_show = false;
+ uint32_t flags = 0;
+ pid_t pid = 0;
+ bool show_obsolete_warning = true;
+
+ while (1) {
+ int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
+ if (c==-1) break;
+
+#ifdef VC_ENABLE_API_LEGACY
+ if (c>=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_SECURE : remove = vc_get_securecaps(); break;
+ case CMD_SHOW : do_show = true; break;
+ case CMD_PID : pid = atoi(optarg); break;
+ case CMD_CAP : remove = getCap(optarg); break;
+ case CMD_FLAG : {
+ char const *err_ptr;
+ size_t err_len;
+
+ flags = vc_textlist2flag(optarg, 0, &err_ptr, &err_len);
+ if (err_ptr!=0) {
+ WRITE_MSG(2, "Unknown flag '");
+ write(2, err_ptr, err_len);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
}
- return ret;
-}
+ break;
+ }
+ }
+ }
+
+ 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);
+ else {
+ Evc_new_s_context(VC_SAMECTX, remove, flags);
+ if (do_show) show(pid);
+
+ WRITE_MSG(2, "Executing\n");
+ Eexecvp(argv[optind], argv+optind);
+ }
+
+ return EXIT_SUCCESS;
+}