Rev 3840 | Rev 11128 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3840 | Rev 7076 | ||
---|---|---|---|
Line 13... | Line 13... | ||
13 | * You should have received a copy of the GNU General Public License |
13 | * You should have received a copy of the GNU General Public License |
14 | * along with this program; if not, write to the Free Software |
14 | * along with this program; if not, write to the Free Software |
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
16 | */ |
16 | */ |
17 | 17 | ||
18 |
|
18 | /* Change root and exec */ |
19 | 19 | ||
20 | #define PROC_QUOTA 15 |
20 | #define PROC_QUOTA 15 |
21 | #define UID_MIN 10000 |
21 | #define UID_MIN 10000 |
22 | #define UID_MASK 127 |
22 | #define UID_MASK 127 |
23 | #define CPU_MAX 4096 |
23 | #define CPU_MAX 4096 |
Line 59... | Line 59... | ||
59 | "texgif_fontdir", "texgif_texheader", |
59 | "texgif_fontdir", "texgif_texheader", |
60 | "w_wims_tmp_debug", "w_insmath_logic", "w_insmath_rawmath", |
60 | "w_wims_tmp_debug", "w_insmath_logic", "w_insmath_rawmath", |
61 | "SERVER_ADMIN", "SERVER_ADDR", "SERVER_NAME" |
61 | "SERVER_ADMIN", "SERVER_ADDR", "SERVER_NAME" |
62 | }; |
62 | }; |
63 | 63 | ||
64 | #define env_rm_cnt (sizeof(env_rm)/sizeof(env_rm[0])) |
64 | #define env_rm_cnt (sizeof(env_rm)/sizeof(env_rm[0])) |
65 | 65 | ||
66 | char name_sh[32]="/bin/ash.static"; |
66 | char name_sh[32]="/bin/ash.static"; |
67 | char opt_sh[32]="-c"; |
67 | char opt_sh[32]="-c"; |
68 | char *pre_sh="\ |
68 | char *pre_sh="\ |
69 | cd $TMPDIR || exit\n\ |
69 | cd $TMPDIR || exit\n\ |
Line 76... | Line 76... | ||
76 | char *pre_perl="\ |
76 | char *pre_perl="\ |
77 | chdir($ENV{TMPDIR}) || exit;\n\ |
77 | chdir($ENV{TMPDIR}) || exit;\n\ |
78 | chdir(\"/\") && exit;\n\ |
78 | chdir(\"/\") && exit;\n\ |
79 | "; |
79 | "; |
80 | 80 | ||
- | 81 | ||
81 |
|
82 | /* Remove a tree */ |
82 | int remove_tree(char *dirname) |
83 | int remove_tree(char *dirname) |
83 | { |
84 | { |
84 | DIR *sdir; |
85 | DIR *sdir; |
85 | struct dirent *f; |
86 | struct dirent *f; |
86 | struct stat dst; |
87 | struct stat dst; |
87 | 88 | ||
88 | sdir=opendir(dirname); |
89 | sdir=opendir(dirname); |
89 | if(sdir==NULL) { /* Cannot open session directory. */ |
90 | if(sdir==NULL) { /* Cannot open session directory. */ |
90 |
|
91 | return -1; |
91 | } |
92 | } |
92 | while((f=readdir(sdir))!=NULL) { |
93 | while((f=readdir(sdir))!=NULL) { |
93 | char fname[255]; |
94 | char fname[255]; |
94 | if(strcmp(".",f->d_name)==0 || strcmp("..",f->d_name)==0) continue; |
95 | if(strcmp(".",f->d_name)==0 || strcmp("..",f->d_name)==0) continue; |
95 | snprintf(fname,sizeof(fname),"%s/%s",dirname,f->d_name); |
96 | snprintf(fname,sizeof(fname),"%s/%s",dirname,f->d_name); |
96 | if(lstat(fname,&dst)) continue; |
97 | if(lstat(fname,&dst)) continue; |
97 | if(S_ISDIR(dst.st_mode)) remove_tree(fname); |
98 | if(S_ISDIR(dst.st_mode)) remove_tree(fname); |
98 | else { |
99 | else { |
99 | if(remove(fname)<0) |
100 | if(remove(fname)<0) |
100 | fprintf(stderr,"ch..root: unable to remove %s. %s\n",fname,strerror(errno)); |
101 | fprintf(stderr,"ch..root: unable to remove %s. %s\n",fname,strerror(errno)); |
101 | } |
102 | } |
102 | } |
103 | } |
103 | closedir(sdir); |
104 | closedir(sdir); |
104 | if(rmdir(dirname)<0) { |
105 | if(rmdir(dirname)<0) { /* Cannot remove directory. */ |
105 |
|
106 | return -1; |
106 | } |
107 | } |
107 | return 0; |
108 | return 0; |
108 | } |
109 | } |
109 | 110 | ||
- | 111 | /* Clean TMP */ |
|
110 | void cleantmp(void) |
112 | void cleantmp(void) |
111 | { |
113 | { |
112 | DIR *sdir_base; |
114 | DIR *sdir_base; |
113 | struct dirent *ses; |
115 | struct dirent *ses; |
114 | struct stat dst; |
116 | struct stat dst; |
115 | 117 | ||
116 | if(chdir("../chroot/tmp/sessions")<0) return; |
118 | if(chdir("../chroot/tmp/sessions")<0) return; |
117 | sdir_base=opendir("."); |
119 | sdir_base=opendir("."); |
118 | if(sdir_base==NULL) return; |
120 | if(sdir_base==NULL) return; |
119 | while((ses=readdir(sdir_base))!=NULL) { |
121 | while((ses=readdir(sdir_base))!=NULL) { |
120 | if(ses->d_name[0]=='.') continue; |
122 | if(ses->d_name[0]=='.') continue; |
121 | if(lstat(ses->d_name,&dst)) continue; |
123 | if(lstat(ses->d_name,&dst)) continue; |
122 | if(!S_ISDIR(dst.st_mode)) continue; |
124 | if(!S_ISDIR(dst.st_mode)) continue; |
123 | if(dst.st_mtime <= now) { |
125 | if(dst.st_mtime <= now) { |
124 | if(dst.st_mtime>=now-CLEAN_DELAY) continue; |
126 | if(dst.st_mtime>=now-CLEAN_DELAY) continue; |
125 | if(dst.st_mtime>=now-CLEAN_DELAY2 && (dst.st_mode&S_IRWXO)==0) continue; |
127 | if(dst.st_mtime>=now-CLEAN_DELAY2 && (dst.st_mode&S_IRWXO)==0) continue; |
126 | } |
128 | } |
127 | remove_tree(ses->d_name); |
129 | remove_tree(ses->d_name); |
128 | } |
130 | } |
129 | } |
131 | } |
130 | 132 | ||
- | 133 | /* Cleaning */ |
|
131 | void cleaning(void) |
134 | void cleaning(void) |
132 | { |
135 | { |
133 | DIR *sdir_base; |
136 | DIR *sdir_base; |
134 | struct dirent *ses; |
137 | struct dirent *ses; |
135 | struct stat dst; |
138 | struct stat dst; |
Line 139... | Line 142... | ||
139 | if(stat(timestamp,&dst)==0 && dst.st_mtime==now) return; |
142 | if(stat(timestamp,&dst)==0 && dst.st_mtime==now) return; |
140 | ub.actime=ub.modtime=now; utime(timestamp,&ub); |
143 | ub.actime=ub.modtime=now; utime(timestamp,&ub); |
141 | sdir_base=opendir("/proc"); |
144 | sdir_base=opendir("/proc"); |
142 | if(sdir_base==NULL) goto tmpdir; |
145 | if(sdir_base==NULL) goto tmpdir; |
143 | while((ses=readdir(sdir_base))!=NULL) { |
146 | while((ses=readdir(sdir_base))!=NULL) { |
144 | if(ses->d_name[0]<'0' || ses->d_name[9]>'9') continue; |
147 | if(ses->d_name[0]<'0' || ses->d_name[9]>'9') continue; |
145 | snprintf(dbuf,sizeof(dbuf),"/proc/%s",ses->d_name); |
148 | snprintf(dbuf,sizeof(dbuf),"/proc/%s",ses->d_name); |
146 | if(lstat(dbuf,&dst)) continue; |
149 | if(lstat(dbuf,&dst)) continue; |
147 | if(!S_ISDIR(dst.st_mode)) continue; |
150 | if(!S_ISDIR(dst.st_mode)) continue; |
148 | if(dst.st_uid<UID_MIN || dst.st_uid>UID_MIN+UID_MASK) continue; |
151 | if(dst.st_uid<UID_MIN || dst.st_uid>UID_MIN+UID_MASK) continue; |
149 | if(((dst.st_gid-UID_MIN-now)&TIME_MASK)<=CPU_MAX) continue; |
152 | if(((dst.st_gid-UID_MIN-now)&TIME_MASK)<=CPU_MAX) continue; |
150 | kill(atoi(ses->d_name),SIGKILL); |
153 | kill(atoi(ses->d_name),SIGKILL); |
151 | } |
154 | } |
152 | closedir(sdir_base); |
155 | closedir(sdir_base); |
153 | tmpdir: return; |
156 | tmpdir: return; |
154 | } |
157 | } |
155 | 158 | ||
- | 159 | /* Test Must */ |
|
156 | int test_must(void) |
160 | int test_must(void) |
157 | { |
161 | { |
158 | char *pc; |
162 | char *pc; |
159 | if(must) return 1; |
163 | if(must) return 1; |
160 | pc=getenv("chroot"); if(pc && strcmp(pc,"must")==0) return 1; |
164 | pc=getenv("chroot"); if(pc && strcmp(pc,"must")==0) return 1; |
161 | else return 0; |
165 | else return 0; |
162 | } |
166 | } |
163 | 167 | ||
- | 168 | /* MAIN */ |
|
164 | int main(int argc,char *argv[]) |
169 | int main(int argc,char *argv[]) |
165 | { |
170 | { |
166 | char *args[1024]; |
171 | char *args[1024]; |
167 | char parm[MAX_PARMLEN]; |
172 | char parm[MAX_PARMLEN]; |
168 | char tmpbuf[256]; |
173 | char tmpbuf[256]; |
Line 174... | Line 179... | ||
174 | if(argc<2) return 0; |
179 | if(argc<2) return 0; |
175 | now=time(NULL); |
180 | now=time(NULL); |
176 | uid=geteuid(); |
181 | uid=geteuid(); |
177 | t=stat("../chroot/tmp/sessions/.chroot",&st); |
182 | t=stat("../chroot/tmp/sessions/.chroot",&st); |
178 | if(uid!=0 || t!=0) { |
183 | if(uid!=0 || t!=0) { |
179 | if(test_must()) goto abandon; |
184 | if(test_must()) goto abandon; |
180 | args[0]="bin/wrap..exec"; k=1; |
185 | args[0]="bin/wrap..exec"; k=1; |
181 | } |
186 | } |
182 | else { |
187 | else { |
183 | k=0; |
188 | k=0; |
184 | p=getenv("REMOTE_ADDR"); |
189 | p=getenv("REMOTE_ADDR"); |
- | 190 | if(p && *p) { |
|
185 | pp=strrchr(p,'.'); if(pp) execuid=(atoi(++pp)&UID_MASK)+UID_MIN; |
191 | pp=strrchr(p,'.'); if(pp) execuid=(atoi(++pp)&UID_MASK)+UID_MIN; |
186 | } |
192 | } |
187 | getrlimit(RLIMIT_CPU,&lim); |
193 | getrlimit(RLIMIT_CPU,&lim); |
188 | i=lim.rlim_max; if(i<0) i=0; if(i>=CPU_MAX) i=CPU_MAX-1; |
194 | i=lim.rlim_max; if(i<0) i=0; if(i>=CPU_MAX) i=CPU_MAX-1; |
189 | execgid=((i+now+1)&TIME_MASK)+UID_MIN; |
195 | execgid=((i+now+1)&TIME_MASK)+UID_MIN; |
190 | cleaning(); |
196 | cleaning(); |
191 | } |
197 | } |
192 | if(argc>1 && strcmp(argv[1],"cleantmpdir")==0) { |
198 | if(argc>1 && strcmp(argv[1],"cleantmpdir")==0) { |
193 | if(uid!=0) fprintf(stderr,"ch..root cleantmpdir: uid not changed.\n"); |
199 | if(uid!=0) fprintf(stderr,"ch..root cleantmpdir: uid not changed.\n"); |
194 | else cleantmp(); |
200 | else cleantmp(); |
195 | return 0; |
201 | return 0; |
196 | } |
202 | } |
197 | if(argc>3 && argv[1][0]=='&') { |
203 | if(argc>3 && argv[1][0]=='&') { |
198 | if(k) goto abandon; |
204 | if(k) goto abandon; |
199 | if(strcmp(argv[2],"sh")==0) { |
205 | if(strcmp(argv[2],"sh")==0) { |
200 | lim.rlim_cur=lim.rlim_max=MAX_OUTLEN; |
206 | lim.rlim_cur=lim.rlim_max=MAX_OUTLEN; |
201 | setrlimit(RLIMIT_FSIZE,&lim); |
207 | setrlimit(RLIMIT_FSIZE,&lim); |
202 | args[0]=name_sh; args[1]=opt_sh; |
208 | args[0]=name_sh; args[1]=opt_sh; |
203 | snprintf(parm,sizeof(parm),"%s\n%s\n",pre_sh,argv[3]); |
209 | snprintf(parm,sizeof(parm),"%s\n%s\n",pre_sh,argv[3]); |
204 | args[2]=parm; args[3]=NULL; must=1; |
210 | args[2]=parm; args[3]=NULL; must=1; |
205 | goto cont; |
211 | goto cont; |
206 | } |
212 | } |
207 | if(strcmp(argv[2],"perl")==0) { |
213 | if(strcmp(argv[2],"perl")==0) { |
208 | lim.rlim_cur=lim.rlim_max=MAX_OUTLEN; |
214 | lim.rlim_cur=lim.rlim_max=MAX_OUTLEN; |
209 | setrlimit(RLIMIT_FSIZE,&lim); |
215 | setrlimit(RLIMIT_FSIZE,&lim); |
210 | args[0]=name_perl; args[1]=opt_perl; |
216 | args[0]=name_perl; args[1]=opt_perl; |
211 | snprintf(parm,sizeof(parm),"%s\n%s\n",pre_perl,argv[3]); |
217 | snprintf(parm,sizeof(parm),"%s\n%s\n",pre_perl,argv[3]); |
212 | args[2]=parm; args[3]=NULL; must=1; |
218 | args[2]=parm; args[3]=NULL; must=1; |
213 | goto cont; |
219 | goto cont; |
214 | } |
220 | } |
215 | goto abandon; |
221 | goto abandon; |
216 | } |
222 | } |
217 | for(i=0;i<1000 && i<argc; i++) args[i+k]=argv[i+1]; |
223 | for(i=0;i<1000 && i<argc; i++) args[i+k]=argv[i+1]; |
218 | args[i]=NULL; |
224 | args[i]=NULL; |
219 | cont: |
225 | cont: |
220 | if(uid!=0) { |
226 | if(uid!=0) { |
221 | if(test_must()) goto abandon; |
227 | if(test_must()) goto abandon; |
222 | goto ex2; |
228 | goto ex2; |
223 | } |
229 | } |
224 | if(t!=0) { |
230 | if(t!=0) { |
225 | stat("bin",&st); execuid=execgid=st.st_uid; |
231 | stat("bin",&st); execuid=execgid=st.st_uid; |
226 | if(test_must()) goto abandon; |
232 | if(test_must()) goto abandon; |
227 | goto ex; |
233 | goto ex; |
228 | } |
234 | } |
229 | if(chroot("../chroot")==0) { |
235 | if(chroot("../chroot")==0) { |
230 | (void)chdir("/tmp"); |
236 | (void)chdir("/tmp"); |
231 | lim.rlim_cur=lim.rlim_max=PROC_QUOTA; |
237 | lim.rlim_cur=lim.rlim_max=PROC_QUOTA; |
232 | setrlimit(RLIMIT_NPROC,&lim); |
238 | setrlimit(RLIMIT_NPROC,&lim); |
233 | setenv("PATH",chroot_path,1); |
239 | setenv("PATH",chroot_path,1); |
234 | p=getenv("w_wims_session"); |
240 | p=getenv("w_wims_session"); |
- | 241 | if(p && *p) { |
|
235 | snprintf(tmpbuf,sizeof(tmpbuf),"/tmp/sessions/%s",p); |
242 | snprintf(tmpbuf,sizeof(tmpbuf),"/tmp/sessions/%s",p); |
236 | p=strchr(tmpbuf,'_'); if(p) *p=0; |
243 | p=strchr(tmpbuf,'_'); if(p) *p=0; |
237 | setenv("TMPDIR",tmpbuf,1); |
244 | setenv("TMPDIR",tmpbuf,1); |
238 | setenv("tmp_dir",tmpbuf,1); |
245 | setenv("tmp_dir",tmpbuf,1); |
239 | p=getenv("w_wims_priv_chroot"); |
246 | p=getenv("w_wims_priv_chroot"); |
240 | if(p && strstr(p,"tmpdir")!=NULL) |
247 | if(p && strstr(p,"tmpdir")!=NULL) |
241 | (void)chdir(tmpbuf); |
248 | (void)chdir(tmpbuf); |
242 | } |
249 | } |
243 | } |
250 | } |
244 | else if(test_must()) goto abandon; |
251 | else if(test_must()) goto abandon; |
245 | ex: |
252 | ex: |
246 | if(setregid(execgid,execgid)<0) goto abandon; |
253 | if(setregid(execgid,execgid)<0) goto abandon; |
247 | if(setreuid(execuid,execuid)<0) goto abandon; |
254 | if(setreuid(execuid,execuid)<0) goto abandon; |