Removed patches. They are no longer needed.
This commit is contained in:
parent
99cd6c74da
commit
53dadf61de
|
@ -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.
|
||||
|
|
|
@ -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?)
|
|
@ -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,
|
|
@ -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,
|
|
@ -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,
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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))
|
Loading…
Reference in a new issue