6b8cf6cd780a51369d3c074e70a95000ef9f999e
[util-vserver.git] / src / reducecap.c
1 // $Id: reducecap.c,v 1.1.4.4 2004/03/05 04:59:36 ensc Exp $
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 #include <strings.h>
31
32 #include "linuxcaps.h"
33 #include "vserver.h"
34
35 #ifndef CAP_QUOTACTL
36 #  define CAP_QUOTACTL  29
37 #endif
38
39 extern int capget (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
40 extern int capset (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
41
42 static void usage()
43 {
44         fprintf (stderr,"reducecap version %s\n",VERSION);
45         fprintf (stderr,"reducecap [ options ] command argument\n");
46         exit (-1);
47 }
48
49 static void reducecap_print(struct __user_cap_data_struct *user)
50 {
51         static const char *tb[]={
52                 "CAP_CHOWN",
53                 "CAP_DAC_OVERRIDE",
54                 "CAP_DAC_READ_SEARCH",
55                 "CAP_FOWNER",
56                 "CAP_FSETID",
57                 "CAP_KILL",
58                 "CAP_SETGID",
59                 "CAP_SETUID",
60                 "CAP_SETPCAP",
61                 "CAP_LINUX_IMMUTABLE",
62                 "CAP_NET_BIND_SERVICE",
63                 "CAP_NET_BROADCAST",
64                 "CAP_NET_ADMIN",
65                 "CAP_NET_RAW",
66                 "CAP_IPC_LOCK",
67                 "CAP_IPC_OWNER",
68                 "CAP_SYS_MODULE",
69                 "CAP_SYS_RAWIO",
70                 "CAP_SYS_CHROOT",
71                 "CAP_SYS_PTRACE",
72                 "CAP_SYS_PACCT",
73                 "CAP_SYS_ADMIN",
74                 "CAP_SYS_BOOT",
75                 "CAP_SYS_NICE",
76                 "CAP_SYS_RESOURCE",
77                 "CAP_SYS_TIME",
78                 "CAP_SYS_TTY_CONFIG",
79                 "CAP_MKNOD",
80                 "CAP_LEASE",
81                 "CAP_QUOTACTL",
82                 NULL
83         };
84         int i;
85         printf ("%22s %9s %9s %9s\n","Capability","Effective","Permitted"
86                 ,"Inheritable");
87         for (i=0; tb[i] != NULL; i++){
88                 int bit = (1 << i);
89                 printf ("%22s %9s %9s %9s\n"
90                         ,tb[i]
91                         ,(user->effective & bit) ? "X    " : " "
92                         ,(user->permitted & bit) ? "X    " : " "
93                         ,(user->inheritable & bit) ? "X    " : " ");
94         }
95 }
96
97 static void reducecap_show()
98 {
99         struct __user_cap_header_struct header;
100         struct __user_cap_data_struct user;
101         header.version = _LINUX_CAPABILITY_VERSION;
102         header.pid = getpid();
103         if (capget(&header,&user)==-1){
104                 perror ("capget");
105         }else{
106                 reducecap_print (&user);
107         }
108 }
109
110
111
112 int main (int argc, char *argv[])
113 {
114         int ret = -1;
115         unsigned long remove = 0;
116         int show = 0;
117         int flags = 0;
118         unsigned long secure = (1<<CAP_LINUX_IMMUTABLE)
119                 |(1<<CAP_NET_BROADCAST)
120                 |(1<<CAP_NET_ADMIN)
121                 |(1<<CAP_NET_RAW)
122                 |(1<<CAP_IPC_LOCK)
123                 |(1<<CAP_IPC_OWNER)
124                 |(1<<CAP_SYS_MODULE)
125                 |(1<<CAP_SYS_RAWIO)
126                 |(1<<CAP_SYS_PACCT)
127                 |(1<<CAP_SYS_ADMIN)
128                 |(1<<CAP_SYS_BOOT)
129                 |(1<<CAP_SYS_NICE)
130                 |(1<<CAP_SYS_RESOURCE)
131                 |(1<<CAP_SYS_TIME)
132                 |(1<<CAP_MKNOD)
133                 |(1<<CAP_QUOTACTL);
134         int i;
135         for (i=1; i<argc; i++){
136                 const char *arg = argv[i];
137                 const char *opt = argv[i+1];
138                 if (strcmp(arg,"--secure")==0){
139                         remove = secure;
140                 }else if (strcmp(arg,"--show")==0){
141                         show = 1;
142                 }else if (strcmp(arg,"--flag")==0){
143                         if (strcmp(opt,"lock")==0){
144                                 flags |= 1;
145                         }else if (strcmp(opt,"sched")==0){
146                                 flags |= 2;
147                         }else if (strcmp(opt,"nproc")==0){
148                                 flags |= 4;
149                         }else if (strcmp(opt,"private")==0){
150                                 flags |= 8;
151                         }else if (strcmp(opt,"hideinfo")==0){
152                                 flags |= 32;
153                         }else{
154                                 fprintf (stderr,"Unknown flag %s\n",opt);
155                         }
156                         i++;
157                 }else if (arg[0] == '-' && arg[1] == '-'){
158                         static struct {
159                                 const char *option;
160                                 int bit;
161                         }tbcap[]={
162                                 // The following capabilities are normally available
163                                 // to vservers administrator, but are place for
164                                 // completeness
165                                 {"CHOWN",CAP_CHOWN},
166                                 {"DAC_OVERRIDE",CAP_DAC_OVERRIDE},
167                                 {"DAC_READ_SEARCH",CAP_DAC_READ_SEARCH},
168                                 {"FOWNER",CAP_FOWNER},
169                                 {"FSETID",CAP_FSETID},
170                                 {"KILL",CAP_KILL},
171                                 {"SETGID",CAP_SETGID},
172                                 {"SETUID",CAP_SETUID},
173                                 {"SETPCAP",CAP_SETPCAP},
174                                 {"SYS_TTY_CONFIG",CAP_SYS_TTY_CONFIG},
175                                 {"LEASE",CAP_LEASE},
176                                 {"SYS_CHROOT",CAP_SYS_CHROOT},
177
178                                 // Those capabilities are not normally available
179                                 // to vservers because they are not needed and
180                                 // may represent a security risk
181                                 {"LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE},
182                                 {"NET_BIND_SERVICE",CAP_NET_BIND_SERVICE},
183                                 {"NET_BROADCAST",CAP_NET_BROADCAST},
184                                 {"NET_ADMIN",   CAP_NET_ADMIN},
185                                 {"NET_RAW",     CAP_NET_RAW},
186                                 {"IPC_LOCK",    CAP_IPC_LOCK},
187                                 {"IPC_OWNER",   CAP_IPC_OWNER},
188                                 {"SYS_MODULE",CAP_SYS_MODULE},
189                                 {"SYS_RAWIO",   CAP_SYS_RAWIO},
190                                 {"SYS_PACCT",   CAP_SYS_PACCT},
191                                 {"SYS_ADMIN",   CAP_SYS_ADMIN},
192                                 {"SYS_BOOT",    CAP_SYS_BOOT},
193                                 {"SYS_NICE",    CAP_SYS_NICE},
194                                 {"SYS_RESOURCE",CAP_SYS_RESOURCE},
195                                 {"SYS_TIME",    CAP_SYS_TIME},
196                                 {"MKNOD",               CAP_MKNOD},
197                                 {"QUOTACTL",          CAP_QUOTACTL},
198                                 {NULL,0}
199                         };
200                         int j;
201                         arg += 2;
202                         if (*arg=='\0') {
203                           ++i;
204                           break;
205                         }
206                         if (strncasecmp(arg, "CAP_", 4)==0) arg += 4;
207                         for (j=0; tbcap[j].option != NULL; j++){
208                                 if (strcasecmp(tbcap[j].option,arg)==0){
209                                         remove |= (1<<tbcap[j].bit);
210                                         break;
211                                 }
212                         }
213                         if (tbcap[j].option == NULL){
214                                 usage();
215                         }
216                 }else{
217                         break;
218                 }
219         }
220         if (i == argc){
221                 if (show){
222                         reducecap_show();
223                 }else{
224                         usage();
225                 }
226         }else{
227                 struct __user_cap_header_struct header;
228                 struct __user_cap_data_struct user;
229                 header.version = _LINUX_CAPABILITY_VERSION;
230                 header.pid = 0;
231                 if (capget(&header,&user)==-1){
232                         perror ("capget");
233                 }else{
234                         if (show){
235                                 reducecap_print (&user);
236                         }
237                         if (vc_new_s_context(-2,remove,flags)==-1){
238                                 perror ("new_s_context -2");
239                         }else{
240                                 fprintf (stderr,"Executing\n");
241                                 execvp (argv[i],argv+i);
242                                 fprintf (stderr,"Can't execute command %s\n",argv[i]);
243                         }
244                 }
245         }
246         return ret;
247 }
248