syscall-legacy.hc (6879B)
1 // $Id$ --*- c -*-- 2 3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 // based on syscall.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 /* 21 This tells the system call number for new_s_context and set_ipv4root 22 using /proc/self/status. This helps until the vserver project is 23 included officially in the kernel (and has its own syscall). 24 25 We rely on /proc/self/status to find the syscall number. 26 27 If it is not there, we rely on adm/unistd.h. 28 29 If this file does not have those system calls (not a patched kernel source) 30 we rely on static values in this file. 31 */ 32 #include "safechroot-internal.hc" 33 34 #include <string.h> 35 #include <stdlib.h> 36 #include <errno.h> 37 #include <asm/unistd.h> 38 #include <stdbool.h> 39 40 #include "syscall-wrap.h" 41 42 // Here is the trick. We keep a copy of the define, then undef it 43 // and then later, we try to locate the value reading /proc/self/status 44 // If this fails, we have the old preserved copy. 45 static int def_NR_set_ipv4root = 274; 46 #undef __NR_set_ipv4root 47 48 static int __NR_set_ipv4root_rev0; 49 static int __NR_set_ipv4root_rev1; 50 static int __NR_set_ipv4root_rev2; 51 static int __NR_set_ipv4root_rev3; 52 static int rev_ipv4root=0; 53 54 #ifdef ENSC_SYSCALL_TRADITIONAL 55 # if defined __dietlibc__ 56 extern long int syscall (long int __sysno, ...); 57 # endif 58 59 inline static int 60 set_ipv4root_rev0(unsigned long ip) 61 { 62 return syscall(__NR_set_ipv4root_rev0, ip); 63 } 64 65 inline static int 66 set_ipv4root_rev1(unsigned long ip, unsigned long bcast) 67 { 68 return syscall(__NR_set_ipv4root_rev1, ip, bcast); 69 } 70 71 inline static int 72 set_ipv4root_rev2(unsigned long *ip, int nb, unsigned long bcast) 73 { 74 return syscall(__NR_set_ipv4root_rev2, ip, nb, bcast); 75 } 76 77 inline static int 78 set_ipv4root_rev3(unsigned long *ip, int nb, unsigned long bcast, unsigned long * mask) 79 { 80 return syscall(__NR_set_ipv4root_rev3, ip, nb, bcast, mask); 81 } 82 83 #else // ENSC_SYSCALL_TRADITIONAL 84 inline static _syscall1(int, set_ipv4root_rev0, unsigned long, ip) 85 inline static _syscall2(int, set_ipv4root_rev1, unsigned long, ip, unsigned long, bcast) 86 inline static _syscall3(int, set_ipv4root_rev2, unsigned long *, ip, int, nb, unsigned long, bcast) 87 inline static _syscall4(int, set_ipv4root_rev3, unsigned long *, ip, int, nb, unsigned long, bcast, unsigned long *, mask) 88 #endif // ENSC_SYSCALL_TRADITIONAL 89 90 static int def_NR_new_s_context = 273; 91 #undef __NR_new_s_context 92 static int __NR_new_s_context_rev0; 93 static int rev_s_context=0; 94 95 96 #ifdef ENSC_SYSCALL_TRADITIONAL 97 inline static xid_t 98 new_s_context_rev0(int newctx, int remove_cap, int flags) 99 { 100 return syscall(__NR_new_s_context_rev0, newctx, remove_cap, flags); 101 } 102 #else // ENSC_SYSCALL_TRADITIONAL 103 inline static _syscall3(int, new_s_context_rev0, int, newctx, int, remove_cap, int, flags) 104 #endif // ENSC_SYSCALL_TRADITIONAL 105 106 107 static bool is_init = false; 108 109 #include "utils-legacy.h" 110 111 #ifndef WRITE_MSG 112 # define WRITE_MSG(FD,X) (void)(write(FD,X,sizeof(X)-1)) 113 #endif 114 115 116 static bool 117 getNumRevPair(char const *str, int *num, int *rev) 118 { 119 char const * blank_pos = strchr(str, ' '); 120 char const * eol_pos = strchr(str, '\n'); 121 122 *num = atoi(str); 123 if (*num==0) return false; 124 125 if (blank_pos!=0 && eol_pos!=0 && blank_pos<eol_pos && 126 strncmp(blank_pos+1, "rev", 3)==0) 127 *rev = atoi(blank_pos+4); 128 129 return true; 130 } 131 132 #define SET_TAG_POS(TAG) \ 133 pos = strstr(buf, (TAG)); \ 134 if (pos) pos+=sizeof(TAG)-1 135 136 static bool init_internal() 137 { 138 size_t bufsize = utilvserver_getProcEntryBufsize(); 139 char buf[bufsize]; 140 char const * pos = 0; 141 pid_t pid = getpid(); 142 int num; 143 144 errno = 0; 145 146 pos=utilvserver_getProcEntry(pid, 0, buf, bufsize); 147 if (pos==0 && errno==EAGAIN) return false; 148 149 SET_TAG_POS("\n__NR_set_ipv4root: "); 150 if ( pos!=0 && getNumRevPair(pos, &num, &rev_ipv4root) ) { 151 __NR_set_ipv4root_rev0 = 152 __NR_set_ipv4root_rev1 = 153 __NR_set_ipv4root_rev2 = 154 __NR_set_ipv4root_rev3 = num; 155 } 156 157 SET_TAG_POS("\n__NR_new_s_context: "); 158 if ( pos!=0 && getNumRevPair(pos, &num, &rev_s_context) ) 159 __NR_new_s_context_rev0 = num; 160 161 return true; 162 } 163 164 #undef SET_TAG_POS 165 166 static void init() 167 { 168 if (!is_init){ 169 __NR_set_ipv4root_rev0 = def_NR_set_ipv4root; 170 __NR_set_ipv4root_rev1 = def_NR_set_ipv4root; 171 __NR_set_ipv4root_rev2 = def_NR_set_ipv4root; 172 __NR_set_ipv4root_rev3 = def_NR_set_ipv4root; 173 __NR_new_s_context_rev0 = def_NR_new_s_context; 174 175 while (!init_internal() && errno==EAGAIN) {} 176 177 is_init = true; 178 } 179 } 180 181 void vc_init_legacy() 182 { 183 init(); 184 } 185 186 void vc_init_internal_legacy(int ctx_rev, int ctx_number, 187 int ipv4_rev, int ipv4_number) 188 { 189 rev_s_context = ctx_rev; 190 __NR_new_s_context_rev0 = ctx_number; 191 192 rev_ipv4root = ipv4_rev; 193 __NR_set_ipv4root_rev0 = ipv4_number; 194 __NR_set_ipv4root_rev1 = ipv4_number; 195 __NR_set_ipv4root_rev2 = ipv4_number; 196 __NR_set_ipv4root_rev3 = ipv4_number; 197 198 is_init = true; 199 } 200 201 static ALWAYSINLINE xid_t 202 vc_new_s_context_legacy(int ctx, int remove_cap, int flags) 203 { 204 xid_t ret = -1; 205 init(); 206 if (rev_s_context == 0){ 207 return new_s_context_rev0(ctx, remove_cap, flags); 208 }else{ 209 errno = -ENOSYS; 210 ret = VC_NOCTX; 211 } 212 return ret; 213 } 214 215 static ALWAYSINLINE int 216 vc_set_ipv4root_legacy_internal ( 217 unsigned long ip[], 218 int nb, 219 unsigned long bcast, 220 unsigned long mask[]) 221 { 222 init(); 223 if (rev_ipv4root == 0){ 224 if (nb > 1){ 225 WRITE_MSG(2,"set_ipv4root: Several IP number specified, but this kernel only supports one. Ignored\n"); 226 } 227 return set_ipv4root_rev0 (ip[0]); 228 }else if (rev_ipv4root == 1){ 229 if (nb > 1){ 230 WRITE_MSG(2,"set_ipv4root: Several IP number specified, but this kernel only supports one. Ignored\n"); 231 } 232 return set_ipv4root_rev1 (ip[0],bcast); 233 }else if (rev_ipv4root == 2){ 234 return set_ipv4root_rev2 (ip,nb,bcast); 235 }else if (rev_ipv4root == 3){ 236 return set_ipv4root_rev3 (ip,nb,bcast,mask); 237 } 238 errno = EINVAL; 239 return -1; 240 } 241 242 static ALWAYSINLINE int 243 vc_set_ipv4root_legacy(uint32_t bcast, size_t nb, struct vc_ip_mask_pair const *ips) 244 { 245 unsigned long ip[nb]; 246 unsigned long mask[nb]; 247 size_t i; 248 249 for (i=0; i<nb; ++i) { 250 ip[i] = ips[i].ip; 251 mask[i] = ips[i].mask; 252 } 253 254 return vc_set_ipv4root_legacy_internal(ip, nb, bcast, mask); 255 }