root/fs/exec.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_uselib
  2. create_tables
  3. count
  4. copy_strings
  5. change_ldt
  6. read_omagic
  7. do_execve

   1 /*
   2  *  linux/fs/exec.c
   3  *
   4  *  (C) 1991  Linus Torvalds
   5  */
   6 
   7 /*
   8  * #!-checking implemented by tytso.
   9  */
  10 
  11 /*
  12  * Demand-loading implemented 01.12.91 - no need to read anything but
  13  * the header into memory. The inode of the executable is put into
  14  * "current->executable", and page faults do the actual loading. Clean.
  15  *
  16  * Once more I can proudly say that linux stood up to being changed: it
  17  * was less than 2 hours work to get demand-loading completely implemented.
  18  */
  19 
  20 #include <signal.h>
  21 #include <errno.h>
  22 #include <linux/string.h>
  23 #include <sys/stat.h>
  24 #include <a.out.h>
  25 
  26 #include <linux/fs.h>
  27 #include <linux/sched.h>
  28 #include <linux/kernel.h>
  29 #include <linux/mm.h>
  30 #include <asm/segment.h>
  31 
  32 extern int sys_exit(int exit_code);
  33 extern int sys_close(int fd);
  34 
  35 /*
  36  * MAX_ARG_PAGES defines the number of pages allocated for arguments
  37  * and envelope for the new program. 32 should suffice, this gives
  38  * a maximum env+arg of 128kB !
  39  */
  40 #define MAX_ARG_PAGES 32
  41 
  42 /*
  43  * Note that a shared library must be both readable and executable due to
  44  * security reasons.
  45  *
  46  * Also note that we take the address to load from from the file itself.
  47  */
  48 int sys_uselib(const char * library)
     /* [previous][next][first][last][top][bottom][index][help] */
  49 {
  50 #define libnum  (current->numlibraries)
  51         struct inode * inode;
  52         struct buffer_head * bh;
  53         struct exec ex;
  54 
  55         if (get_limit(0x17) != TASK_SIZE)
  56                 return -EINVAL;
  57         if ((libnum >= MAX_SHARED_LIBS) || (libnum < 0))
  58                 return -EINVAL;
  59         if (library)
  60                 inode = namei(library);
  61         else
  62                 inode = NULL;
  63         if (!inode)
  64                 return -ENOENT;
  65         if (!S_ISREG(inode->i_mode) || !permission(inode,MAY_READ)) {
  66                 iput(inode);
  67                 return -EACCES;
  68         }
  69         if (!(bh = bread(inode->i_dev,inode->i_data[0]))) {
  70                 iput(inode);
  71                 return -EACCES;
  72         }
  73         ex = *(struct exec *) bh->b_data;
  74         brelse(bh);
  75         if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
  76                 ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
  77                 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
  78                 iput(inode);
  79                 return -ENOEXEC;
  80         }
  81         current->libraries[libnum].library = inode;
  82         current->libraries[libnum].start = ex.a_entry;
  83         current->libraries[libnum].length = (ex.a_data+ex.a_text+0xfff) & 0xfffff000;
  84 #if 0
  85         printk("Loaded library %d at %08x, length %08x\n",
  86                 libnum,
  87                 current->libraries[libnum].start,
  88                 current->libraries[libnum].length);
  89 #endif
  90         libnum++;
  91         return 0;
  92 #undef libnum
  93 }
  94 
  95 /*
  96  * create_tables() parses the env- and arg-strings in new user
  97  * memory and creates the pointer tables from them, and puts their
  98  * addresses on the "stack", returning the new stack pointer value.
  99  */
 100 static unsigned long * create_tables(char * p,int argc,int envc)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         unsigned long *argv,*envp;
 103         unsigned long * sp;
 104 
 105         sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
 106         sp -= envc+1;
 107         envp = sp;
 108         sp -= argc+1;
 109         argv = sp;
 110         put_fs_long((unsigned long)envp,--sp);
 111         put_fs_long((unsigned long)argv,--sp);
 112         put_fs_long((unsigned long)argc,--sp);
 113         while (argc-->0) {
 114                 put_fs_long((unsigned long) p,argv++);
 115                 while (get_fs_byte(p++)) /* nothing */ ;
 116         }
 117         put_fs_long(0,argv);
 118         while (envc-->0) {
 119                 put_fs_long((unsigned long) p,envp++);
 120                 while (get_fs_byte(p++)) /* nothing */ ;
 121         }
 122         put_fs_long(0,envp);
 123         return sp;
 124 }
 125 
 126 /*
 127  * count() counts the number of arguments/envelopes
 128  */
 129 static int count(char ** argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         int i=0;
 132         char ** tmp;
 133 
 134         if (tmp = argv)
 135                 while (get_fs_long((unsigned long *) (tmp++)))
 136                         i++;
 137 
 138         return i;
 139 }
 140 
 141 /*
 142  * 'copy_string()' copies argument/envelope strings from user
 143  * memory to free pages in kernel mem. These are in a format ready
 144  * to be put directly into the top of new user memory.
 145  *
 146  * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
 147  * whether the string and the string array are from user or kernel segments:
 148  * 
 149  * from_kmem     argv *        argv **
 150  *    0          user space    user space
 151  *    1          kernel space  user space
 152  *    2          kernel space  kernel space
 153  * 
 154  * We do this by playing games with the fs segment register.  Since it
 155  * it is expensive to load a segment register, we try to avoid calling
 156  * set_fs() unless we absolutely have to.
 157  */
 158 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
     /* [previous][next][first][last][top][bottom][index][help] */
 159                 unsigned long p, int from_kmem)
 160 {
 161         char *tmp, *pag;
 162         int len, offset = 0;
 163         unsigned long old_fs, new_fs;
 164 
 165         if (!p)
 166                 return 0;       /* bullet-proofing */
 167         new_fs = get_ds();
 168         old_fs = get_fs();
 169         if (from_kmem==2)
 170                 set_fs(new_fs);
 171         while (argc-- > 0) {
 172                 if (from_kmem == 1)
 173                         set_fs(new_fs);
 174                 if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
 175                         panic("argc is wrong");
 176                 if (from_kmem == 1)
 177                         set_fs(old_fs);
 178                 len=0;          /* remember zero-padding */
 179                 do {
 180                         len++;
 181                 } while (get_fs_byte(tmp++));
 182                 if (p < len) {  /* this shouldn't happen - 128kB */
 183                         set_fs(old_fs);
 184                         return 0;
 185                 }
 186                 while (len) {
 187                         --p; --tmp; --len;
 188                         if (--offset < 0) {
 189                                 offset = p % PAGE_SIZE;
 190                                 if (from_kmem==2)
 191                                         set_fs(old_fs);
 192                                 if (!(pag = (char *) page[p/PAGE_SIZE]) &&
 193                                     !(pag = (char *) page[p/PAGE_SIZE] =
 194                                       (unsigned long *) get_free_page())) 
 195                                         return 0;
 196                                 if (from_kmem==2)
 197                                         set_fs(new_fs);
 198 
 199                         }
 200                         *(pag + offset) = get_fs_byte(tmp);
 201                 }
 202         }
 203         if (from_kmem==2)
 204                 set_fs(old_fs);
 205         return p;
 206 }
 207 
 208 static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
     /* [previous][next][first][last][top][bottom][index][help] */
 209 {
 210         unsigned long code_limit,data_limit,code_base,data_base;
 211         int i;
 212 
 213         code_limit = TASK_SIZE;
 214         data_limit = TASK_SIZE;
 215         code_base = get_base(current->ldt[1]);
 216         data_base = code_base;
 217         set_base(current->ldt[1],code_base);
 218         set_limit(current->ldt[1],code_limit);
 219         set_base(current->ldt[2],data_base);
 220         set_limit(current->ldt[2],data_limit);
 221 /* make sure fs points to the NEW data segment */
 222         __asm__("pushl $0x17\n\tpop %%fs"::);
 223         data_base += data_limit - LIBRARY_SIZE;
 224         for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
 225                 data_base -= PAGE_SIZE;
 226                 if (page[i])
 227                         put_dirty_page(page[i],data_base);
 228         }
 229         return data_limit;
 230 }
 231 
 232 static void read_omagic(struct inode *inode, int bytes)
     /* [previous][next][first][last][top][bottom][index][help] */
 233 {
 234         struct buffer_head *bh;
 235         int n, blkno, blk = 0;
 236         char *dest = (char *) 0;
 237 
 238         while (bytes > 0) {
 239                 if (!(blkno = bmap(inode, blk)))
 240                         sys_exit(-1);
 241                 if (!(bh = bread(inode->i_dev, blkno)))
 242                         sys_exit(-1);
 243                 n = (blk ? BLOCK_SIZE : BLOCK_SIZE - sizeof(struct exec));
 244                 if (bytes < n)
 245                         n = bytes;
 246 
 247                 memcpy_tofs(dest, (blk ? bh->b_data :
 248                                 bh->b_data + sizeof(struct exec)), n);
 249                 brelse(bh);
 250                 ++blk;
 251                 dest += n;
 252                 bytes -= n;
 253         }
 254         iput(inode);
 255         current->executable = NULL;
 256 }
 257 
 258 /*
 259  * 'do_execve()' executes a new program.
 260  *
 261  * NOTE! We leave 4MB free at the top of the data-area for a loadable
 262  * library.
 263  */
 264 int do_execve(unsigned long * eip,long tmp,char * filename,
     /* [previous][next][first][last][top][bottom][index][help] */
 265         char ** argv, char ** envp)
 266 {
 267         struct inode * inode;
 268         struct buffer_head * bh;
 269         struct exec ex;
 270         unsigned long page[MAX_ARG_PAGES];
 271         int i,argc,envc;
 272         int e_uid, e_gid;
 273         int retval;
 274         int sh_bang = 0;
 275         unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
 276         int ch;
 277 
 278         if ((0xffff & eip[1]) != 0x000f)
 279                 panic("execve called from supervisor mode");
 280         for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
 281                 page[i]=0;
 282         if (!(inode=namei(filename)))           /* get executables inode */
 283                 return -ENOENT;
 284         argc = count(argv);
 285         envc = count(envp);
 286         
 287 restart_interp:
 288         if (!S_ISREG(inode->i_mode)) {  /* must be regular file */
 289                 retval = -EACCES;
 290                 goto exec_error2;
 291         }
 292         i = inode->i_mode;
 293         /* make sure we don't let suid, sgid files be ptraced. */
 294         if (current->flags & PF_PTRACED) {
 295                 e_uid = current->euid;
 296                 e_gid = current->egid;
 297         } else {
 298                 e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
 299                 e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
 300         }
 301         if (current->euid == inode->i_uid)
 302                 i >>= 6;
 303         else if (in_group_p(inode->i_gid))
 304                 i >>= 3;
 305         if (!(i & 1) &&
 306             !((inode->i_mode & 0111) && suser())) {
 307                 retval = -EACCES;
 308                 goto exec_error2;
 309         }
 310         if (!(bh = bread(inode->i_dev,inode->i_data[0]))) {
 311                 retval = -EACCES;
 312                 goto exec_error2;
 313         }
 314         ex = *((struct exec *) bh->b_data);     /* read exec-header */
 315         if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
 316                 /*
 317                  * This section does the #! interpretation.
 318                  * Sorta complicated, but hopefully it will work.  -TYT
 319                  */
 320 
 321                 char buf[128], *cp, *interp, *i_name, *i_arg;
 322                 unsigned long old_fs;
 323 
 324                 strncpy(buf, bh->b_data+2, 127);
 325                 brelse(bh);
 326                 iput(inode);
 327                 buf[127] = '\0';
 328                 if (cp = strchr(buf, '\n')) {
 329                         *cp = '\0';
 330                         for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
 331                 }
 332                 if (!cp || *cp == '\0') {
 333                         retval = -ENOEXEC; /* No interpreter name found */
 334                         goto exec_error1;
 335                 }
 336                 interp = i_name = cp;
 337                 i_arg = 0;
 338                 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
 339                         if (*cp == '/')
 340                                 i_name = cp+1;
 341                 }
 342                 if (*cp) {
 343                         *cp++ = '\0';
 344                         i_arg = cp;
 345                 }
 346                 /*
 347                  * OK, we've parsed out the interpreter name and
 348                  * (optional) argument.
 349                  */
 350                 if (sh_bang++ == 0) {
 351                         p = copy_strings(envc, envp, page, p, 0);
 352                         p = copy_strings(--argc, argv+1, page, p, 0);
 353                 }
 354                 /*
 355                  * Splice in (1) the interpreter's name for argv[0]
 356                  *           (2) (optional) argument to interpreter
 357                  *           (3) filename of shell script
 358                  *
 359                  * This is done in reverse order, because of how the
 360                  * user environment and arguments are stored.
 361                  */
 362                 p = copy_strings(1, &filename, page, p, 1);
 363                 argc++;
 364                 if (i_arg) {
 365                         p = copy_strings(1, &i_arg, page, p, 2);
 366                         argc++;
 367                 }
 368                 p = copy_strings(1, &i_name, page, p, 2);
 369                 argc++;
 370                 if (!p) {
 371                         retval = -ENOMEM;
 372                         goto exec_error1;
 373                 }
 374                 /*
 375                  * OK, now restart the process with the interpreter's inode.
 376                  */
 377                 old_fs = get_fs();
 378                 set_fs(get_ds());
 379                 if (!(inode=namei(interp))) { /* get executables inode */
 380                         set_fs(old_fs);
 381                         retval = -ENOENT;
 382                         goto exec_error1;
 383                 }
 384                 set_fs(old_fs);
 385                 goto restart_interp;
 386         }
 387         brelse(bh);
 388         if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC) ||
 389                 ex.a_trsize || ex.a_drsize ||
 390                 ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
 391                 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
 392                 retval = -ENOEXEC;
 393                 goto exec_error2;
 394         }
 395         if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) != OMAGIC) {
 396                 printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
 397                 retval = -ENOEXEC;
 398                 goto exec_error2;
 399         }
 400         if (!sh_bang) {
 401                 p = copy_strings(envc,envp,page,p,0);
 402                 p = copy_strings(argc,argv,page,p,0);
 403                 if (!p) {
 404                         retval = -ENOMEM;
 405                         goto exec_error2;
 406                 }
 407         }
 408 /* OK, This is the point of no return */
 409         for (i=0; (ch = get_fs_byte(filename++)) != '\0';)
 410                 if (ch == '/')
 411                         i = 0;
 412                 else
 413                         if (i < 8)
 414                                 current->comm[i++] = ch;
 415         if (i < 8)
 416                 current->comm[i] = '\0';
 417         if (current->executable)
 418                 iput(current->executable);
 419         i = current->numlibraries;
 420         while (i-- > 0) {
 421                 iput(current->libraries[i].library);
 422                 current->libraries[i].library = NULL;
 423         }
 424         current->numlibraries = 0;
 425         current->executable = inode;
 426         current->signal = 0;
 427         for (i=0 ; i<32 ; i++) {
 428                 current->sigaction[i].sa_mask = 0;
 429                 current->sigaction[i].sa_flags = 0;
 430                 if (current->sigaction[i].sa_handler != SIG_IGN)
 431                         current->sigaction[i].sa_handler = NULL;
 432         }
 433         for (i=0 ; i<NR_OPEN ; i++)
 434                 if ((current->close_on_exec>>i)&1)
 435                         sys_close(i);
 436         current->close_on_exec = 0;
 437         free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
 438         free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
 439         if (last_task_used_math == current)
 440                 last_task_used_math = NULL;
 441         current->used_math = 0;
 442         p += change_ldt(ex.a_text,page);
 443         p -= LIBRARY_SIZE + MAX_ARG_PAGES*PAGE_SIZE;
 444         p = (unsigned long) create_tables((char *)p,argc,envc);
 445         current->brk = ex.a_bss +
 446                 (current->end_data = ex.a_data +
 447                 (current->end_code = ex.a_text));
 448         current->start_stack = p;
 449         current->rss = (LIBRARY_OFFSET - p + PAGE_SIZE-1) / PAGE_SIZE;
 450         current->suid = current->euid = e_uid;
 451         current->sgid = current->egid = e_gid;
 452         if (N_MAGIC(ex) == OMAGIC)
 453                 read_omagic(inode, ex.a_text+ex.a_data);
 454         eip[0] = ex.a_entry;            /* eip, magic happens :-) */
 455         eip[3] = p;                     /* stack pointer */
 456         if (current->flags & PF_PTRACED)
 457           send_sig(SIGTRAP, current, 0);
 458         return 0;
 459 exec_error2:
 460         iput(inode);
 461 exec_error1:
 462         for (i=0 ; i<MAX_ARG_PAGES ; i++)
 463                 free_page(page[i]);
 464         return(retval);
 465 }

/* [previous][next][first][last][top][bottom][index][help] */