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