/* * (c) 2004 National Research Council Canada * Written by: * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * This program is a set-uid wrapper, which will set * mapped_base of a task to a suitably low value, and * exec the production task. For many programs, this * will increase the amount of available memory visible * with malloc or ALLOCATE by about 800Mbytes. * * CAUTION: Changing task's mapped base may cause codes * using sbrk() for memory allocation to malfunction! * * If is intended for reasonably recent Linux kernels * (e.g. 2.4.21 works, but 2.4.19 does not). */ #include #include #include #include #include #include #include #include static char *new_task_base = "0x10000000" ; int main( int argc, char *argv[] ) { uid_t euid, uid, gid ; int len, wrlen ; int fd, err ; char *shell ; /* * Warn if not root */ euid = geteuid() ; if (euid!=0) { fprintf(stderr,"Changing task mapped base required special privileges.\n") ; fprintf(stderr,"Since I am running as euid = %d, change will likely fail.\n",euid) ; } /* * Change mapped_base */ fd = open("/proc/self/mapped_base",O_WRONLY) ; if (fd<0) { err = errno ; fprintf(stderr,"Unable to open /proc/self/mapped_base for write access.\n") ; fprintf(stderr,"System error code was %d (%s)\n",err,strerror(err)) ; fprintf(stderr,"Task mapped base will not be changed.\n") ; } if (fd>=0) { len = strlen(new_task_base) ; wrlen = write(fd,new_task_base,len) ; err = (wrlen<0)?errno:0 ; if (len!=wrlen) { fprintf(stderr,"Error writing new task base to /proc/self/mapped_base.\n") ; fprintf(stderr,"Requested transfer length = %d, actual transfer length = %d\n", len, wrlen) ; fprintf(stderr,"System error code was %d (%s)\n",err,strerror(err)) ; } close(fd) ; } /* * Drop special privileges */ uid = getuid() ; gid = getgid() ; if ( setresgid(gid,gid,gid) != 0 ) { err = errno ; fprintf(stderr,"FATAL: Unable to clear effective/saved group id.\n") ; fprintf(stderr,"System error code was %d (%s)\n",err,strerror(err)) ; exit(EXIT_FAILURE) ; } if ( setresuid(uid,uid,uid) != 0 ) { err = errno ; fprintf(stderr,"FATAL: Unable to clear effective/saved user id.\n") ; fprintf(stderr,"System error code was %d (%s)\n",err,strerror(err)) ; exit(EXIT_FAILURE) ; } /* * Exec the actual program, or shell if there were no arguments */ if (argc<2) { shell = getenv("SHELL") ; if (!shell) shell = "/bin/sh" ; fprintf(stderr,"Starting interactive shell %s\n",shell) ; fprintf(stderr,"Type 'exit' to return\n") ; execl (shell,shell,NULL) ; } else { shell = argv[1] ; execv( argv[1], argv + 1 ) ; } /* * If we end up here, exec() failed */ err = errno ; fprintf(stderr,"FATAL: Unable to run %s\n",shell) ; fprintf(stderr,"System error code was %d (%s)\n",err,strerror(err)) ; exit(EXIT_FAILURE) ; }