2
0
Fork 0

Removed patches. They are no longer needed.

This commit is contained in:
mike 1996-01-03 12:49:58 +00:00
parent 99cd6c74da
commit 53dadf61de
7 changed files with 7 additions and 1537 deletions

View file

@ -1,5 +1,12 @@
Wed Jan 3 12:16:47 GMT/BST 1996
* Removed all kernel patches in the Patches directory. None
should be need for kernels 1.3.50 (or earlier?) and onwards.
None should be essential for 1.2.13 - although some capability
is lost notably SCO OpenServer 5 ELF binaries (if the kernel
ELF loader is present) and BSD a.out binaries.
-- Mike
* Another fix to termio[s] ioctls to get the control character
settings right for SVR4. Previously this was just copied
from the SCO mapping and just never got changed.

View file

@ -1,748 +0,0 @@
Patches to 1.0 to add support for the iBCS emulator.
This moves the iBCS stuff clear of the standard kernel but allows the
iBCS module to be loaded by a standard kernel.
This patch file is annotated. If you need to apply this you ought to
read it first!
This patch file creates some new header files. To get them in the
correct place you should be using 'patch -p0' or 'patch -p1' if you
are in the linux source directory already.
===========================================================================
ELF/COFF support is bundled together as IBCS support now. If you say
yes to this question you'll get the iBCS emulator linked in to your
kernel (assuming you have replaced the stub ibcs directory with the
real one). If you say no (which I recommend) you'll get kernel hooks
for the loadable module form of the iBCS emulator regardless of whether
you have the full emulator or not. If you have replaced the stub ibcs
directory with the real one you'll also get the iBCS module built for you.
===========================================================================
diff -u linux/config.in:1.1.1.1 linux/config.in:1.1.1.1.8.1
--- linux/config.in:1.1.1.1 Tue Mar 15 17:05:25 1994
+++ linux/config.in Tue Mar 15 17:05:25 1994
@@ -15,8 +15,7 @@
*
* Program binary formats
*
-bool 'Elf executables' CONFIG_BINFMT_ELF n
-bool 'COFF executables' CONFIG_BINFMT_COFF n
+bool 'Link with Elf/COFF support' CONFIG_BINFMT_IBCS n
*
* SCSI support
*
============================================================================
The ELF and COFF loaders are now in the (full) ibcs directory. If you
don't have the full ibcs emulator you don't need these. You should
delete the binfmt_elf.c and binfmt_coff.c files from the fs directory
since these are no further use right now.
============================================================================
diff -u linux/fs/Makefile:1.1.1.1 linux/fs/Makefile:1.1.1.1.8.1
--- linux/fs/Makefile:1.1.1.1 Tue Mar 15 17:05:30 1994
+++ linux/fs/Makefile Tue Mar 15 17:05:30 1994
@@ -40,12 +40,6 @@
FS_SUBDIRS := $(FS_SUBDIRS) hpfs
endif
-ifdef CONFIG_BINFMT_ELF
-BINFMTS := $(BINFMTS) binfmt_elf.o
-endif
-ifdef CONFIG_BINFMT_COFF
-BINFMTS := $(BINFMTS) binfmt_coff.o
-endif
.c.s:
$(CC) $(CFLAGS) -S $<
===========================================================================
The flag that indicates an ELF executable becomes a more general
purpose code that indicates the "personality" of an executable
allowing us to correctly emulate different sets of system calls
(SVR3 vendors tend to extend the base SVR3 set with their own
without following any particular standard - symlinks support is
a common problem). The "personality" can also be used to emulate
lower level kernel "features". <evil laugh>
============================================================================
diff -u linux/include/linux/sched.h:1.1.1.1 linux/include/linux/sched.h:1.1.1.1.8.1
--- linux/include/linux/sched.h:1.1.1.1 Tue Mar 15 17:05:36 1994
+++ linux/include/linux/sched.h Tue Mar 15 17:05:36 1994
@@ -180,7 +180,7 @@
unsigned long saved_kernel_stack;
unsigned long kernel_stack_page;
int exit_code, exit_signal;
- int elf_executable:1;
+ unsigned long personality;
int dumpable:1;
int swappable:1;
int did_exec:1;
diff -u /dev/null linux/include/linux/personality.h:1.1.2.1
--- /dev/null Tue Mar 15 17:05:36 1994
+++ linux/include/linux/personality.h Tue Mar 15 17:05:36 1994
@@ -0,0 +1,12 @@
+/* Flags for bug emulation. These occupy the top three bytes. */
+#define STICKY_TIMEOUTS 0x8000000
+#define WHOLE_SECONDS 0x4000000
+
+/* Personality types. These go in the low byte. */
+#define PER_MASK (0x00ff)
+#define PER_LINUX (0x0000)
+#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS)
+#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS)
+#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)
+#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS)
+#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS)
===========================================================================
For the standard (Linux) exec we just default the personality to
zero. The ELF and COFF loaders (which are now in the full ibcs
directory) default to SVR4 and SVR3 respectively.
We also leave slots in the table of loaders so that we can hook
in the ELF, COFF and XOUT loaders when the iBCS module is loaded.
============================================================================
diff -u linux/fs/exec.c:1.1.1.1 linux/fs/exec.c:1.1.1.1.8.1
--- linux/fs/exec.c:1.1.1.1 Tue Mar 15 17:05:31 1994
+++ linux/fs/exec.c Wed Mar 23 09:38:31 1994
@@ -530,13 +530,13 @@
if (last_task_used_math == current)
last_task_used_math = NULL;
current->used_math = 0;
- current->elf_executable = 0;
+ current->personality = 0;
}
/*
* sys_execve() executes a new program.
*/
-static int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs)
+int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs)
{
struct linux_binprm bprm;
struct linux_binfmt * fmt;
@@ -730,26 +730,34 @@
struct pt_regs * regs);
extern int load_aout_library(int fd);
-#ifdef CONFIG_BINFMT_ELF
+#ifdef CONFIG_BINFMT_IBCS
+/* These come from the loaders in the linux/ibcs directory. */
extern int load_elf_binary(struct linux_binprm *,
struct pt_regs * regs);
extern int load_elf_library(int fd);
-#endif
-#ifdef CONFIG_BINFMT_COFF
extern int load_coff_binary(struct linux_binprm *,
struct pt_regs * regs);
extern int load_coff_library(int fd);
+
+extern int load_xout_binary(struct linux_binprm *,
+ struct pt_regs * regs);
+extern int load_xout_library(int fd);
#endif
/* Here are the actual binaries that will be accepted */
struct linux_binfmt formats[] = {
{load_aout_binary, load_aout_library},
-#ifdef CONFIG_BINFMT_ELF
+#ifdef CONFIG_BINFMT_IBCS
{load_elf_binary, load_elf_library},
-#endif
-#ifdef CONFIG_BINFMT_COFF
{load_coff_binary, load_coff_library},
+ {load_xout_binary, load_xout_library},
+#endif
+#ifndef CONFIG_BINFMT_IBCS
+ /* Not compiled in so leave slots for the module to be loaded. */
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
#endif
{NULL, NULL}
};
===========================================================================
Ok, here's the demo kernel "feature" :-). Some systems expect the
timeout value in a select to be left unchanged. Currently this is
the only kernel "feature" emulated. Others may be necessary?
============================================================================
diff -u linux/fs/select.c:1.1.1.1 linux/fs/select.c:1.1.1.1.8.1
--- linux/fs/select.c:1.1.1.1 Tue Mar 15 17:05:31 1994
+++ linux/fs/select.c Tue Mar 15 17:05:31 1994
@@ -3,6 +3,11 @@
*
* Created for Linux based loosely upon Mathius Lattner's minix
* patches by Peter MacDonald. Heavily edited by Linus.
+ *
+ * 4 February 1994
+ * COFF/ELF binary emulation. If the process has the STICKY_TIMEOUTS
+ * flag set in its personality we do *not* modify the given timeout
+ * parameter to reflect time remaining.
*/
#include <linux/types.h>
@@ -14,6 +19,7 @@
#include <linux/stat.h>
#include <linux/signal.h>
#include <linux/errno.h>
+#include <linux/personality.h>
#include <asm/segment.h>
#include <asm/system.h>
@@ -235,7 +241,7 @@
else
timeout = 0;
current->timeout = 0;
- if (tvp) {
+ if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
put_fs_long(timeout/HZ, (unsigned long *) &tvp->tv_sec);
timeout %= HZ;
timeout *= (1000000/HZ);
============================================================================
Change the stub ibcs emulator so it has a hook for the loadable
module to attach to. The kernel will be capable of loading the
iBCS module even if only the stub ibcs code was compiled.
============================================================================
diff -u linux/ibcs/emulate.c:1.1.1.1 linux/ibcs/emulate.c:1.1.1.1.8.1
--- linux/ibcs/emulate.c:1.1.1.1 Tue Mar 15 17:05:33 1994
+++ linux/ibcs/emulate.c Tue Mar 15 17:05:34 1994
@@ -20,8 +20,14 @@
#include <asm/segment.h>
#include <asm/system.h>
+void (* iABI_hook)(struct pt_regs * regs) = NULL;
+
asmlinkage void iABI_emulate(struct pt_regs * regs)
{
- printk("iBCS2 binaries not supported yet\n");
- do_exit(SIGSEGV);
+ if (iABI_hook) {
+ iABI_hook(regs);
+ } else {
+ printk(KERN_INFO "iBCS: emulation module not loaded\n");
+ do_exit(SIGSEGV);
+ }
}
============================================================================
Add the symbols that the loadable iBCS module requires to the table
used by the modules code.
============================================================================
diff -u linux/kernel/ksyms.S:1.1.1.1 linux/kernel/ksyms.S:1.1.1.1.8.1
--- linux/kernel/ksyms.S:1.1.1.1 Tue Mar 15 17:05:38 1994
+++ linux/kernel/ksyms.S Tue Mar 15 17:05:38 1994
@@ -7,6 +7,7 @@
* Jon.
*/
+_sys_call_table
_register_chrdev
_unregister_chrdev
_register_blkdev
@@ -27,4 +28,59 @@
#
_ftape_big_buffer
_do_floppy
+#endif
+
+#ifndef CONFIG_BINFMT_IBCS
+#
+# The following are needed if iBCS support is modular rather than
+# compiled in.
+#
+___get_free_page
+_change_ldt
+_check_pending
+_copy_strings
+_create_tables
+_do_execve
+_do_mmap
+_do_signal
+_EISA_bus
+_file_systems
+_flush_old_exec
+_formats
+_free_page
+_getname
+_iABI_hook
+_ibcs_invmapsig
+_insert_vm_struct
+_iput
+_kfree_s
+_kmalloc
+_lnamei
+_namei
+_open_inode
+_putname
+_read_exec
+_send_sig
+_si_meminfo
+_sprintf
+_strcmp
+_strcpy
+_system_utsname
+_waitpid
+_zeromap_page_range
+
+_sock_lseek
+_sock_read
+_sock_write
+_sock_readdir
+_sock_close
+_sock_select
+_sock_ioctl
+_sock_getpeername
+_socki_lookup
+_sock_getsockopt
+_sock_setsockopt
+_sock_socket
+_sock_connect
+
#endif
============================================================================
After sorting the list of symbols remove the duplicates. We don't
want them.
============================================================================
diff -u linux/kernel/ksyms.sh:1.1.1.1 linux/kernel/ksyms.sh:1.1.1.1.8.1
--- linux/kernel/ksyms.sh:1.1.1.1 Tue Mar 15 17:05:38 1994
+++ linux/kernel/ksyms.sh Tue Mar 15 17:05:38 1994
@@ -12,7 +12,7 @@
trap "rm -f ksyms.tmp ksyms.lst ; exit 1" 1 2
-sed -e '/^#/d' -e '/^[ ]*$/d' ksyms.lst | sort > ksyms.tmp
+sed -e '/^#/d' -e '/^[ ]*$/d' ksyms.lst | sort | uniq > ksyms.tmp
echo ' .data
.globl _symbol_table_size, _symbol_table
=============================================================================
The TCP/IP interface emulators in the iBCS module need to hook in to
the socket layer. We remove a load of statics and prototype the
functions in a new header, sockfunc.h. We use a new header because
putting them in socket.h means socket.h then requires various other
headers which makes for dependency loops between things.
============================================================================
diff -u /dev/null linux/include/linux/sockfunc.h:1.1.2.1
--- /dev/null Tue Mar 15 17:05:37 1994
+++ linux/include/linux/sockfunc.h Tue Mar 15 17:05:37 1994
@@ -0,0 +1,27 @@
+#ifndef _LINUX_SOCKFUNC_H
+#define _LINUX_SOCKFUNC_H
+
+#ifdef __KERNEL__
+extern int sock_lseek(struct inode *inode, struct file *file, off_t offset,
+ int whence);
+extern int sock_read(struct inode *inode, struct file *file, char *buf,
+ int size);
+extern int sock_write(struct inode *inode, struct file *file, char *buf,
+ int size);
+extern int sock_readdir(struct inode *inode, struct file *file,
+ struct dirent *dirent, int count);
+extern void sock_close(struct inode *inode, struct file *file);
+extern int sock_select(struct inode *inode, struct file *file, int which, select_table *seltable);
+extern int sock_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+extern int sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
+extern int sock_getsockopt(int fd, int level, int optname, char *optval, int optlen);
+extern int sock_setsockopt(int fd, int level, int optname, char *optval, int optlen);
+
+extern int sock_socket(int family, int type, int protocol);
+extern int sock_connect(int fd, struct sockaddr *uservaddr, int addrlen);
+
+extern struct socket * socki_lookup(struct inode *inode);
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SOCKFUNC_H */
diff -u linux/net/socket.c:1.1.1.1 linux/net/socket.c:1.1.1.1.8.1
--- linux/net/socket.c:1.1.1.1 Tue Mar 15 17:05:39 1994
+++ linux/net/socket.c Tue Mar 15 17:05:39 1994
@@ -43,17 +43,17 @@
#define DPRINTF(x) /**/
#endif
-static int sock_lseek(struct inode *inode, struct file *file, off_t offset,
+int sock_lseek(struct inode *inode, struct file *file, off_t offset,
int whence);
-static int sock_read(struct inode *inode, struct file *file, char *buf,
+int sock_read(struct inode *inode, struct file *file, char *buf,
int size);
-static int sock_write(struct inode *inode, struct file *file, char *buf,
+int sock_write(struct inode *inode, struct file *file, char *buf,
int size);
-static int sock_readdir(struct inode *inode, struct file *file,
+int sock_readdir(struct inode *inode, struct file *file,
struct dirent *dirent, int count);
-static void sock_close(struct inode *inode, struct file *file);
-static int sock_select(struct inode *inode, struct file *file, int which, select_table *seltable);
-static int sock_ioctl(struct inode *inode, struct file *file,
+void sock_close(struct inode *inode, struct file *file);
+int sock_select(struct inode *inode, struct file *file, int which, select_table *seltable);
+int sock_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
@@ -260,7 +260,7 @@
}
-static int
+int
sock_lseek(struct inode *inode, struct file *file, off_t offset, int whence)
{
DPRINTF((net_debug, "NET: sock_lseek: huh?\n"));
@@ -268,7 +268,7 @@
}
-static int
+int
sock_read(struct inode *inode, struct file *file, char *ubuf, int size)
{
struct socket *sock;
@@ -283,7 +283,7 @@
}
-static int
+int
sock_write(struct inode *inode, struct file *file, char *ubuf, int size)
{
struct socket *sock;
@@ -298,7 +298,7 @@
}
-static int
+int
sock_readdir(struct inode *inode, struct file *file, struct dirent *dirent,
int count)
{
@@ -323,7 +323,7 @@
}
-static int
+int
sock_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
{
struct socket *sock;
@@ -424,7 +424,7 @@
* Perform the socket system call. we locate the appropriate
* family, then create a fresh socket.
*/
-static int
+int
sock_socket(int family, int type, int protocol)
{
int i, fd;
@@ -635,7 +635,7 @@
/* Attempt to connect to a socket with the server address. */
-static int
+int
sock_connect(int fd, struct sockaddr *uservaddr, int addrlen)
{
struct socket *sock;
@@ -685,7 +685,7 @@
}
-static int
+int
sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
{
struct socket *sock;
@@ -774,42 +774,66 @@
}
-static int
+/*
+ * This is meant for all protocols to use and covers goings on
+ * at the socket level. Everything here is generic.
+ */
+
+int
sock_setsockopt(int fd, int level, int optname, char *optval, int optlen)
{
- struct socket *sock;
- struct file *file;
+ struct socket *sock;
+ struct file *file;
- DPRINTF((net_debug, "NET: sock_setsockopt(fd=%d, level=%d, optname=%d,\n",
- fd, level, optname));
- DPRINTF((net_debug, " optval = %X, optlen = %d)\n",
- optval, optlen));
-
- if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
- return(-EBADF);
- if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
-
- return(sock->ops->setsockopt(sock, level, optname, optval, optlen));
+ DPRINTF((net_debug, "NET: sock_setsockopt(fd=%d, level=%d, optname=%d,\n",
+ fd, level, optname));
+ DPRINTF((net_debug, " optval = %X, optlen = %d)\n",
+ optval, optlen));
+
+ /* If it isn't a valid file... */
+ if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
+ return(-EBADF);
+
+ /* Or if it isn't a socket... */
+ if (!(sock = sockfd_lookup(fd, NULL)))
+ return(-ENOTSOCK);
+
+ /* Or if we don't have a value for the option... */
+ if (optval == NULL)
+ return -EINVAL;
+
+ if (!sock->ops || !sock->ops->setsockopt)
+ return -EOPNOTSUPP;
+ else
+ return (sock->ops->setsockopt(sock, level,
+ optname, optval, optlen));
}
-static int
+int
sock_getsockopt(int fd, int level, int optname, char *optval, int *optlen)
{
- struct socket *sock;
- struct file *file;
+ struct socket *sock;
+ struct file *file;
- DPRINTF((net_debug, "NET: sock_getsockopt(fd=%d, level=%d, optname=%d,\n",
- fd, level, optname));
- DPRINTF((net_debug, " optval = %X, optlen = %X)\n",
- optval, optlen));
-
- if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
- return(-EBADF);
- if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
+ DPRINTF((net_debug, "NET: sock_getsockopt(fd=%d, level=%d, optname=%d,\n",
+ fd, level, optname));
+ DPRINTF((net_debug, " optval = %X, optlen = %X)\n",
+ optval, optlen));
+
+ /* If it isn't a valid file... */
+ if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
+ return(-EBADF);
+
+ /* Or if it isn't a socket... */
+ if (!(sock = sockfd_lookup(fd, NULL)))
+ return -ENOTSOCK;
- if (!sock->ops || !sock->ops->getsockopt) return(0);
- return(sock->ops->getsockopt(sock, level, optname, optval, optlen));
+ if (!sock->ops || !sock->ops->getsockopt)
+ return -EOPNOTSUPP;
+ else
+ return (sock->ops->getsockopt(sock, level,
+ optname, optval, optlen));
}
=============================================================================
Tidy up the inet socket option routines to avoid multiple global
sock_{get,set}sockopt() functions.
============================================================================
diff -u linux/net/inet/sock.c:1.1.1.1 linux/net/inet/sock.c:1.1.1.1.8.1
--- linux/net/inet/sock.c:1.1.1.1 Tue Mar 15 17:05:40 1994
+++ linux/net/inet/sock.c Tue Mar 15 17:05:42 1994
@@ -483,43 +483,19 @@
char *optval, int optlen)
{
struct sock *sk = (struct sock *) sock->data;
- if (level == SOL_SOCKET)
- return sock_setsockopt(sk,level,optname,optval,optlen);
- if (sk->prot->setsockopt==NULL)
- return(-EOPNOTSUPP);
- else
- return sk->prot->setsockopt(sk,level,optname,optval,optlen);
-}
-
-
-
-
-static int inet_getsockopt(struct socket *sock, int level, int optname,
- char *optval, int *optlen)
-{
- struct sock *sk = (struct sock *) sock->data;
- if (level == SOL_SOCKET)
- return sock_getsockopt(sk,level,optname,optval,optlen);
- if(sk->prot->getsockopt==NULL)
- return(-EOPNOTSUPP);
- else
- return sk->prot->getsockopt(sk,level,optname,optval,optlen);
-}
-
-/*
- * This is meant for all protocols to use and covers goings on
- * at the socket level. Everything here is generic.
- */
-
-int sock_setsockopt(struct sock *sk, int level, int optname,
- char *optval, int optlen)
-{
- int val;
int err;
+ int val;
struct linger ling;
- if (optval == NULL)
- return(-EINVAL);
+ /* If it isn't for the socket layer pass it down to the
+ * protocol layer.
+ */
+ if (level != SOL_SOCKET)
+ if (!sk->prot || !sk->prot->setsockopt)
+ return(-EOPNOTSUPP);
+ else
+ return sk->prot->setsockopt(sk, level,
+ optname, optval, optlen);
err=verify_area(VERIFY_READ, optval, sizeof(int));
if(err)
@@ -612,13 +588,28 @@
}
-int sock_getsockopt(struct sock *sk, int level, int optname,
- char *optval, int *optlen)
-{
- int val;
+
+
+static int inet_getsockopt(struct socket *sock, int level, int optname,
+ char *optval, int *optlen)
+{
+ struct sock *sk = (struct sock *) sock->data;
int err;
+ int val;
struct linger ling;
+ /* If it isn't for the socket layer pass it down to the
+ * protocol layer.
+ */
+ if (level != SOL_SOCKET)
+ if(!sk->prot || !sk->prot->getsockopt)
+ return(-EOPNOTSUPP);
+ else
+ return sk->prot->getsockopt(sk, level,
+ optname, optval, optlen);
+
+ sk = (struct sock *) sock->data;
+
switch(optname)
{
case SO_DEBUG:
@@ -663,10 +654,7 @@
break;
case SO_TYPE:
- if (sk->prot == &tcp_prot)
- val = SOCK_STREAM;
- else
- val = SOCK_DGRAM;
+ val = sock->type;
break;
case SO_ERROR:
=============================================================================
We also need to change the signal routines slightly to give us an
iBCS stack frame.
============================================================================
diff -u linux/kernel/signal.c:1.1.1.1 linux/kernel/signal.c:1.1.1.1.8.1
--- linux/kernel/signal.c:1.1.1.1 Tue Mar 15 17:05:38 1994
+++ linux/kernel/signal.c Tue Mar 15 17:05:38 1994
@@ -137,7 +137,7 @@
* isn't actually ignored, but does automatic child reaping, while
* SIG_DFL is explicitly said by POSIX to force the signal to be ignored..
*/
-static void check_pending(int signum)
+void check_pending(int signum)
{
struct sigaction *p;
@@ -248,6 +248,8 @@
do_exit(SIGSEGV);
}
+int (*ibcs_invmapsig)(int) = NULL;
+
/*
* Set up a signal frame... Make the stack look the way iBCS2 expects
* it to look.
@@ -267,7 +269,10 @@
do_exit(SIGSEGV);
/* set up the "normal" stack seen by the signal handler (iBCS2) */
put_fs_long(__CODE,frame);
- put_fs_long(signr, frame+1);
+ if(current->personality && ibcs_invmapsig)
+ put_fs_long(ibcs_invmapsig(signr), frame+1);
+ else
+ put_fs_long(signr, frame+1);
put_fs_long(regs->gs, frame+2);
put_fs_long(regs->fs, frame+3);
put_fs_long(regs->es, frame+4);
That's all, folks!
(You actually *read* this then?)

View file

@ -1,249 +0,0 @@
===================================================================
RCS file: /var/CVS/linux/fs/exec.c,v
retrieving revision 1.1.1.1.14.16
diff -u -r1.1.1.1.14.16 exec.c
--- 1.1.1.1.14.16 1994/11/07 09:45:18
+++ exec.c 1994/11/07 09:55:54
@@ -38,6 +38,7 @@
#include <linux/user.h>
#include <linux/segment.h>
#include <linux/malloc.h>
+#include <linux/in.h> /* for ntohl() */
#include <asm/system.h>
@@ -790,29 +791,94 @@
struct file * file;
int fd, error;
unsigned long p = bprm->p;
- unsigned long fd_offset;
-
- ex = *((struct exec *) bprm->buf); /* exec-header */
- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
- N_MAGIC(ex) != QMAGIC) ||
- ex.a_trsize || ex.a_drsize ||
- bprm->inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
+ unsigned long fd_offset, vm_offset;
+ unsigned long pers;
+ unsigned long rlim;
+
+ ex = *((struct exec *) bprm->buf);
+
+ /* Basic sanity checks. There should be no relocation information
+ * and the size of the file must be greater than the total text
+ * plus data size.
+ */
+ if (ex.a_trsize || ex.a_drsize
+ || ex.a_text + ex.a_data > bprm->inode->i_size)
return -ENOEXEC;
- }
- current->personality = PER_LINUX;
- fd_offset = N_TXTOFF(ex);
- if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
- printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
- return -ENOEXEC;
- }
+ /* If the machine type is zero assume a BSD flavour, Linux uses
+ * M_386 (100) as the machine type except on very old binaries
+ * which can easily be updated using the lnxstamp program supplied
+ * as part of the iBCS/BSD emulator.
+ */
+ pers = (N_MACHTYPE(ex) == 100 ? PER_LINUX : PER_BSD);
+
+ /* Set up the file and vm offsets based on the type of
+ * executable.
+ */
+ switch (ex.a_info & 0xffff) {
+ case ZMAGIC: /* demand paged executable */
+ /* Alignment varies. If there is no symbol table
+ * we can work out the offset to the text start
+ * easily. If there is a symbol table we would
+ * have to walk it to find out the size of the
+ * string pool so in this case we guess at the
+ * "standard" Linux alignment. Alignment doesn't
+ * imply personality is known though...
+ */
+ if (ex.a_text == 0) {
+ /* Bill's 386bsd used a code-in-data kludge
+ * on the boot disk.
+ */
+ fd_offset = 0;
+ } else if (ex.a_syms == 0) {
+ fd_offset = (bprm->inode->i_size
+ - ex.a_text - ex.a_data)
+ & (~15);
+ } else {
+ fd_offset = N_TXTOFF(ex);
+ }
+ vm_offset = 0;
+ break;
- if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
- (fd_offset < bprm->inode->i_sb->s_blocksize)) {
- printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
- return -ENOEXEC;
+ case QMAGIC: /* demand paged with page 0 unmapped */
+ fd_offset = 0;
+ vm_offset = PAGE_SIZE;
+ break;
+
+ case OMAGIC: /* impure executable */
+ fd_offset = 32;
+ vm_offset = 0;
+ break;
+
+ default:
+ /* NetBSD puts the info field in network byte
+ * order instead of host order. Why? It also
+ * treats ZMAGIC and QMAGIC identically with
+ * regards leaving page 0 unmapped.
+ */
+ switch (ntohl(ex.a_info) & 0xffff) {
+ case ZMAGIC:
+ case QMAGIC:
+ pers = PER_BSD;
+ fd_offset = 0;
+ vm_offset = PAGE_SIZE;
+ break;
+
+ default:
+ return -ENOEXEC;
+ }
}
+ /* Check initial limits. This avoids letting people circumvent
+ * size limits imposed on them by creating programs with large
+ * arrays in the data or bss.
+ */
+ rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+ if (rlim >= RLIM_INFINITY)
+ rlim = ~0;
+ if (ex.a_data + ex.a_bss > rlim)
+ return -ENOMEM;
+
/* OK, This is the point of no return */
flush_old_exec(bprm);
@@ -820,61 +886,74 @@
(current->mm->start_brk =
(current->mm->end_data = ex.a_data +
(current->mm->end_code = ex.a_text +
- (current->mm->start_code = N_TXTADDR(ex)))));
+ (current->mm->start_code = vm_offset))));
current->mm->rss = 0;
current->mm->mmap = NULL;
- current->suid = current->euid = current->fsuid = bprm->e_uid;
- current->sgid = current->egid = current->fsgid = bprm->e_gid;
- if (N_MAGIC(ex) == OMAGIC) {
- do_mmap(NULL, 0, ex.a_text+ex.a_data,
+ current->suid = current->euid = current->fsuid = bprm->e_uid;
+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
+ /* If the file offset is not on a filesystem block boundary treat
+ * the file as impure and slurp the lot in. Theory says we should
+ * able to slurp in the odd bits at the start and end of text and
+ * data segments and mmap the blocks in between. This might be useful
+ * for the cases where filesystems with differing block sizes are
+ * in use or the programmer is just thick. It isn't implemented
+ * yet however.
+ * Also slurp the data if the filesystem doesn't support mmap.
+ */
+ fd = open_inode(bprm->inode, O_RDONLY);
+ if (fd < 0) {
+ /* Too late! We're doomed... */
+ send_sig(SIGSEGV, current, 0);
+ return fd;
+ }
+ file = current->files->fd[fd];
+ if (fd_offset % bprm->inode->i_sb->s_blocksize
+ || !file->f_op || !file->f_op->mmap) {
+ sys_close(fd);
+ do_mmap(NULL, vm_offset, ex.a_text+ex.a_data,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data);
+ read_exec(bprm->inode, fd_offset, (char *)vm_offset,
+ ex.a_text+ex.a_data);
} else {
- if (ex.a_text & 0xfff || ex.a_data & 0xfff)
- printk(KERN_NOTICE "executable not page aligned\n");
-
- fd = open_inode(bprm->inode, O_RDONLY);
-
- if (fd < 0)
- return fd;
- file = current->files->fd[fd];
- if (!file->f_op || !file->f_op->mmap) {
- sys_close(fd);
- do_mmap(NULL, 0, ex.a_text+ex.a_data,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, fd_offset,
- (char *) N_TXTADDR(ex), ex.a_text+ex.a_data);
- goto beyond_if;
- }
-
- error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
- PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
- fd_offset);
-
- if (error != N_TXTADDR(ex)) {
- sys_close(fd);
- send_sig(SIGKILL, current, 0);
- return error;
+ /* Don't forget that Bill's 386bsd data-in-text kludge
+ * won't have any text.
+ */
+ if (ex.a_text) {
+ error = do_mmap(file, vm_offset, ex.a_text,
+ PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_SHARED | MAP_DENYWRITE | MAP_EXECUTABLE,
+ fd_offset);
+
+ if (error != vm_offset) {
+ sys_close(fd);
+ send_sig(SIGSEGV, current, 0);
+ return -EINVAL;
+ }
}
- error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data,
+ /* N.B. Linux makes data executable. BSD doesn't (unless
+ * using Bill's code-in-data kludge).
+ */
+ error = do_mmap(file, vm_offset + ex.a_text, ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
sys_close(fd);
- if (error != N_TXTADDR(ex) + ex.a_text) {
- send_sig(SIGKILL, current, 0);
- return error;
+ if (error != vm_offset + ex.a_text) {
+ send_sig(SIGSEGV, current, 0);
+ return -EINVAL;
}
}
-beyond_if:
+
+ set_brk(current->mm->start_brk, current->mm->brk);
+
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)--;
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)--;
+ current->personality = pers;
current->exec_domain = lookup_exec_domain(current->personality);
current->binfmt = &aout_format;
if (current->exec_domain && current->exec_domain->use_count)
@@ -882,8 +961,6 @@
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)++;
- set_brk(current->mm->start_brk, current->mm->brk);
-
p += change_ldt(ex.a_text,bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long)create_tables((char *)p,

View file

@ -1,249 +0,0 @@
===================================================================
RCS file: /var/CVS/linux/fs/exec.c,v
retrieving revision 1.1.1.1.14.18
diff -u -r1.1.1.1.14.18 exec.c
--- 1.1.1.1.14.18 1994/12/01 12:10:48
+++ exec.c 1994/12/01 12:26:24
@@ -39,6 +39,7 @@
#include <linux/malloc.h>
#include <linux/binfmts.h>
#include <linux/personality.h>
+#include <linux/in.h> /* for ntohl() */
#include <asm/system.h>
#include <asm/segment.h>
@@ -798,29 +799,94 @@
struct file * file;
int fd, error;
unsigned long p = bprm->p;
- unsigned long fd_offset;
-
- ex = *((struct exec *) bprm->buf); /* exec-header */
- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
- N_MAGIC(ex) != QMAGIC) ||
- ex.a_trsize || ex.a_drsize ||
- bprm->inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
+ unsigned long fd_offset, vm_offset;
+ unsigned long pers;
+ unsigned long rlim;
+
+ ex = *((struct exec *) bprm->buf);
+
+ /* Basic sanity checks. There should be no relocation information
+ * and the size of the file must be greater than the total text
+ * plus data size.
+ */
+ if (ex.a_trsize || ex.a_drsize
+ || ex.a_text + ex.a_data > bprm->inode->i_size)
return -ENOEXEC;
- }
- current->personality = PER_LINUX;
- fd_offset = N_TXTOFF(ex);
- if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
- printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
- return -ENOEXEC;
- }
+ /* If the machine type is zero assume a BSD flavour, Linux uses
+ * M_386 (100) as the machine type except on very old binaries
+ * which can easily be updated using the lnxstamp program supplied
+ * as part of the iBCS/BSD emulator.
+ */
+ pers = (N_MACHTYPE(ex) == 100 ? PER_LINUX : PER_BSD);
+
+ /* Set up the file and vm offsets based on the type of
+ * executable.
+ */
+ switch (ex.a_info & 0xffff) {
+ case ZMAGIC: /* demand paged executable */
+ /* Alignment varies. If there is no symbol table
+ * we can work out the offset to the text start
+ * easily. If there is a symbol table we would
+ * have to walk it to find out the size of the
+ * string pool so in this case we guess at the
+ * "standard" Linux alignment. Alignment doesn't
+ * imply personality is known though...
+ */
+ if (ex.a_text == 0) {
+ /* Bill's 386bsd used a code-in-data kludge
+ * on the boot disk.
+ */
+ fd_offset = 0;
+ } else if (ex.a_syms == 0) {
+ fd_offset = (bprm->inode->i_size
+ - ex.a_text - ex.a_data)
+ & (~15);
+ } else {
+ fd_offset = N_TXTOFF(ex);
+ }
+ vm_offset = 0;
+ break;
- if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
- (fd_offset < bprm->inode->i_sb->s_blocksize)) {
- printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
- return -ENOEXEC;
+ case QMAGIC: /* demand paged with page 0 unmapped */
+ fd_offset = 0;
+ vm_offset = PAGE_SIZE;
+ break;
+
+ case OMAGIC: /* impure executable */
+ fd_offset = 32;
+ vm_offset = 0;
+ break;
+
+ default:
+ /* NetBSD puts the info field in network byte
+ * order instead of host order. Why? It also
+ * treats ZMAGIC and QMAGIC identically with
+ * regards leaving page 0 unmapped.
+ */
+ switch (ntohl(ex.a_info) & 0xffff) {
+ case ZMAGIC:
+ case QMAGIC:
+ pers = PER_BSD;
+ fd_offset = 0;
+ vm_offset = PAGE_SIZE;
+ break;
+
+ default:
+ return -ENOEXEC;
+ }
}
+ /* Check initial limits. This avoids letting people circumvent
+ * size limits imposed on them by creating programs with large
+ * arrays in the data or bss.
+ */
+ rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+ if (rlim >= RLIM_INFINITY)
+ rlim = ~0;
+ if (ex.a_data + ex.a_bss > rlim)
+ return -ENOMEM;
+
/* OK, This is the point of no return */
flush_old_exec(bprm);
@@ -828,61 +894,74 @@
(current->mm->start_brk =
(current->mm->end_data = ex.a_data +
(current->mm->end_code = ex.a_text +
- (current->mm->start_code = N_TXTADDR(ex)))));
+ (current->mm->start_code = vm_offset))));
current->mm->rss = 0;
current->mm->mmap = NULL;
- current->suid = current->euid = current->fsuid = bprm->e_uid;
- current->sgid = current->egid = current->fsgid = bprm->e_gid;
- if (N_MAGIC(ex) == OMAGIC) {
- do_mmap(NULL, 0, ex.a_text+ex.a_data,
+ current->suid = current->euid = current->fsuid = bprm->e_uid;
+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
+ /* If the file offset is not on a filesystem block boundary treat
+ * the file as impure and slurp the lot in. Theory says we should
+ * able to slurp in the odd bits at the start and end of text and
+ * data segments and mmap the blocks in between. This might be useful
+ * for the cases where filesystems with differing block sizes are
+ * in use or the programmer is just thick. It isn't implemented
+ * yet however.
+ * Also slurp the data if the filesystem doesn't support mmap.
+ */
+ fd = open_inode(bprm->inode, O_RDONLY);
+ if (fd < 0) {
+ /* Too late! We're doomed... */
+ send_sig(SIGSEGV, current, 0);
+ return fd;
+ }
+ file = current->files->fd[fd];
+ if (fd_offset % bprm->inode->i_sb->s_blocksize
+ || !file->f_op || !file->f_op->mmap) {
+ sys_close(fd);
+ do_mmap(NULL, vm_offset, ex.a_text+ex.a_data,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data);
+ read_exec(bprm->inode, fd_offset, (char *)vm_offset,
+ ex.a_text+ex.a_data);
} else {
- if (ex.a_text & 0xfff || ex.a_data & 0xfff)
- printk(KERN_NOTICE "executable not page aligned\n");
-
- fd = open_inode(bprm->inode, O_RDONLY);
-
- if (fd < 0)
- return fd;
- file = current->files->fd[fd];
- if (!file->f_op || !file->f_op->mmap) {
- sys_close(fd);
- do_mmap(NULL, 0, ex.a_text+ex.a_data,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, fd_offset,
- (char *) N_TXTADDR(ex), ex.a_text+ex.a_data);
- goto beyond_if;
- }
-
- error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
- PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
- fd_offset);
-
- if (error != N_TXTADDR(ex)) {
- sys_close(fd);
- send_sig(SIGKILL, current, 0);
- return error;
+ /* Don't forget that Bill's 386bsd data-in-text kludge
+ * won't have any text.
+ */
+ if (ex.a_text) {
+ error = do_mmap(file, vm_offset, ex.a_text,
+ PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_SHARED | MAP_DENYWRITE | MAP_EXECUTABLE,
+ fd_offset);
+
+ if (error != vm_offset) {
+ sys_close(fd);
+ send_sig(SIGSEGV, current, 0);
+ return -EINVAL;
+ }
}
- error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data,
+ /* N.B. Linux makes data executable. BSD doesn't (unless
+ * using Bill's code-in-data kludge).
+ */
+ error = do_mmap(file, vm_offset + ex.a_text, ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
sys_close(fd);
- if (error != N_TXTADDR(ex) + ex.a_text) {
- send_sig(SIGKILL, current, 0);
- return error;
+ if (error != vm_offset + ex.a_text) {
+ send_sig(SIGSEGV, current, 0);
+ return -EINVAL;
}
}
-beyond_if:
+
+ set_brk(current->mm->start_brk, current->mm->brk);
+
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)--;
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)--;
+ current->personality = pers;
current->exec_domain = lookup_exec_domain(current->personality);
current->binfmt = &aout_format;
if (current->exec_domain && current->exec_domain->use_count)
@@ -890,8 +969,6 @@
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)++;
- set_brk(current->mm->start_brk, current->mm->brk);
-
p += change_ldt(ex.a_text,bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long)create_tables((char *)p,

View file

@ -1,241 +0,0 @@
===================================================================
RCS file: /var/CVS/linux/fs/exec.c,v
retrieving revision 1.1.1.1.14.15
diff -u -r1.1.1.1.14.15 exec.c
--- 1.1.1.1.14.15 1994/10/24 09:30:00
+++ exec.c 1994/11/01 10:51:22
@@ -38,6 +38,7 @@
#include <linux/user.h>
#include <linux/segment.h>
#include <linux/malloc.h>
+#include <linux/in.h> /* for ntohl() */
#include <asm/system.h>
@@ -785,29 +786,94 @@
struct file * file;
int fd, error;
unsigned long p = bprm->p;
- unsigned long fd_offset;
-
- ex = *((struct exec *) bprm->buf); /* exec-header */
- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
- N_MAGIC(ex) != QMAGIC) ||
- ex.a_trsize || ex.a_drsize ||
- bprm->inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
+ unsigned long fd_offset, vm_offset;
+ unsigned long pers;
+ unsigned long rlim;
+
+ ex = *((struct exec *) bprm->buf);
+
+ /* Basic sanity checks. There should be no relocation information
+ * and the size of the file must be greater than the total text
+ * plus data size.
+ */
+ if (ex.a_trsize || ex.a_drsize
+ || ex.a_text + ex.a_data > bprm->inode->i_size)
return -ENOEXEC;
- }
- current->personality = PER_LINUX;
- fd_offset = N_TXTOFF(ex);
- if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
- printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
- return -ENOEXEC;
- }
+ /* If the machine type is zero assume a BSD flavour, Linux uses
+ * M_386 (100) as the machine type except on very old binaries
+ * which can easily be updated using the lnxstamp program supplied
+ * as part of the iBCS/BSD emulator.
+ */
+ pers = (N_MACHTYPE(ex) == 100 ? PER_LINUX : PER_BSD);
+
+ /* Set up the file and vm offsets based on the type of
+ * executable.
+ */
+ switch (ex.a_info & 0xffff) {
+ case ZMAGIC: /* demand paged executable */
+ /* Alignment varies. If there is no symbol table
+ * we can work out the offset to the text start
+ * easily. If there is a symbol table we would
+ * have to walk it to find out the size of the
+ * string pool so in this case we guess at the
+ * "standard" Linux alignment. Alignment doesn't
+ * imply personality is known though...
+ */
+ if (ex.a_text == 0) {
+ /* Bill's 386bsd used a code-in-data kludge
+ * on the boot disk.
+ */
+ fd_offset = 0;
+ } else if (ex.a_syms == 0) {
+ fd_offset = (bprm->inode->i_size
+ - ex.a_text - ex.a_data)
+ & (~15);
+ } else {
+ fd_offset = N_TXTOFF(ex);
+ }
+ vm_offset = 0;
+ break;
- if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
- (fd_offset < bprm->inode->i_sb->s_blocksize)) {
- printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
- return -ENOEXEC;
+ case QMAGIC: /* demand paged with page 0 unmapped */
+ fd_offset = 0;
+ vm_offset = PAGE_SIZE;
+ break;
+
+ case OMAGIC: /* impure executable */
+ fd_offset = 32;
+ vm_offset = 0;
+ break;
+
+ default:
+ /* NetBSD puts the info field in network byte
+ * order instead of host order. Why? It also
+ * treats ZMAGIC and QMAGIC identically with
+ * regards leaving page 0 unmapped.
+ */
+ switch (ntohl(ex.a_info) & 0xffff) {
+ case ZMAGIC:
+ case QMAGIC:
+ pers = PER_BSD;
+ fd_offset = 0;
+ vm_offset = PAGE_SIZE;
+ break;
+
+ default:
+ return -ENOEXEC;
+ }
}
+ /* Check initial limits. This avoids letting people circumvent
+ * size limits imposed on them by creating programs with large
+ * arrays in the data or bss.
+ */
+ rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+ if (rlim >= RLIM_INFINITY)
+ rlim = ~0;
+ if (ex.a_data + ex.a_bss > rlim)
+ return -ENOMEM;
+
/* OK, This is the point of no return */
flush_old_exec(bprm);
@@ -815,63 +881,74 @@
(current->mm->start_brk =
(current->mm->end_data = ex.a_data +
(current->mm->end_code = ex.a_text +
- (current->mm->start_code = N_TXTADDR(ex)))));
+ (current->mm->start_code = vm_offset))));
current->mm->rss = 0;
current->mm->mmap = NULL;
- current->suid = current->euid = current->fsuid = bprm->e_uid;
- current->sgid = current->egid = current->fsgid = bprm->e_gid;
- if (N_MAGIC(ex) == OMAGIC) {
- do_mmap(NULL, 0, ex.a_text+ex.a_data,
+ current->suid = current->euid = current->fsuid = bprm->e_uid;
+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
+ /* If the file offset is not on a filesystem block boundary treat
+ * the file as impure and slurp the lot in. Theory says we should
+ * able to slurp in the odd bits at the start and end of text and
+ * data segments and mmap the blocks in between. This might be useful
+ * for the cases where filesystems with differing block sizes are
+ * in use or the programmer is just thick. It isn't implemented
+ * yet however.
+ * Also slurp the data if the filesystem doesn't support mmap.
+ */
+ fd = open_inode(bprm->inode, O_RDONLY);
+ if (fd < 0) {
+ /* Too late! We're doomed... */
+ send_sig(SIGSEGV, current, 0);
+ return fd;
+ }
+ file = current->files->fd[fd];
+ if (fd_offset % bprm->inode->i_sb->s_blocksize
+ || !file->f_op || !file->f_op->mmap) {
+ sys_close(fd);
+ do_mmap(NULL, vm_offset, ex.a_text+ex.a_data,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data);
+ read_exec(bprm->inode, fd_offset, (char *)vm_offset,
+ ex.a_text+ex.a_data);
} else {
- if (ex.a_text & 0xfff || ex.a_data & 0xfff)
- printk(KERN_NOTICE "executable not page aligned\n");
-
- fd = open_inode(bprm->inode, O_RDONLY);
-
- if (fd < 0)
- return fd;
- file = current->files->fd[fd];
- if (!file->f_op || !file->f_op->mmap) {
- sys_close(fd);
- do_mmap(NULL, 0, ex.a_text+ex.a_data,
- PROT_READ|PROT_WRITE|PROT_EXEC,
- MAP_FIXED|MAP_PRIVATE, 0);
- read_exec(bprm->inode, fd_offset,
- (char *) N_TXTADDR(ex), ex.a_text+ex.a_data);
- goto beyond_if;
- }
-
+ /* Don't forget that Bill's 386bsd data-in-text kludge
+ * won't have any text.
+ */
if (ex.a_text) {
- error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
+ error = do_mmap(file, vm_offset, ex.a_text,
PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_SHARED | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset);
-
- if (error != N_TXTADDR(ex)) {
+
+ if (error != vm_offset) {
sys_close(fd);
send_sig(SIGSEGV, current, 0);
return -EINVAL;
}
}
- error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data,
+ /* N.B. Linux makes data executable. BSD doesn't (unless
+ * using Bill's code-in-data kludge).
+ */
+ error = do_mmap(file, vm_offset + ex.a_text, ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
sys_close(fd);
- if (error != N_TXTADDR(ex) + ex.a_text) {
+ if (error != vm_offset + ex.a_text) {
send_sig(SIGSEGV, current, 0);
return -EINVAL;
}
}
-beyond_if:
+
+ set_brk(current->mm->start_brk, current->mm->brk);
+
if (current->exec_domain && current->exec_domain->use_count)
(*current->exec_domain->use_count)--;
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)--;
+ current->personality = pers;
current->exec_domain = lookup_exec_domain(current->personality);
current->binfmt = &aout_format;
if (current->exec_domain && current->exec_domain->use_count)
@@ -879,8 +956,6 @@
if (current->binfmt && current->binfmt->use_count)
(*current->binfmt->use_count)++;
- set_brk(current->mm->start_brk, current->mm->brk);
-
p += change_ldt(ex.a_text,bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long)create_tables((char *)p,

View file

@ -1,38 +0,0 @@
This patch is to Linux versions 1.2.x. It is expected to be introduced
to the 1.3.x tree if not before.
This allows the kernel to attempt to switch to SVR4 personality if
it receives an lcall7 system call from what it previously thought
was a Linux binary. This is needed to support statically linked
SVR4 ELF binaries which are not recognised at load time.
Note: you can avoid using this patch if you build the ELF program loader
into the iBCS2 emulator. Also, I believe that it would probably work
to fix the kernel to always assume PER_SVR4, since crt1.o for native
images performs a syscall to set the personality to PER_LINUX. -Eric
diff -ur --new-file -X linux.exclude linux.dist/kernel/exec_domain.c linux/kernel/exec_domain.c
--- linux.dist/kernel/exec_domain.c Tue Jan 24 09:42:13 1995
+++ linux/kernel/exec_domain.c Mon Mar 20 13:56:24 1995
@@ -28,6 +28,21 @@
static asmlinkage void no_lcall7(struct pt_regs * regs)
{
+ if (current->exec_domain && current->exec_domain->use_count)
+ (*current->exec_domain->use_count)--;
+
+ current->personality = PER_SVR4;
+ current->exec_domain = lookup_exec_domain(current->personality);
+
+ if (current->exec_domain && current->exec_domain->use_count)
+ (*current->exec_domain->use_count)++;
+
+ if (current->exec_domain && current->exec_domain->handler
+ && current->exec_domain->handler != no_lcall7) {
+ current->exec_domain->handler(regs);
+ return;
+ }
+
send_sig(SIGSEGV, current, 1);
}

View file

@ -1,12 +0,0 @@
diff -ur linux.dist/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- linux.dist/arch/i386/kernel/signal.c Thu Apr 27 11:55:29 1995
+++ linux/arch/i386/kernel/signal.c Wed Aug 2 17:02:52 1995
@@ -89,7 +89,7 @@
#define __CODE ((unsigned long)(frame+24))
#define CODE(x) ((unsigned long *) ((x)+__CODE))
frame = *fp;
- if (regs->ss != USER_DS)
+ if (regs->ss != USER_DS && sa->sa_restorer)
frame = (unsigned long *) sa->sa_restorer;
frame -= 32;
if (verify_area(VERIFY_WRITE,frame,32*4))