minor bug in fs/exec.c

Bill Hawes (whawes@star.net)
Mon, 23 Jun 1997 06:52:26 -0400


This is a multi-part message in MIME format.
--------------B84E09D3FA02A996DC24710B
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

While checking out some other problems I noticed that occasionally
generic_file_read was being passed junk values for the read ahead
parameters (f_ralen, etc.). I traced these down to fs/exec.c, which
uses a hand-rolled struct file on the stack but doesn't clear the memory
first. While it's difficult to analyze the effects of uninitialized
variables, it looks like under some circumstances this could result in
slower loading of executables.

I modified fs/exec.c by writing a routine to properly initialize a
struct file for a given inode and mode. As there were nearly identical
uses of file structures on the stack in binfmt_elf.c and binfmt_aout.c,
I changed these to call the common code.

The following patch (against 2.1.42) fixes the problem.

-Bill
--------------B84E09D3FA02A996DC24710B
Content-Type: text/plain; charset=us-ascii; name="exec_init-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="exec_init-patch"

--- fs/exec.c.old Wed May 14 18:01:21 1997
+++ fs/exec.c Sat Jun 21 08:09:52 1997
@@ -329,6 +329,24 @@
}

/*
+ * Clears and initializes a (private) struct file for the given inode,
+ * and calls the open function (if any). The caller must verify that
+ * inode->i_op and inode->i_op->default_file_ops are not NULL.
+ */
+int init_private_file(struct inode *inode, struct file *filp, int mode)
+{
+ memset(filp, 0, sizeof(*filp));
+ filp->f_mode = mode;
+ filp->f_count = 1;
+ filp->f_inode = inode;
+ filp->f_op = inode->i_op->default_file_ops;
+ if (filp->f_op->open)
+ return filp->f_op->open(inode, filp);
+ else
+ return 0;
+}
+
+/*
* Read in the complete executable. This is used for "-N" files
* that aren't on a block boundary, and for files on filesystems
* without bmap support.
@@ -341,17 +359,9 @@

if (!inode->i_op || !inode->i_op->default_file_ops)
goto end_readexec;
- file.f_mode = 1;
- file.f_flags = 0;
- file.f_count = 1;
- file.f_inode = inode;
- file.f_pos = 0;
- file.f_reada = 0;
- file.f_op = inode->i_op->default_file_ops;
- if (file.f_op->open)
- if (file.f_op->open(inode,&file))
- goto end_readexec;
- if (!file.f_op || !file.f_op->read)
+ if (init_private_file(inode, &file, 1))
+ goto end_readexec;
+ if (!file.f_op->read)
goto close_readexec;
if (file.f_op->llseek) {
if (file.f_op->llseek(inode,&file,offset,0) != offset)
--- fs/binfmt_aout.c.old Thu Apr 17 16:20:47 1997
+++ fs/binfmt_aout.c Sat Jun 21 08:08:04 1997
@@ -33,6 +33,7 @@
static int aout_core_dump(long signr, struct pt_regs * regs);

extern void dump_thread(struct pt_regs *, struct user *);
+extern int init_private_file(struct inode *, struct file *, int);

static struct linux_binfmt aout_format = {
#ifndef MODULE
@@ -124,16 +125,8 @@
goto end_coredump;
if (get_write_access(inode))
goto end_coredump;
- file.f_mode = 3;
- file.f_flags = 0;
- file.f_count = 1;
- file.f_inode = inode;
- file.f_pos = 0;
- file.f_reada = 0;
- file.f_op = inode->i_op->default_file_ops;
- if (file.f_op->open)
- if (file.f_op->open(inode,&file))
- goto done_coredump;
+ if (init_private_file(inode, &file, 3))
+ goto done_coredump;
if (!file.f_op->write)
goto close_coredump;
has_dumped = 1;
--- fs/binfmt_elf.c.old Mon May 19 15:39:25 1997
+++ fs/binfmt_elf.c Sat Jun 21 08:04:23 1997
@@ -42,6 +42,7 @@
static int load_elf_library(int fd);
extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
extern void dump_thread(struct pt_regs *, struct user *);
+extern int init_private_file(struct inode *, struct file *, int);

#ifdef __sparc__
extern unsigned long get_unmapped_area(unsigned long addr, unsigned long len);
@@ -1089,16 +1090,8 @@
goto end_coredump;
if (!inode->i_op || !inode->i_op->default_file_ops)
goto end_coredump;
- file.f_mode = 3;
- file.f_flags = 0;
- file.f_count = 1;
- file.f_inode = inode;
- file.f_pos = 0;
- file.f_reada = 0;
- file.f_op = inode->i_op->default_file_ops;
- if (file.f_op->open)
- if (file.f_op->open(inode,&file))
- goto end_coredump;
+ if (init_private_file(inode, &file, 3))
+ goto end_coredump;
if (!file.f_op->write)
goto close_coredump;
has_dumped = 1;

--------------B84E09D3FA02A996DC24710B--