cleanups in the vc_new_s_context() call
[util-vserver.git] / util-vserver / src / reducecap.c
1 // $Id$
2
3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 // based on reducecap.cc by Jacques Gelinas
5 //  
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10 //  
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //  
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif
23 #include "compat.h"
24
25 #include <stdio.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "vserver.h"
32 #include "linuxcaps.h"
33
34 #ifndef CAP_QUOTACTL
35 #  define CAP_QUOTACTL          VC_CAP_QUOTACTL
36 #endif
37
38 extern int capget (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
39 extern int capset (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
40
41 static void usage()
42 {
43         fprintf (stderr,"reducecap version %s\n",VERSION);
44         fprintf (stderr,"reducecap [ options ] command argument\n");
45         exit (-1);
46 }
47
48 static void reducecap_print(struct __user_cap_data_struct *user)
49 {
50         int i;
51         printf ("%22s %9s %9s %9s\n","Capability","Effective","Permitted"
52                 ,"Inheritable");
53         for (i=0;; ++i) {
54                 char const *    text = vc_cap2text(i);
55                 int             bit  = 1<<i;
56                 if (text==0) break;
57                 
58                 printf ("%-22s %9s %9s %9s\n"
59                         ,text
60                         ,(user->effective   & bit) ? "X    " : " "
61                         ,(user->permitted   & bit) ? "X    " : " "
62                         ,(user->inheritable & bit) ? "X    " : " ");
63         }
64 }
65
66 static void reducecap_show()
67 {
68         struct __user_cap_header_struct header;
69         struct __user_cap_data_struct user;
70         header.version = _LINUX_CAPABILITY_VERSION;
71         header.pid = getpid();
72         if (capget(&header,&user)==-1){
73                 perror ("capget");
74         }else{
75                 reducecap_print (&user);
76         }
77 }
78
79
80
81 int main (int argc, char *argv[])
82 {
83         int ret = -1;
84         unsigned long remove = 0;
85         int show = 0;
86         int flags = 0;
87         unsigned long secure = (1<<CAP_LINUX_IMMUTABLE)
88                 |(1<<CAP_NET_BROADCAST)
89                 |(1<<CAP_NET_ADMIN)
90                 |(1<<CAP_NET_RAW)
91                 |(1<<CAP_IPC_LOCK)
92                 |(1<<CAP_IPC_OWNER)
93                 |(1<<CAP_SYS_MODULE)
94                 |(1<<CAP_SYS_RAWIO)
95                 |(1<<CAP_SYS_PACCT)
96                 |(1<<CAP_SYS_ADMIN)
97                 |(1<<CAP_SYS_BOOT)
98                 |(1<<CAP_SYS_NICE)
99                 |(1<<CAP_SYS_RESOURCE)
100                 |(1<<CAP_SYS_TIME)
101                 |(1<<CAP_MKNOD)
102                 |(1<<CAP_QUOTACTL);
103         int i;
104         for (i=1; i<argc; i++){
105                 const char *arg = argv[i];
106                 const char *opt = argv[i+1];
107                 if (strcmp(arg,"--secure")==0){
108                         remove = secure;
109                 }else if (strcmp(arg,"--show")==0){
110                         show = 1;
111                 }else if (strcmp(arg,"--flag")==0){
112                         if (strcmp(opt,"lock")==0){
113                                 flags |= 1;
114                         }else if (strcmp(opt,"sched")==0){
115                                 flags |= 2;
116                         }else if (strcmp(opt,"nproc")==0){
117                                 flags |= 4;
118                         }else if (strcmp(opt,"private")==0){
119                                 flags |= 8;
120                         }else if (strcmp(opt,"hideinfo")==0){
121                                 flags |= 32;
122                         }else{
123                                 fprintf (stderr,"Unknown flag %s\n",opt);
124                         }
125                         i++;
126                 }else if (arg[0] == '-' && arg[1] == '-'){
127                         static struct {
128                                 const char *option;
129                                 int bit;
130                         }tbcap[]={
131                                 // The following capabilities are normally available
132                                 // to vservers administrator, but are place for
133                                 // completeness
134                                 {"CAP_CHOWN",CAP_CHOWN},
135                                 {"CAP_DAC_OVERRIDE",CAP_DAC_OVERRIDE},
136                                 {"CAP_DAC_READ_SEARCH",CAP_DAC_READ_SEARCH},
137                                 {"CAP_FOWNER",CAP_FOWNER},
138                                 {"CAP_FSETID",CAP_FSETID},
139                                 {"CAP_KILL",CAP_KILL},
140                                 {"CAP_SETGID",CAP_SETGID},
141                                 {"CAP_SETUID",CAP_SETUID},
142                                 {"CAP_SETPCAP",CAP_SETPCAP},
143                                 {"CAP_SYS_TTY_CONFIG",CAP_SYS_TTY_CONFIG},
144                                 {"CAP_LEASE",CAP_LEASE},
145                                 {"CAP_SYS_CHROOT",CAP_SYS_CHROOT},
146
147                                 // Those capabilities are not normally available
148                                 // to vservers because they are not needed and
149                                 // may represent a security risk
150                                 {"--LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE},
151                                 {"--NET_BIND_SERVICE",CAP_NET_BIND_SERVICE},
152                                 {"--NET_BROADCAST",CAP_NET_BROADCAST},
153                                 {"--NET_ADMIN", CAP_NET_ADMIN},
154                                 {"--NET_RAW",   CAP_NET_RAW},
155                                 {"--IPC_LOCK",  CAP_IPC_LOCK},
156                                 {"--IPC_OWNER", CAP_IPC_OWNER},
157                                 {"--SYS_MODULE",CAP_SYS_MODULE},
158                                 {"--SYS_RAWIO", CAP_SYS_RAWIO},
159                                 {"--SYS_PACCT", CAP_SYS_PACCT},
160                                 {"--SYS_ADMIN", CAP_SYS_ADMIN},
161                                 {"--SYS_BOOT",  CAP_SYS_BOOT},
162                                 {"--SYS_NICE",  CAP_SYS_NICE},
163                                 {"--SYS_RESOURCE",CAP_SYS_RESOURCE},
164                                 {"--SYS_TIME",  CAP_SYS_TIME},
165                                 {"--MKNOD",             CAP_MKNOD},
166                                 {"--QUOTACTL",          CAP_QUOTACTL},
167                                 {NULL,0}
168                         };
169                         int j;
170                         for (j=0; tbcap[j].option != NULL; j++){
171                                 if (strcasecmp(tbcap[j].option,arg)==0){
172                                         remove |= (1<<tbcap[j].bit);
173                                         break;
174                                 }
175                         }
176                         if (tbcap[j].option != NULL){
177                                 usage();
178                         }
179                 }else{
180                         break;
181                 }
182         }
183         if (i == argc){
184                 if (show){
185                         reducecap_show();
186                 }else{
187                         usage();
188                 }
189         }else if (argv[i][0] == '-'){
190                 usage();
191         }else{
192                 struct __user_cap_header_struct header;
193                 struct __user_cap_data_struct user;
194                 header.version = _LINUX_CAPABILITY_VERSION;
195                 header.pid = 0;
196                 if (capget(&header,&user)==-1){
197                         perror ("capget");
198                 }else{
199                         if (show){
200                                 reducecap_print (&user);
201                         }
202                         if (vc_new_s_context(VC_SAMECTX,remove,flags)==VC_NOCTX){
203                                 perror ("new_s_context -2");
204                         }else{
205                                 fprintf (stderr,"Executing\n");
206                                 execvp (argv[i],argv+i);
207                                 fprintf (stderr,"Can't execute command %s\n",argv[i]);
208                         }
209                 }
210         }
211         return ret;
212 }
213