Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 984

kernel-2.6.18-238.el5.src.rpm

From: Dave Anderson <anderson@redhat.com>
Date: Mon, 19 Nov 2007 15:28:18 -0500
Subject: [fs] executing binaries with >2GB debug info
Message-id: 4741F1E2.1090301@redhat.com
O-Subject: [RHEL5.2 PATCH] BZ #224679: FEAT: Executing >2GB binaries with <2GB code but >2GB debug
Bugzilla: 224679

BZ #224679:  FEAT: Executing >2GB binaries with <2GB code but >2GB debug
    https://bugzilla.redhat.com/show_bug.cgi?id=224679

Description:
   The feature request contains discussions about the inability of RHEL5
   to execute an x86_64 binary with less than 2GB of code, but with greater
   than 2GB of debug data.  There's not much to the supplied binary test
   program, but it has a .debug_macinfo section that is greater than 2GB:

     # ls -l main
     -rwx--x--x 1 root root 2588865021 Nov 19 09:32 main
     # size main
        text    data     bss     dec     hex filename
         996     496       8    1500     5dc main
     # size --format sysv main | grep -e section -e .debug
     section                 size      addr
     .debug_aranges            48         0
     .debug_pubnames           27         0
     .debug_info              157         0
     .debug_abbrev             56         0
     .debug_line               69         0
     .debug_frame              56         0
     .debug_loc                76         0
     .debug_macinfo    2588857187         0
     #

   It fails like so:

     # ./main
     -bash: ./main: File too large
     # strace ./main
     execve("./main", ["./main"], [/* 24 vars */]) = -1 EFBIG (File too large)
     ...
     #

   The problem has nothing to do with the file's format, but simply is a
   matter of file size.  The failing sys_execve() function trace is this:

     sys_execve()
       do_execve()
         open_exec()
           nameidata_to_filp()
             __dentry_open()
               generic_file_open()

   where generic_file_open() returns the EFBIG -- because the inode's file
   size is greater than MAX_NON_LFS (2GB-1):

     /*
      * Called when an inode is about to be open.
      * We use this to disallow opening large files on 32bit systems if
      * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
      * on this flag in sys_open.
      */
     int generic_file_open(struct inode * inode, struct file * filp)
     {
             if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
                     return -EFBIG;
             return 0;
     }

   As the comments above indicate, when a file is opened by sys_open(),
   this path is taken:

     sys_open()
       do_sys_open()
         do_filp_open()
           nameidata_to_filp()
             __dentry_open()
               generic_file_open()

   and O_LARGEFILE gets set in sys_open():

     asmlinkage long sys_open(const char __user *filename, int flags, int mode)
     {
             long ret;

             if (force_o_largefile())
                     flags |= O_LARGEFILE;

   where force_o_largefile() looks like this:

     #define force_o_largefile() (BITS_PER_LONG != 32)

   Therefore, with respect to the exec failure, the EFBIG can be avoided
   by checking force_o_largefile() somewhere in the sys_execve() path.
   To me it made the most sense to add the force_o_largefile() check to
   open_exec().

Testing:
   The supplied test program runs as expected.

Proposed RHEL5 patch:

Acked-by: Chip Coldwell <coldwell@redhat.com>

diff --git a/fs/exec.c b/fs/exec.c
index 8ff68d0..0581532 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -488,7 +488,8 @@ struct file *open_exec(const char *name)
 			int err = vfs_permission(&nd, MAY_EXEC);
 			file = ERR_PTR(err);
 			if (!err) {
-				file = nameidata_to_filp(&nd, O_RDONLY);
+				file = nameidata_to_filp(&nd, force_o_largefile() ?
+					O_RDONLY|O_LARGEFILE : O_RDONLY);
 				if (!IS_ERR(file)) {
 					err = deny_write_access(file);
 					if (err) {