- int ret = -1;
- int i;
- int nbctx = 0;
- int ctxs[16];
- int disconnect = 0;
- int silent = 0;
- int flags = 0;
- unsigned remove_cap = 0;
- unsigned add_cap = 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);
- const char *hostname=NULL, *domainname=NULL;
-
- for (i=1; i<argc; i++){
- const char *arg = argv[i];
- const char *opt = argv[i+1];
- if (strcmp(arg,"--ctx")==0){
- if (nbctx >= 16){
- fprintf (stderr,"Too many context, max 16, ignored.\n");
- }else{
- ctxs[nbctx++] = atoi(opt);
- }
- i++;
- }else if (strcmp(arg,"--disconnect")==0){
- disconnect = 1;
- }else if (strcmp(arg,"--silent")==0){
- silent = 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,"fakeinit")==0){
- flags |= 16;
- }else if (strcmp(opt,"hideinfo")==0){
- flags |= 32;
- }else if (strcmp(opt,"ulimit")==0){
- flags |= 64;
- }else{
- fprintf (stderr,"Unknown flag %s\n",opt);
- }
- i++;
- }else if (strcmp(arg,"--cap")==0){
- 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
- {"CAP_LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE},
- {"CAP_NET_BIND_SERVICE",CAP_NET_BIND_SERVICE},
- {"CAP_NET_BROADCAST",CAP_NET_BROADCAST},
- {"CAP_NET_ADMIN", CAP_NET_ADMIN},
- {"CAP_NET_RAW", CAP_NET_RAW},
- {"CAP_IPC_LOCK", CAP_IPC_LOCK},
- {"CAP_IPC_OWNER", CAP_IPC_OWNER},
- {"CAP_SYS_MODULE",CAP_SYS_MODULE},
- {"CAP_SYS_RAWIO", CAP_SYS_RAWIO},
- {"CAP_SYS_PACCT", CAP_SYS_PACCT},
- {"CAP_SYS_ADMIN", CAP_SYS_ADMIN},
- {"CAP_SYS_BOOT", CAP_SYS_BOOT},
- {"CAP_SYS_NICE", CAP_SYS_NICE},
- {"CAP_SYS_RESOURCE",CAP_SYS_RESOURCE},
- {"CAP_SYS_TIME", CAP_SYS_TIME},
- {"CAP_MKNOD", CAP_MKNOD},
- {"CAP_QUOTACTL", CAP_QUOTACTL},
- {NULL,0}
- };
- int j;
- unsigned *cap = &add_cap;
- if (opt[0] == '!'){
- cap = &remove_cap;
- opt++;
- }
- for (j=0; tbcap[j].option != NULL; j++){
- if (strcasecmp(tbcap[j].option,opt)==0){
- *cap |= (1<<tbcap[j].bit);
- break;
- }
- }
- if (tbcap[j].option == NULL){
- fprintf (stderr,"Unknown capability %s\n",opt);
- }
- i++;
- }else if (strcmp(arg,"--secure")==0){
- remove_cap |= secure;
- }else if (strcmp(arg,"--hostname")==0){
- hostname = opt;
- i++;
- }else if (strcmp(arg,"--domainname")==0){
- if (opt != NULL && strcmp(opt,"none")==0) opt = "";
- domainname = opt;
- i++;
- }else{
- break;
- }
- }
- if (i == argc){
- usage();
- }else if (argv[i][0] == '-'){
- usage();
- }else{
- /*
- We must fork early because fakeinit set the current
- process as the special init process
- */
- if (disconnect == 0 || fork()==0){
- int newctx;
- int xflags = flags & 16;
-
- if (nbctx == 0) ctxs[nbctx++] = -1;
- newctx = vc_new_s_context(ctxs[0],0,flags&~16);
- if (newctx != -1){
- if (hostname != NULL){
- if (sethostname (hostname,strlen(hostname))==-1){
- fprintf (stderr,"Can't set the host name (%s)\n"
- ,strerror(errno));
- }else if (!silent){
- printf ("Host name is now %s\n",hostname);
- }
- }
- if (domainname != NULL){
- setdomainname (domainname,strlen(domainname));
- if (!silent){
- printf ("Domain name is now %s\n",domainname);
- }
- }
- remove_cap &= (~add_cap);
- if (remove_cap!=0 || xflags!=0)
- vc_new_s_context (-2,remove_cap,xflags);
- if (!silent){
- printf ("New security context is %d\n"
- ,ctxs[0] == -1 ? newctx : ctxs[0]);
- }
- execvp (argv[i],argv+i);
- fprintf (stderr,"Can't exec %s (%s)\n",argv[i]
- ,strerror(errno));
- }else{
- perror ("Can't set the new security context\n");
- }
- if (disconnect != 0) _exit(0);
- }