Re: patches for 1.3.71 w/iBCS

Tom Grigg (st588@bayou.uh.edu)
Fri, 15 Mar 1996 06:11:32 -0600 (CST)


On Thu, 7 Mar 1996, Linus Torvalds wrote:

> > As many of you have noticed, the 1.3.71 kernel breaks iBCS. Below are
> > some patches to correct this problem, both for the kernel and iBCS itself.

> I'd suggest copying the "create_aout_tables()" function into the iBCS2
> code, because it should really be a per-binfmt thing (that way I can
> also remove the test for "ibcs" in the kernel create_aout_tables())

First of all I'd like to apologize for not posting anything sooner. I've
been feeling ill this past week. :(

I had originally thought to move the "create_tables" code into iBCS
itself, but was worried about having to export more kernel symbols
(specifically, `bad_user_access_length'). After compiling the code into
assembly, however, I noticed that `bad_user_access_length' was optimized
away by the compiler and then I realized what the comments about it in
the sources meant. A few moments after this, I realized that I shouldn't
have been worried at all, since the a.out support in the kernel can itself
be compiled as a module now. :)

Anyway, below are two patches, as before; the first for the kernel (the
diff was taken against 1.3.73, but should patch cleanly into 1.3.74) and
the second for the iBCS code found in the file:
ftp://tsx-11.mit.edu/pub/linux/BETA/ibcs2/ibcs-1.3-960201.tar.gz

The patch to the kernel is fairly trivial--the changes to binfmts.h and
personality.h are so that the `use_count' fields of the `linux_binfmt'
and `exec_domain' structures match the declaration of `mod_use_count_'.
The other change (to binfmt_aout.c) removes the test for iBCS in the
kernel's `create_aout_tables'.

The patches to iBCS do a number of things, as before.

* Fix the MAKEDEV.ibcs script
* Allow the iBCS module to be compiled with MODVERSIONS enabled, if you
so desire. This can be done by uncommenting the end of the MODFLAGS
line in ibcs/iBCSemul/Makefile. MODVERSIONS is not enabled by default
to prevent problems with those whose kernel is not compiled with it.
* The `create_tables' function is now in its own file, binfmt_tables.c
* Some warnings taken care of.

NOTE that the new iBCS code will not work with kernel versions prior to
1.3.71. Also note that this patch to the iBCS sources will not work if
my previous one has already been applied; please either unpatch the
sources or unpack a fresh copy and work from there.

As a final note, currently I only use iBCS to run the SCO version of
WordPerfect (which is a COFF executable), so I have personally only
tested the COFF support. If someone could point me to some freely
available binaries in the other formats iBCS supports, I'd be happy to
test those out as well.

I would appreciate any and all feedback from those using these patches.
Thanks!

diff -u --recursive linux-1.3.73/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- linux-1.3.73/fs/binfmt_aout.c Wed Mar 13 03:32:03 1996
+++ linux/fs/binfmt_aout.c Wed Mar 13 03:36:07 1996
@@ -202,7 +202,7 @@
* memory and creates the pointer tables from them, and puts their
* addresses on the "stack", returning the new stack pointer value.
*/
-static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm, int ibcs)
+static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
{
unsigned long *argv,*envp;
unsigned long * sp;
@@ -228,10 +228,8 @@
sp -= argc+1;
argv = sp;
#ifdef __i386__
- if (!ibcs) {
- put_user(envp,--sp);
- put_user(argv,--sp);
- }
+ put_user(envp,--sp);
+ put_user(argv,--sp);
#endif
put_user(argc,--sp);
current->mm->arg_start = (unsigned long) p;
@@ -385,8 +383,7 @@

p = setup_arg_pages(p, bprm);

- p = (unsigned long) create_aout_tables((char *)p, bprm,
- current->personality != PER_LINUX);
+ p = (unsigned long) create_aout_tables((char *)p, bprm);
current->mm->start_stack = p;
#ifdef __alpha__
regs->gp = ex.a_gpvalue;
diff -u --recursive linux-1.3.73/include/linux/binfmts.h linux/include/linux/binfmts.h
--- linux-1.3.73/include/linux/binfmts.h Fri Mar 8 21:50:25 1996
+++ linux/include/linux/binfmts.h Wed Mar 13 03:36:46 1996
@@ -32,7 +32,7 @@
*/
struct linux_binfmt {
struct linux_binfmt * next;
- int *use_count;
+ long *use_count;
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
int (*load_shlib)(int fd);
int (*core_dump)(long signr, struct pt_regs * regs);
diff -u --recursive linux-1.3.73/include/linux/personality.h linux/include/linux/personality.h
--- linux-1.3.73/include/linux/personality.h Wed Sep 13 02:31:15 1995
+++ linux/include/linux/personality.h Wed Mar 13 03:36:32 1996
@@ -37,7 +37,7 @@
unsigned char pers_low, pers_high;
unsigned long * signal_map;
unsigned long * signal_invmap;
- int *use_count;
+ long *use_count;
struct exec_domain *next;
};
-----------------------[ cut here ]----------------------------------
diff -u --recursive --new-file ibcs-960201/MAKEDEV.ibcs ibcs/MAKEDEV.ibcs
--- ibcs-960201/MAKEDEV.ibcs Thu Feb 1 06:54:59 1996
+++ ibcs/MAKEDEV.ibcs Tue Mar 5 23:24:36 1996
@@ -13,26 +13,26 @@
fi

rm -f socksys nfsd
-mknod -m 0666 socksys c $(SOCKSYS_MAJOR) 0
+mknod -m 0666 socksys c ${SOCKSYS_MAJOR} 0
ln socksys nfsd
rm -f spx X0R
-mknod -m 0666 spx c $(SOCKSYS_MAJOR) 1
+mknod -m 0666 spx c ${SOCKSYS_MAJOR} 1
ln spx X0R

rm -fr inet
rm -f ip icmp ggp ipip tcp egp pup udp idp rawip arp rip
mkdir -m 0755 inet

-mknod -m 0666 inet/ip c $(SOCKSYS_MAJOR) 32
-mknod -m 0666 inet/icmp c $(SOCKSYS_MAJOR) 33
-mknod -m 0666 inet/ggp c $(SOCKSYS_MAJOR) 34
-mknod -m 0666 inet/ipip c $(SOCKSYS_MAJOR) 35
-mknod -m 0666 inet/tcp c $(SOCKSYS_MAJOR) 36
-mknod -m 0666 inet/egp c $(SOCKSYS_MAJOR) 37
-mknod -m 0666 inet/pup c $(SOCKSYS_MAJOR) 38
-mknod -m 0666 inet/udp c $(SOCKSYS_MAJOR) 39
-mknod -m 0666 inet/idp c $(SOCKSYS_MAJOR) 40
-mknod -m 0666 inet/rawip c $(SOCKSYS_MAJOR) 41
+mknod -m 0666 inet/ip c ${SOCKSYS_MAJOR} 32
+mknod -m 0666 inet/icmp c ${SOCKSYS_MAJOR} 33
+mknod -m 0666 inet/ggp c ${SOCKSYS_MAJOR} 34
+mknod -m 0666 inet/ipip c ${SOCKSYS_MAJOR} 35
+mknod -m 0666 inet/tcp c ${SOCKSYS_MAJOR} 36
+mknod -m 0666 inet/egp c ${SOCKSYS_MAJOR} 37
+mknod -m 0666 inet/pup c ${SOCKSYS_MAJOR} 38
+mknod -m 0666 inet/udp c ${SOCKSYS_MAJOR} 39
+mknod -m 0666 inet/idp c ${SOCKSYS_MAJOR} 40
+mknod -m 0666 inet/rawip c ${SOCKSYS_MAJOR} 41
ln inet/udp inet/arp
ln inet/udp inet/rip
for i in ip icmp ggp ipip tcp egp pup udp idp rawip arp rip
diff -u --recursive --new-file ibcs-960201/iBCSemul/Makefile ibcs/iBCSemul/Makefile
--- ibcs-960201/iBCSemul/Makefile Thu Jan 18 10:10:25 1996
+++ ibcs/iBCSemul/Makefile Fri Mar 8 22:50:16 1996
@@ -13,12 +13,14 @@
include ../CONFIG

MODULEDIR = /usr/lib/modules
+MODFLAGS = -DMODULE # -DMODVERSIONS -include /usr/include/linux/modversions.h

EMUOPTS =
OBJS = emulate.o map.o coff.o hrtsys.o ioctl.o ipc.o mmap.o open.o \
secureware.o socket.o poll.o ptrace.o signal.o socksys.o stat.o \
stream.o sysconf.o sysfs.o sysi86.o sysinfo.o sysisc.o syslocal.o \
- timod.o ulimit.o utsname.o vtkd.o wysev386.o xnx.o xstat.o
+ timod.o ulimit.o utsname.o vtkd.o wysev386.o xnx.o xstat.o \
+ binfmt_tables.o

ifeq ($(HAVE_QUOTA),yes)
EMUOPTS := $(EMUOPTS) -DHAVE_QUOTA
@@ -99,7 +101,7 @@
endif


-CFLAGS = -D__KERNEL__=1 -DMODULE -D__NO_VERSION__ \
+CFLAGS = -D__KERNEL__=1 -D__NO_VERSION__ $(MODFLAGS) \
-I../include -Wall -Wstrict-prototypes \
-O3 -fomit-frame-pointer -m486 \
-DSOCKSYS_MAJOR=$(SOCKSYS_MAJOR) $(EMUOPTS)
diff -u --recursive --new-file ibcs-960201/iBCSemul/binfmt_aout.c ibcs/iBCSemul/binfmt_aout.c
--- ibcs-960201/iBCSemul/binfmt_aout.c Fri Jan 12 11:27:15 1996
+++ ibcs/iBCSemul/binfmt_aout.c Thu Mar 7 21:06:59 1996
@@ -9,6 +9,14 @@
* linux/fs/exec.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * 5 March 1996
+ * Tom Grigg (st588@jetson.uh.edu)
+ * Modified code to work with Linux 1.3.71.
+ *
+ * ****************** !! NOTE !! ********************
+ * This code will not work on prior verions of Linux!
+ * **************************************************
*/
#include <linux/config.h>

@@ -272,8 +280,7 @@
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)++;

- p += setup_arg_pages(ex.a_text,bprm->page);
- p -= MAX_ARG_PAGES*PAGE_SIZE;
+ p = setup_arg_pages(p, bprm);
#ifdef __NR_getsid
p = (unsigned long)create_tables((char *)p, bprm,
current->personality != PER_LINUX);
diff -u --recursive --new-file ibcs-960201/iBCSemul/binfmt_coff.c ibcs/iBCSemul/binfmt_coff.c
--- ibcs-960201/iBCSemul/binfmt_coff.c Fri Jan 12 11:27:17 1996
+++ ibcs/iBCSemul/binfmt_coff.c Thu Mar 7 21:50:34 1996
@@ -25,6 +25,14 @@
* If compile the module version of iBCS rather than the in-kernel
* version we must take care to signal when module code is in use
* or it may be freed from under us - Bad News :-).
+ *
+ * 5 March 1996
+ * Tom Grigg (st588@jetson.uh.edu)
+ * Modified code to work with Linux 1.3.71.
+ *
+ * ****************** !! NOTE !! ********************
+ * This code will not work on prior verions of Linux!
+ * **************************************************
*/

#include <linux/config.h>
@@ -563,13 +571,11 @@
* Construct the parameter and environment string table entries.
*/
#ifdef STACK_TOP
- bprm->p += setup_arg_pages (0, bprm->page);
- bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
+ bprm->p = setup_arg_pages (bprm->p, bprm);
bprm->p = (unsigned long) create_tables ((char *) bprm->p,
bprm, 1);
#else
- bprm->p += change_ldt (0, bprm->page);
- bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
+ bprm->p = change_ldt (bprm->p, bprm);
bprm->p = (unsigned long) create_tables ((char *) bprm->p,
bprm->argc,
bprm->envc,
@@ -957,7 +963,9 @@
{
unsigned long offset, nbytes;
char *buffer;
+#ifndef STACK_TOP
int old_fs;
+#endif
int status;

/*
@@ -1098,8 +1106,9 @@
else {
struct file *file; /* Pointer to the file table */
struct pt_regs regs; /* Register work area */
+#ifndef STACK_TOP
int old_fs = get_fs (); /* Previous FS register value */
-
+#endif
memset (bprm, '\0', sizeof (struct linux_binprm));

file = current->FD[fd];
diff -u --recursive --new-file ibcs-960201/iBCSemul/binfmt_tables.c ibcs/iBCSemul/binfmt_tables.c
--- ibcs-960201/iBCSemul/binfmt_tables.c Wed Dec 31 18:00:00 1969
+++ ibcs/iBCSemul/binfmt_tables.c Fri Mar 8 22:49:47 1996
@@ -0,0 +1,56 @@
+/*
+ * Derived from:
+ *
+ * linux/fs/binfmt_aout.c
+ *
+ * Copyright (C) 1991, 1992, 1996 Linus Torvalds
+ *
+ * Modified by Tom Grigg (st588@jetson.uh.edu), 7 March 1996, for iBCS
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/binfmts.h>
+#include <asm/segment.h>
+
+/*
+ * create_tables() parses the env- and arg-strings in new user
+ * memory and creates the pointer tables from them, and puts their
+ * addresses on the "stack", returning the new stack pointer value.
+ */
+unsigned long * create_tables(char * p, struct linux_binprm * bprm, int ibcs)
+{
+ unsigned long *argv,*envp;
+ unsigned long * sp;
+ int argc = bprm->argc;
+ int envc = bprm->envc;
+
+ sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
+
+ sp -= envc+1;
+ envp = sp;
+ sp -= argc+1;
+ argv = sp;
+
+ if (!ibcs) {
+ put_user(envp,--sp);
+ put_user(argv,--sp);
+ }
+
+ put_user(argc,--sp);
+ current->mm->arg_start = (unsigned long) p;
+ while (argc-->0) {
+ put_user(p,argv++);
+ while (get_user(p++)) /* nothing */ ;
+ }
+ put_user(NULL,argv);
+ current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+ while (envc-->0) {
+ put_user(p,envp++);
+ while (get_user(p++)) /* nothing */ ;
+ }
+ put_user(NULL,envp);
+ current->mm->env_end = (unsigned long) p;
+ return sp;
+}
+
diff -u --recursive --new-file ibcs-960201/iBCSemul/binfmt_xout.c ibcs/iBCSemul/binfmt_xout.c
--- ibcs-960201/iBCSemul/binfmt_xout.c Thu Jun 22 07:11:23 1995
+++ ibcs/iBCSemul/binfmt_xout.c Thu Mar 7 21:01:22 1996
@@ -9,6 +9,14 @@
* This file is based upon code written by Al Longyear for the COFF file
* format which is in turn based upon code written by Eric Youngdale for
* the ELF object file format. Any errors are most likely my own however.
+ *
+ * 5 March 1996
+ * Tom Grigg (st588@jetson.uh.edu)
+ * Modified code to work with Linux 1.3.71.
+ *
+ * ****************** !! NOTE !! ********************
+ * This code will not work on prior verions of Linux!
+ * **************************************************
*/
#include <linux/config.h>

@@ -388,8 +396,7 @@
/*
* Construct the parameter and environment string table entries.
*/
- bprm->p += change_ldt(0, bprm->page);
- bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
+ bprm->p = change_ldt(bprm->p, bprm);
#ifdef __NR_getdents
bprm->p = (unsigned long)create_tables((char *) bprm->p,
bprm,
diff -u --recursive --new-file ibcs-960201/iBCSemul/ioctl.c ibcs/iBCSemul/ioctl.c
--- ibcs-960201/iBCSemul/ioctl.c Wed Jan 24 04:22:29 1996
+++ ibcs/iBCSemul/ioctl.c Tue Mar 5 23:24:36 1996
@@ -774,7 +774,7 @@
}

memcpy_fromfs(&tx, arg, sizeof(struct termiox));
- if ((tx.x_hflag != 0 && tx.x_hflag != RTSXOFF|CTSXON)
+ if ((tx.x_hflag != 0 && tx.x_hflag != (RTSXOFF|CTSXON))
|| tx.x_cflag || tx.x_rflag[0] || tx.x_rflag[1]
|| tx.x_rflag[2] || tx.x_rflag[3] || tx.x_rflag[4]
|| tx.x_sflag)
diff -u --recursive --new-file ibcs-960201/iBCSemul/open.c ibcs/iBCSemul/open.c
--- ibcs-960201/iBCSemul/open.c Tue Dec 12 04:31:05 1995
+++ ibcs/iBCSemul/open.c Tue Mar 5 23:24:36 1996
@@ -35,6 +35,7 @@
#include <linux/malloc.h>

#include <ibcs/ibcs.h>
+#include <ibcs/xnx.h>

#ifdef __NR_getdents
#include <linux/dirent.h>
diff -u --recursive --new-file ibcs-960201/iBCSemul/socksys.c ibcs/iBCSemul/socksys.c
--- ibcs-960201/iBCSemul/socksys.c Wed Jan 24 04:22:32 1996
+++ ibcs/iBCSemul/socksys.c Tue Mar 5 23:24:36 1996
@@ -54,7 +54,7 @@
int sel_type, select_table *wait);

static int spx_write(struct inode *ino, struct file *filep,
- char *buf, int count);
+ const char *buf, int count);

/* spx_fops defines the file operations that can be applied to the
* /dev/spx server devices.
@@ -647,7 +647,7 @@


static int
-spx_write(struct inode *ino, struct file *filep, char *buf, int count)
+spx_write(struct inode *ino, struct file *filep, const char *buf, int count)
{
int newfd, err, args[3];
struct sockaddr_un addr = {
diff -u --recursive --new-file ibcs-960201/include/ibcs/ibcs.h ibcs/include/ibcs/ibcs.h
--- ibcs-960201/include/ibcs/ibcs.h Thu Dec 14 04:46:24 1995
+++ ibcs/include/ibcs/ibcs.h Fri Mar 8 21:33:51 1996
@@ -92,6 +92,9 @@
int len;
};

+/* binfmt_tables.c */
+extern unsigned long * create_tables(char * p, struct linux_binprm * bprm, int ibcs);
+
/* coff.c */
extern int ibcs_brk(unsigned long newbrk);
extern int ibcs_fork(struct pt_regs * regs);

--
Tom Grigg
st588@jetson.uh.edu
http://www.egr.uh.edu/~eac64750/tom/