Back to index

wims  3.65+svn20090927
Defines | Functions | Variables
chroot.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <utime.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/resource.h>

Go to the source code of this file.

Defines

#define PROC_QUOTA   15
#define UID_MIN   10000
#define UID_MASK   127
#define CPU_MAX   4096
#define TIME_MASK   16383
#define CLEAN_DELAY   100
#define CLEAN_DELAY2   500000
#define MAX_PARMLEN   16384
#define MAX_OUTLEN   65536
#define chroot_tmp   "../chroot/tmp/sessions"
#define chroot_path   "/bin:/usr/bin:/usr/local/bin"
#define timestamp   "../tmp/log/chroot.stamp"
#define env_rm_cnt   (sizeof(env_rm)/sizeof(env_rm[0]))

Functions

int remove_tree (char *dirname)
void cleantmp (void)
void cleaning (void)
int test_must (void)
int main (int argc, char *argv[])

Variables

int execuid = 15999
int execgid = 15999
int must = 0
time_t now
char * env_rm []
char name_sh [32] = "/bin/ash.static"
char opt_sh [32] = "-c"
char * pre_sh
char * name_perl = "/usr/bin/perl"
char * opt_perl = "-e"
char * pre_perl

Define Documentation

#define chroot_path   "/bin:/usr/bin:/usr/local/bin"

Definition at line 30 of file chroot.c.

#define chroot_tmp   "../chroot/tmp/sessions"

Definition at line 29 of file chroot.c.

#define CLEAN_DELAY   100

Definition at line 25 of file chroot.c.

#define CLEAN_DELAY2   500000

Definition at line 26 of file chroot.c.

#define CPU_MAX   4096

Definition at line 23 of file chroot.c.

#define env_rm_cnt   (sizeof(env_rm)/sizeof(env_rm[0]))

Definition at line 64 of file chroot.c.

#define MAX_OUTLEN   65536

Definition at line 28 of file chroot.c.

#define MAX_PARMLEN   16384

Definition at line 27 of file chroot.c.

#define PROC_QUOTA   15

Definition at line 20 of file chroot.c.

#define TIME_MASK   16383

Definition at line 24 of file chroot.c.

#define timestamp   "../tmp/log/chroot.stamp"

Definition at line 31 of file chroot.c.

#define UID_MASK   127

Definition at line 22 of file chroot.c.

#define UID_MIN   10000

Definition at line 21 of file chroot.c.


Function Documentation

void cleaning ( void  )

Definition at line 131 of file chroot.c.

{
    DIR *sdir_base;
    struct dirent *ses;
    struct stat dst;
    struct utimbuf ub;
    char dbuf[256];

    if(stat(timestamp,&dst)==0 && dst.st_mtime==now) return;
    ub.actime=ub.modtime=now; utime(timestamp,&ub);
    sdir_base=opendir("/proc");
    if(sdir_base==NULL) goto tmpdir;
    while((ses=readdir(sdir_base))!=NULL) {
       if(ses->d_name[0]<'0' || ses->d_name[9]>'9') continue;
       snprintf(dbuf,sizeof(dbuf),"/proc/%s",ses->d_name);
       if(lstat(dbuf,&dst)) continue;
       if(!S_ISDIR(dst.st_mode)) continue;
       if(dst.st_uid<UID_MIN || dst.st_uid>UID_MIN+UID_MASK) continue;
       if(((dst.st_gid-UID_MIN-now)&TIME_MASK)<=CPU_MAX) continue;
       kill(atoi(ses->d_name),SIGKILL);
    }
    closedir(sdir_base);
    tmpdir: return;
}

Here is the caller graph for this function:

void cleantmp ( void  )

Definition at line 110 of file chroot.c.

{
    DIR *sdir_base;
    struct dirent *ses;
    struct stat dst;
    
    if(chdir("../chroot/tmp/sessions")<0) return;
    sdir_base=opendir(".");
    if(sdir_base==NULL) return;
    while((ses=readdir(sdir_base))!=NULL) {
       if(ses->d_name[0]=='.') continue;
       if(lstat(ses->d_name,&dst)) continue;
       if(!S_ISDIR(dst.st_mode)) continue;
       if(dst.st_mtime <= now) {
           if(dst.st_mtime>=now-CLEAN_DELAY) continue;
           if(dst.st_mtime>=now-CLEAN_DELAY2 && (dst.st_mode&S_IRWXO)==0) continue;
       }
       remove_tree(ses->d_name);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  argc,
char *  argv[] 
)

Definition at line 164 of file chroot.c.

{
    char *args[1024];
    char parm[MAX_PARMLEN];
    char tmpbuf[256];
    int i,k,uid,t;
    struct stat st;
    struct rlimit lim;
    char *p, *pp;
    
    if(argc<2) return 0;
    now=time(NULL);
    uid=geteuid();
    t=stat("../chroot/tmp/sessions/.chroot",&st);
    if(uid!=0 || t!=0) {
       if(test_must()) goto abandon;
       args[0]="bin/wrap..exec"; k=1;
    }
    else {
       k=0;
       p=getenv("REMOTE_ADDR"); if(p && *p) {
           pp=strrchr(p,'.'); if(pp) execuid=(atoi(++pp)&UID_MASK)+UID_MIN;
       }
       getrlimit(RLIMIT_CPU,&lim);
       i=lim.rlim_max; if(i<0) i=0; if(i>=CPU_MAX) i=CPU_MAX-1;
       execgid=((i+now+1)&TIME_MASK)+UID_MIN;
       cleaning();
    }
    if(argc>1 && strcmp(argv[1],"cleantmpdir")==0) {
       if(uid!=0) fprintf(stderr,"ch..root cleantmpdir: uid not changed.\n");
       else cleantmp();
       return 0;
    }
    if(argc>3 && argv[1][0]=='&') {
       if(k) goto abandon;
       if(strcmp(argv[2],"sh")==0) {
           lim.rlim_cur=lim.rlim_max=MAX_OUTLEN;
           setrlimit(RLIMIT_FSIZE,&lim);
           args[0]=name_sh; args[1]=opt_sh;
           snprintf(parm,sizeof(parm),"%s\n%s\n",pre_sh,argv[3]);
           args[2]=parm; args[3]=NULL; must=1;
           goto cont;
       }
       if(strcmp(argv[2],"perl")==0) {
           lim.rlim_cur=lim.rlim_max=MAX_OUTLEN;
           setrlimit(RLIMIT_FSIZE,&lim);
           args[0]=name_perl; args[1]=opt_perl;
           snprintf(parm,sizeof(parm),"%s\n%s\n",pre_perl,argv[3]);
           args[2]=parm; args[3]=NULL; must=1;
           goto cont;
       }
       goto abandon;
    }
    for(i=0;i<1000 && i<argc; i++) args[i+k]=argv[i+1];
    args[i]=NULL;
    cont:
    if(uid!=0) {
       if(test_must()) goto abandon;
       goto ex2;
    }
    if(t!=0) {
       stat("bin",&st); execuid=execgid=st.st_uid;
       if(test_must()) goto abandon;
       goto ex;
    }
    if(chroot("../chroot")==0) {
       chdir("/tmp");
       lim.rlim_cur=lim.rlim_max=PROC_QUOTA;
       setrlimit(RLIMIT_NPROC,&lim);
       setenv("PATH",chroot_path,1);
       p=getenv("w_wims_session"); if(p && *p) {
           snprintf(tmpbuf,sizeof(tmpbuf),"/tmp/sessions/%s",p);
           p=strchr(tmpbuf,'_'); if(p) *p=0;
           setenv("TMPDIR",tmpbuf,1);
           setenv("tmp_dir",tmpbuf,1);
           p=getenv("w_wims_priv_chroot");
           if(p && strstr(p,"tmpdir")!=NULL)
             chdir(tmpbuf);
       }
    }
    else if(test_must()) goto abandon;
    ex:
    if(setregid(execgid,execgid)<0) goto abandon;
    if(setreuid(execuid,execuid)<0) goto abandon; 
    ex2:
    for(i=0;i<env_rm_cnt;i++) unsetenv(env_rm[i]);
    if(strchr(args[0],'/')) execv(args[0],args); else execvp(args[0],args);
    abandon: return 127;
}

Here is the call graph for this function:

int remove_tree ( char *  dirname)

Definition at line 82 of file chroot.c.

{
    DIR *sdir;
    struct dirent *f;
    struct stat dst;

    sdir=opendir(dirname);
    if(sdir==NULL) {   /* Cannot open session directory. */
       return -1;
    }
    while((f=readdir(sdir))!=NULL) {
       char fname[255];
       if(strcmp(".",f->d_name)==0 || strcmp("..",f->d_name)==0) continue;
       snprintf(fname,sizeof(fname),"%s/%s",dirname,f->d_name);
       if(lstat(fname,&dst)) continue;
       if(S_ISDIR(dst.st_mode)) remove_tree(fname);
       else {
           if(remove(fname)<0)
             fprintf(stderr,"ch..root: unable to remove %s. %s\n",fname,strerror(errno));
       }
    }
    closedir(sdir);
    if(rmdir(dirname)<0) {  /* Cannot remove directory. */
       return -1;
    }
    return 0;
}

Here is the call graph for this function:

int test_must ( void  )

Definition at line 156 of file chroot.c.

{
    char *pc;
    if(must) return 1;
    pc=getenv("chroot"); if(pc && strcmp(pc,"must")==0) return 1;
    else return 0;
}

Here is the caller graph for this function:


Variable Documentation

char* env_rm[]
Initial value:
{
    "s2_dir", "w_wims_home", "session_base_dir", "trusted_module",
      "session_dir", "wims_server_base", "w_httpd_PWD",
      "w_wims_sesdir", "HTTP_CONNECTION",
      "w_gnuplot_format", "w_insplot_font", "w_ins_anim_limit",
      "w_ins_density", "w_ins_format",
      "texgif_fontdir", "texgif_texheader",
      "w_wims_tmp_debug", "w_insmath_logic", "w_insmath_rawmath",
      "SERVER_ADMIN", "SERVER_ADDR", "SERVER_NAME"
}

Definition at line 53 of file chroot.c.

int execgid = 15999

Definition at line 49 of file chroot.c.

int execuid = 15999

Definition at line 48 of file chroot.c.

int must = 0

Definition at line 50 of file chroot.c.

char* name_perl = "/usr/bin/perl"

Definition at line 74 of file chroot.c.

char name_sh[32] = "/bin/ash.static"

Definition at line 66 of file chroot.c.

time_t now

Definition at line 51 of file chroot.c.

char* opt_perl = "-e"

Definition at line 75 of file chroot.c.

char opt_sh[32] = "-c"

Definition at line 67 of file chroot.c.

char* pre_perl
Initial value:
"\
chdir($ENV{TMPDIR}) || exit;\n\
chdir(\"/\") && exit;\n\
"

Definition at line 76 of file chroot.c.

char* pre_sh
Initial value:
"\
cd $TMPDIR || exit\n\
echo >/dev/null || exit\n\
cd / 2>/dev/null && exit\n\
"

Definition at line 68 of file chroot.c.