aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@cc.helsinki.fi>1994-02-14 16:51:45 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:32 -0400
commit61119d8da02481d9744f37f62cabeec5aecac3ba (patch)
tree22bf3689b1b5559861c4c3bc5ca480c65937aa8e
parentd9cc76127bcc137e3214b9166c439e02d2060cda (diff)
downloadarchive-61119d8da02481d9744f37f62cabeec5aecac3ba.tar.gz
ALPHA-pl15d
-rw-r--r--Makefile2
-rw-r--r--drivers/FPU-emu/README32
-rw-r--r--drivers/FPU-emu/errors.c9
-rw-r--r--drivers/FPU-emu/fpu_emu.h6
-rw-r--r--drivers/FPU-emu/fpu_entry.c90
-rw-r--r--drivers/FPU-emu/fpu_proto.h43
-rw-r--r--drivers/FPU-emu/fpu_system.h5
-rw-r--r--drivers/FPU-emu/get_address.c195
-rw-r--r--drivers/FPU-emu/load_store.c46
-rw-r--r--drivers/FPU-emu/reg_ld_str.c151
-rw-r--r--drivers/FPU-emu/version.h2
-rw-r--r--drivers/net/Space.c8
-rw-r--r--fs/binfmt_coff.c76
-rw-r--r--fs/nfs/proc.c173
-rw-r--r--include/linux/in_systm.h32
-rw-r--r--include/linux/mm.h2
-rw-r--r--kernel/signal.c9
-rw-r--r--net/inet/route.c8
18 files changed, 621 insertions, 268 deletions
diff --git a/Makefile b/Makefile
index 5c71b86..a65d090 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 0.99
PATCHLEVEL = 15
-ALPHA = c
+ALPHA = d
all: Version zImage
diff --git a/drivers/FPU-emu/README b/drivers/FPU-emu/README
index 8493558..1ae3263 100644
--- a/drivers/FPU-emu/README
+++ b/drivers/FPU-emu/README
@@ -47,7 +47,7 @@ Please report bugs, etc to me at:
--Bill Metzenthen
- Jan 1994
+ Feb 1994
----------------------- Internals of wm-FPU-emu -----------------------
@@ -92,21 +92,12 @@ is confined to five files:
----------------------- Limitations of wm-FPU-emu -----------------------
There are a number of differences between the current wm-FPU-emu
-(version beta 1.5) and the 80486 FPU (apart from bugs). Some of the
+(version beta 1.10) and the 80486 FPU (apart from bugs). Some of the
more important differences are listed below:
-Segment overrides don't do anything yet.
-
-All internal computations are performed at 64 bit or higher precision
-and the results rounded etc as required by the PC bits of the FPU
-control word. Under the crt0 version for Linux current at June 1993,
-the FPU PC bits specify 64 bits precision.
-
-The precision flag (PE of the FPU status word) and the Roundup flag
-(C1 of the status word) are now implemented. Does anyone write code
-which uses these features? The Roundup flag does not have much meaning
-for the transcendental functions and its 80486 value with these
-functions is likely to differ from its emulator value.
+The Roundup flag does not have much meaning for the transcendental
+functions and its 80486 value with these functions is likely to differ
+from its emulator value.
In a few rare cases the Underflow flag obtained with the emulator will
be different from that obtained with an 80486. This occurs when the
@@ -140,6 +131,19 @@ result of any arithmetic operation. An 80486 can keep one of these
numbers in an FPU register with its identity as a PseudoDenormal, but
the emulator will not; they are always converted to a valid number.
+Self modifying code can cause the emulator to fail. An example of such
+code is:
+ movl %esp,[%ebx]
+ fld1
+The FPU instruction may be (usually will be) loaded into the pre-fetch
+queue of the cpu before the mov instruction is executed. If the
+destination of the 'movl' overlaps the FPU instruction then the bytes
+in the prefetch queue and memory will be inconsistent when the FPU
+instruction is executed. The emulator will be invoked but will not be
+able to find the instruction which caused the device-not-present
+exception. For this case, the emulator cannot emulate the behaviour of
+an 80486DX.
+
----------------------- Performance of wm-FPU-emu -----------------------
Speed.
diff --git a/drivers/FPU-emu/errors.c b/drivers/FPU-emu/errors.c
index 99de4fa..0454c51 100644
--- a/drivers/FPU-emu/errors.c
+++ b/drivers/FPU-emu/errors.c
@@ -85,13 +85,15 @@ void emu_printall()
RE_ENTRANT_CHECK_OFF;
/* No need to verify_area(), we have previously fetched these bytes. */
printk("At %p: ", (void *) address);
- while ( 1 )
+#define MAX_PRINTED_BYTES 20
+ for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
{
byte1 = get_fs_byte((unsigned char *) address);
if ( (byte1 & 0xf8) == 0xd8 ) break;
printk("[%02x]", byte1);
address++;
}
+ if ( i == MAX_PRINTED_BYTES ) printk("[more..]");
printk("%02x ", byte1);
FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
partial_status = status_word();
@@ -234,6 +236,7 @@ static struct {
0x126 in fpu_entry.c
0x127 in poly_2xm1.c
0x128 in fpu_entry.c
+ 0x130 in get_address.c
0x2nn in an *.S file:
0x201 in reg_u_add.S
0x202 in reg_u_div.S
@@ -310,11 +313,11 @@ void exception(int n)
#endif PRINT_MESSAGES
}
else
- printk("FP emulator: Unknown Exception: 0x%04x!\n", n);
+ printk("FPU emulator: Unknown Exception: 0x%04x!\n", n);
if ( n == EX_INTERNAL )
{
- printk("FP emulator: Internal error type 0x%04x\n", int_type);
+ printk("FPU emulator: Internal error type 0x%04x\n", int_type);
emu_printall();
}
#ifdef PRINT_MESSAGES
diff --git a/drivers/FPU-emu/fpu_emu.h b/drivers/FPU-emu/fpu_emu.h
index 7b1a7e8..49e02ed 100644
--- a/drivers/FPU-emu/fpu_emu.h
+++ b/drivers/FPU-emu/fpu_emu.h
@@ -94,7 +94,11 @@ extern char emulating;
typedef void (*FUNC)(void);
typedef struct fpu_reg FPU_REG;
-typedef struct { unsigned char address_size, segment; } overrides;
+typedef struct { unsigned char address_size, operand_size, segment; }
+ overrides;
+/* This structure is 32 bits: */
+typedef struct { overrides override;
+ unsigned char vm86; } fpu_addr_modes;
#define st(x) ( regs[((top+x) &7 )] )
diff --git a/drivers/FPU-emu/fpu_entry.c b/drivers/FPU-emu/fpu_entry.c
index 063f54f..944a9da 100644
--- a/drivers/FPU-emu/fpu_entry.c
+++ b/drivers/FPU-emu/fpu_entry.c
@@ -137,13 +137,14 @@ unsigned short FPU_data_selector;
char emulating=0;
#endif PARANOID
-static int valid_prefix(unsigned char *byte, overrides *override);
+static int valid_prefix(unsigned char *Byte, unsigned char **fpu_eip,
+ overrides *override);
asmlinkage void math_emulate(long arg)
{
unsigned char FPU_modrm, byte1;
- overrides override;
+ fpu_addr_modes addr_modes;
int unmasked;
#ifdef PARANOID
@@ -170,35 +171,40 @@ asmlinkage void math_emulate(long arg)
SETUP_DATA_AREA(arg);
- FPU_ORIG_EIP = FPU_EIP;
+ addr_modes.vm86 = (FPU_EFLAGS & 0x00020000) != 0;
- /* We cannot handle emulation in v86-mode */
- if (FPU_EFLAGS & 0x00020000)
- {
- math_abort(FPU_info,SIGILL);
- }
+ if ( addr_modes.vm86 )
+ FPU_EIP += FPU_CS << 4;
- /* user code space? */
- if (FPU_CS == KERNEL_CS)
- {
- printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP);
- panic("Math emulation needed in kernel");
- }
+ FPU_ORIG_EIP = FPU_EIP;
- /* We cannot handle multiple segments yet */
- if (FPU_CS != USER_CS || FPU_DS != USER_DS)
+ if ( !addr_modes.vm86 )
{
- math_abort(FPU_info,SIGILL);
+ /* user code space? */
+ if (FPU_CS == KERNEL_CS)
+ {
+ printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP);
+ panic("Math emulation needed in kernel");
+ }
+
+ /* We cannot handle multiple segments yet */
+ if (FPU_CS != USER_CS || FPU_DS != USER_DS)
+ {
+ math_abort(FPU_info,SIGILL);
+ }
}
FPU_lookahead = 1;
if (current->flags & PF_PTRACED)
- FPU_lookahead = 0;
+ FPU_lookahead = 0;
- if ( !valid_prefix(&byte1, &override) )
+ if ( !valid_prefix(&byte1, (unsigned char **)&FPU_EIP,
+ &addr_modes.override) )
{
RE_ENTRANT_CHECK_OFF;
- printk("FPU emulator: Unknown prefix byte 0x%02x\n", byte1);
+ printk("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
+ "FPU emulator: self-modifying code! (emulation impossible)\n",
+ byte1);
RE_ENTRANT_CHECK_ON;
EXCEPTION(EX_INTERNAL|0x126);
math_abort(FPU_info,SIGILL);
@@ -289,7 +295,11 @@ do_another_FPU_instruction:
if ( FPU_modrm < 0300 )
{
/* All of these instructions use the mod/rm byte to get a data address */
- get_address(FPU_modrm, override);
+ if ( addr_modes.vm86
+ ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX) )
+ get_address_16(FPU_modrm, &FPU_EIP, addr_modes);
+ else
+ get_address(FPU_modrm, &FPU_EIP, addr_modes);
if ( !(byte1 & 1) )
{
unsigned short status1 = partial_status;
@@ -303,16 +313,16 @@ do_another_FPU_instruction:
switch ( (byte1 >> 1) & 3 )
{
case 0:
- unmasked = reg_load_single(override);
+ unmasked = reg_load_single();
break;
case 1:
- reg_load_int32(override);
+ reg_load_int32();
break;
case 2:
- unmasked = reg_load_double(override);
+ unmasked = reg_load_double();
break;
case 3:
- reg_load_int16(override);
+ reg_load_int16();
break;
}
@@ -440,7 +450,8 @@ do_another_FPU_instruction:
}
else
{
- load_store_instr(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1, override);
+ load_store_instr(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1,
+ addr_modes);
}
reg_mem_instr_done:
@@ -527,10 +538,14 @@ FPU_fwait_done:
if (FPU_lookahead && !need_resched)
{
FPU_ORIG_EIP = FPU_EIP;
- if ( valid_prefix(&byte1, &override) )
+ if ( valid_prefix(&byte1, (unsigned char **)&FPU_EIP,
+ &addr_modes.override) )
goto do_another_FPU_instruction;
}
+ if ( addr_modes.vm86 )
+ FPU_EIP -= FPU_CS << 4;
+
RE_ENTRANT_CHECK_OFF;
}
@@ -539,16 +554,17 @@ FPU_fwait_done:
all prefix bytes, further changes are needed in the emulator code
which accesses user address space. Access to separate segments is
important for msdos emulation. */
-static int valid_prefix(unsigned char *Byte, overrides *override)
+static int valid_prefix(unsigned char *Byte, unsigned char **fpu_eip,
+ overrides *override)
{
unsigned char byte;
- unsigned long ip = FPU_EIP;
+ unsigned char *ip = *fpu_eip;
- *override = (overrides) { 0, PREFIX_DS }; /* defaults */
+ *override = (overrides) { 0, 0, PREFIX_DS }; /* defaults */
RE_ENTRANT_CHECK_OFF;
FPU_code_verify_area(1);
- byte = get_fs_byte((unsigned char *) FPU_EIP);
+ byte = get_fs_byte(ip);
RE_ENTRANT_CHECK_ON;
while ( 1 )
@@ -558,6 +574,11 @@ static int valid_prefix(unsigned char *Byte, overrides *override)
case ADDR_SIZE_PREFIX:
override->address_size = ADDR_SIZE_PREFIX;
goto do_next_byte;
+
+ case OP_SIZE_PREFIX:
+ override->operand_size = OP_SIZE_PREFIX;
+ goto do_next_byte;
+
case PREFIX_CS:
override->segment = PREFIX_CS;
goto do_next_byte;
@@ -585,12 +606,11 @@ static int valid_prefix(unsigned char *Byte, overrides *override)
case PREFIX_REPE:
case PREFIX_REPNE:
- case OP_SIZE_PREFIX: /* Used often by gcc, but has no effect. */
do_next_byte:
- FPU_EIP++;
+ ip++;
RE_ENTRANT_CHECK_OFF;
FPU_code_verify_area(1);
- byte = get_fs_byte((unsigned char *) (FPU_EIP));
+ byte = get_fs_byte(ip);
RE_ENTRANT_CHECK_ON;
break;
case FWAIT_OPCODE:
@@ -600,6 +620,7 @@ static int valid_prefix(unsigned char *Byte, overrides *override)
if ( (byte & 0xf8) == 0xd8 )
{
*Byte = byte;
+ *fpu_eip = ip;
return 1;
}
else
@@ -607,7 +628,6 @@ static int valid_prefix(unsigned char *Byte, overrides *override)
/* Not a valid sequence of prefix bytes followed by
an FPU instruction. */
*Byte = byte; /* Needed for error message. */
- FPU_EIP = ip;
return 0;
}
}
diff --git a/drivers/FPU-emu/fpu_proto.h b/drivers/FPU-emu/fpu_proto.h
index ca659a2..a55f2d9 100644
--- a/drivers/FPU-emu/fpu_proto.h
+++ b/drivers/FPU-emu/fpu_proto.h
@@ -63,10 +63,13 @@ extern void trig_a(void);
extern void trig_b(void);
/* get_address.c */
-extern void get_address(unsigned char FPU_modrm, overrides override);
+extern void get_address(unsigned char FPU_modrm, unsigned long *fpu_eip,
+ fpu_addr_modes);
+extern void get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip,
+ fpu_addr_modes);
/* load_store.c */
-extern void load_store_instr(char type, overrides override);
+extern void load_store_instr(char type, fpu_addr_modes addr_modes);
/* poly_2xm1.c */
extern int poly_2xm1(FPU_REG const *arg, FPU_REG *result);
@@ -105,26 +108,26 @@ extern void fucompp(void);
extern void fconst(void);
/* reg_ld_str.c */
-extern int reg_load_extended(overrides override);
-extern int reg_load_double(overrides override);
-extern int reg_load_single(overrides override);
-extern void reg_load_int64(overrides override);
-extern void reg_load_int32(overrides override);
-extern void reg_load_int16(overrides override);
-extern void reg_load_bcd(overrides override);
-extern int reg_store_extended(overrides override);
-extern int reg_store_double(overrides override);
-extern int reg_store_single(overrides override);
-extern int reg_store_int64(overrides override);
-extern int reg_store_int32(overrides override);
-extern int reg_store_int16(overrides override);
-extern int reg_store_bcd(overrides override);
+extern int reg_load_extended(void);
+extern int reg_load_double(void);
+extern int reg_load_single(void);
+extern void reg_load_int64(void);
+extern void reg_load_int32(void);
+extern void reg_load_int16(void);
+extern void reg_load_bcd(void);
+extern int reg_store_extended(void);
+extern int reg_store_double(void);
+extern int reg_store_single(void);
+extern int reg_store_int64(void);
+extern int reg_store_int32(void);
+extern int reg_store_int16(void);
+extern int reg_store_bcd(void);
extern int round_to_int(FPU_REG *r);
-extern char *fldenv(void);
-extern void frstor(void);
+extern char *fldenv(fpu_addr_modes addr_modes);
+extern void frstor(fpu_addr_modes addr_modes);
extern unsigned short tag_word(void);
-extern char *fstenv(void);
-extern void fsave(void);
+extern char *fstenv(fpu_addr_modes addr_modes);
+extern void fsave(fpu_addr_modes addr_modes);
/* reg_mul.c */
extern int reg_mul(FPU_REG const *a, FPU_REG const *b,
diff --git a/drivers/FPU-emu/fpu_system.h b/drivers/FPU-emu/fpu_system.h
index 52ae0f7..a8e7af3 100644
--- a/drivers/FPU-emu/fpu_system.h
+++ b/drivers/FPU-emu/fpu_system.h
@@ -23,7 +23,12 @@
#define FPU_info (I387.soft.info)
#define FPU_CS (*(unsigned short *) &(FPU_info->___cs))
+#define FPU_SS (*(unsigned short *) &(FPU_info->___ss))
#define FPU_DS (*(unsigned short *) &(FPU_info->___ds))
+#define FPU_VM86_ES ((&FPU_SS)[2])
+#define FPU_VM86_DS ((&FPU_SS)[4])
+#define FPU_VM86_FS ((&FPU_SS)[6])
+#define FPU_VM86_GS ((&FPU_SS)[8])
#define FPU_EAX (FPU_info->___eax)
#define FPU_EFLAGS (FPU_info->___eflags)
#define FPU_EIP (FPU_info->___eip)
diff --git a/drivers/FPU-emu/get_address.c b/drivers/FPU-emu/get_address.c
index f2b00b5..224cb60 100644
--- a/drivers/FPU-emu/get_address.c
+++ b/drivers/FPU-emu/get_address.c
@@ -41,16 +41,16 @@ static int reg_offset[] = {
/* Decode the SIB byte. This function assumes mod != 0 */
-static void *sib(int mod)
+static void *sib(int mod, unsigned long *fpu_eip)
{
unsigned char ss,index,base;
long offset;
RE_ENTRANT_CHECK_OFF;
FPU_code_verify_area(1);
- base = get_fs_byte((char *) FPU_EIP); /* The SIB byte */
+ base = get_fs_byte((char *) (*fpu_eip)); /* The SIB byte */
RE_ENTRANT_CHECK_ON;
- FPU_EIP++;
+ (*fpu_eip)++;
ss = base >> 6;
index = (base >> 3) & 7;
base &= 7;
@@ -77,23 +77,51 @@ static void *sib(int mod)
/* 8 bit signed displacement */
RE_ENTRANT_CHECK_OFF;
FPU_code_verify_area(1);
- offset += (signed char) get_fs_byte((char *) FPU_EIP);
+ offset += (signed char) get_fs_byte((char *) (*fpu_eip));
RE_ENTRANT_CHECK_ON;
- FPU_EIP++;
+ (*fpu_eip)++;
}
else if (mod == 2 || base == 5) /* The second condition also has mod==0 */
{
/* 32 bit displacment */
RE_ENTRANT_CHECK_OFF;
FPU_code_verify_area(4);
- offset += (signed) get_fs_long((unsigned long *) FPU_EIP);
+ offset += (signed) get_fs_long((unsigned long *) (*fpu_eip));
RE_ENTRANT_CHECK_ON;
- FPU_EIP += 4;
+ (*fpu_eip) += 4;
}
return (void *) offset;
}
+static unsigned long vm86_segment(char segment)
+{
+ switch ( segment )
+ {
+ case PREFIX_CS:
+ return FPU_CS << 4;
+ break;
+ case PREFIX_SS:
+ return FPU_SS << 4;
+ break;
+ case PREFIX_ES:
+ return FPU_VM86_ES << 4;
+ break;
+ case PREFIX_DS:
+ return FPU_VM86_DS << 4;
+ break;
+ case PREFIX_FS:
+ return FPU_VM86_FS << 4;
+ break;
+ case PREFIX_GS:
+ return FPU_VM86_GS << 4;
+ break;
+ default:
+ EXCEPTION(EX_INTERNAL|0x130);
+ return 0; /* Keep gcc quiet. */
+ }
+}
+
/*
MOD R/M byte: MOD == 3 has a special use for the FPU
@@ -112,7 +140,8 @@ static void *sib(int mod)
*/
-void get_address(unsigned char FPU_modrm, overrides override)
+void get_address(unsigned char FPU_modrm, unsigned long *fpu_eip,
+ fpu_addr_modes addr_modes)
{
unsigned char mod;
long *cpu_reg_ptr;
@@ -123,11 +152,20 @@ void get_address(unsigned char FPU_modrm, overrides override)
FPU_data_selector = FPU_DS;
#endif PECULIAR_486
+ /* Memory accessed via the cs selector is write protected
+ in 32 bit protected mode. */
+#define FPU_WRITE_BIT 0x10
+ if ( !addr_modes.vm86 && (FPU_modrm & FPU_WRITE_BIT)
+ && (addr_modes.override.segment == PREFIX_CS) )
+ {
+ math_abort(FPU_info,SIGSEGV);
+ }
+
mod = (FPU_modrm >> 6) & 3;
if (FPU_rm == 4 && mod != 3)
{
- FPU_data_address = sib(mod);
+ FPU_data_address = sib(mod, fpu_eip);
return;
}
@@ -137,20 +175,11 @@ void get_address(unsigned char FPU_modrm, overrides override)
case 0:
if (FPU_rm == 5)
{
- /* Special case: disp16 or disp32 */
+ /* Special case: disp32 */
RE_ENTRANT_CHECK_OFF;
- if ( override.address_size == ADDR_SIZE_PREFIX )
- {
- FPU_code_verify_area(2);
- offset = get_fs_word((unsigned short *) FPU_EIP);
- FPU_EIP += 2;
- }
- else
- {
- FPU_code_verify_area(4);
- offset = get_fs_long((unsigned long *) FPU_EIP);
- FPU_EIP += 4;
- }
+ FPU_code_verify_area(4);
+ offset = get_fs_long((unsigned long *) (*fpu_eip));
+ (*fpu_eip) += 4;
RE_ENTRANT_CHECK_ON;
FPU_data_address = (void *) offset;
return;
@@ -165,33 +194,125 @@ void get_address(unsigned char FPU_modrm, overrides override)
/* 8 bit signed displacement */
RE_ENTRANT_CHECK_OFF;
FPU_code_verify_area(1);
- offset = (signed char) get_fs_byte((char *) FPU_EIP);
+ offset = (signed char) get_fs_byte((char *) (*fpu_eip));
RE_ENTRANT_CHECK_ON;
- FPU_EIP++;
+ (*fpu_eip)++;
break;
case 2:
- /* 16 or 32 bit displacement */
+ /* 32 bit displacement */
RE_ENTRANT_CHECK_OFF;
- if ( override.address_size == ADDR_SIZE_PREFIX )
+ FPU_code_verify_area(4);
+ offset = (signed) get_fs_long((unsigned long *) (*fpu_eip));
+ (*fpu_eip) += 4;
+ RE_ENTRANT_CHECK_ON;
+ break;
+ case 3:
+ /* Not legal for the FPU */
+ EXCEPTION(EX_Invalid);
+ }
+
+ if ( addr_modes.vm86 )
+ {
+ offset += vm86_segment(addr_modes.override.segment);
+ }
+
+ FPU_data_address = offset + (char *)*cpu_reg_ptr;
+}
+
+
+void get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip,
+ fpu_addr_modes addr_modes)
+{
+ unsigned char mod;
+ int offset = 0; /* Default used for mod == 0 */
+
+#ifndef PECULIAR_486
+ /* This is a reasonable place to do this */
+ FPU_data_selector = FPU_DS;
+#endif PECULIAR_486
+
+ /* Memory accessed via the cs selector is write protected
+ in 32 bit protected mode. */
+#define FPU_WRITE_BIT 0x10
+ if ( !addr_modes.vm86 && (FPU_modrm & FPU_WRITE_BIT)
+ && (addr_modes.override.segment == PREFIX_CS) )
+ {
+ math_abort(FPU_info,SIGSEGV);
+ }
+
+ mod = (FPU_modrm >> 6) & 3;
+
+ switch (mod)
+ {
+ case 0:
+ if (FPU_rm == 6)
{
+ /* Special case: disp16 */
+ RE_ENTRANT_CHECK_OFF;
FPU_code_verify_area(2);
- offset = (signed) get_fs_word((unsigned short *) FPU_EIP);
- FPU_EIP += 2;
- }
- else
- {
- FPU_code_verify_area(4);
- offset = (signed) get_fs_long((unsigned long *) FPU_EIP);
- FPU_EIP += 4;
+ offset = (unsigned short)get_fs_word((unsigned short *) (*fpu_eip));
+ (*fpu_eip) += 2;
+ RE_ENTRANT_CHECK_ON;
+ goto add_segment;
}
+ break;
+ case 1:
+ /* 8 bit signed displacement */
+ RE_ENTRANT_CHECK_OFF;
+ FPU_code_verify_area(1);
+ offset = (signed char) get_fs_byte((signed char *) (*fpu_eip));
+ RE_ENTRANT_CHECK_ON;
+ (*fpu_eip)++;
+ break;
+ case 2:
+ /* 16 bit displacement */
+ RE_ENTRANT_CHECK_OFF;
+ FPU_code_verify_area(2);
+ offset = (unsigned) get_fs_word((unsigned short *) (*fpu_eip));
+ (*fpu_eip) += 2;
RE_ENTRANT_CHECK_ON;
break;
case 3:
/* Not legal for the FPU */
EXCEPTION(EX_Invalid);
+ break;
+ }
+ switch ( FPU_rm )
+ {
+ case 0:
+ offset += FPU_info->___ebx + FPU_info->___esi;
+ break;
+ case 1:
+ offset += FPU_info->___ebx + FPU_info->___edi;
+ break;
+ case 2:
+ offset += FPU_info->___ebp + FPU_info->___esi;
+ break;
+ case 3:
+ offset += FPU_info->___ebp + FPU_info->___edi;
+ break;
+ case 4:
+ offset += FPU_info->___esi;
+ break;
+ case 5:
+ offset += FPU_info->___edi;
+ break;
+ case 6:
+ offset += FPU_info->___ebp;
+ break;
+ case 7:
+ offset += FPU_info->___ebx;
+ break;
}
- FPU_data_address = offset + (char *)*cpu_reg_ptr;
- if ( override.address_size == ADDR_SIZE_PREFIX )
- FPU_data_address = (void *)((long)FPU_data_address & 0xffff);
+ add_segment:
+ offset &= 0xffff;
+
+ if ( addr_modes.vm86 )
+ {
+ offset += vm86_segment(addr_modes.override.segment);
+ }
+
+ FPU_data_address = (void *)offset ;
}
+
diff --git a/drivers/FPU-emu/load_store.c b/drivers/FPU-emu/load_store.c
index 5b5737b..d1c1f75 100644
--- a/drivers/FPU-emu/load_store.c
+++ b/drivers/FPU-emu/load_store.c
@@ -46,7 +46,7 @@ static unsigned char const type_table[32] = {
_NONE_, _REG0_, _NONE_, _REG0_
};
-void load_store_instr(char type, overrides override)
+void load_store_instr(char type, fpu_addr_modes addr_modes)
{
FPU_REG *pop_ptr; /* We need a version of FPU_st0_ptr which won't
change if the emulator is re-entered. */
@@ -85,7 +85,7 @@ switch ( type )
{
case 000: /* fld m32real */
clear_C1();
- reg_load_single(override);
+ reg_load_single();
if ( (FPU_loaded_data.tag == TW_NaN) &&
real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
{
@@ -96,12 +96,12 @@ switch ( type )
break;
case 001: /* fild m32int */
clear_C1();
- reg_load_int32(override);
+ reg_load_int32();
reg_move(&FPU_loaded_data, pop_ptr);
break;
case 002: /* fld m64real */
clear_C1();
- reg_load_double(override);
+ reg_load_double();
if ( (FPU_loaded_data.tag == TW_NaN) &&
real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
{
@@ -112,58 +112,58 @@ switch ( type )
break;
case 003: /* fild m16int */
clear_C1();
- reg_load_int16(override);
+ reg_load_int16();
reg_move(&FPU_loaded_data, pop_ptr);
break;
case 010: /* fst m32real */
clear_C1();
- reg_store_single(override);
+ reg_store_single();
break;
case 011: /* fist m32int */
clear_C1();
- reg_store_int32(override);
+ reg_store_int32();
break;
case 012: /* fst m64real */
clear_C1();
- reg_store_double(override);
+ reg_store_double();
break;
case 013: /* fist m16int */
clear_C1();
- reg_store_int16(override);
+ reg_store_int16();
break;
case 014: /* fstp m32real */
clear_C1();
- if ( reg_store_single(override) )
+ if ( reg_store_single() )
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 015: /* fistp m32int */
clear_C1();
- if ( reg_store_int32(override) )
+ if ( reg_store_int32() )
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 016: /* fstp m64real */
clear_C1();
- if ( reg_store_double(override) )
+ if ( reg_store_double() )
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 017: /* fistp m16int */
clear_C1();
- if ( reg_store_int16(override) )
+ if ( reg_store_int16() )
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 020: /* fldenv m14/28byte */
- fldenv();
+ fldenv(addr_modes);
break;
case 022: /* frstor m94/108byte */
- frstor();
+ frstor(addr_modes);
break;
case 023: /* fbld m80dec */
clear_C1();
- reg_load_bcd(override);
+ reg_load_bcd();
reg_move(&FPU_loaded_data, pop_ptr);
break;
case 024: /* fldcw */
@@ -183,25 +183,25 @@ switch ( type )
break;
case 025: /* fld m80real */
clear_C1();
- reg_load_extended(override);
+ reg_load_extended();
reg_move(&FPU_loaded_data, pop_ptr);
break;
case 027: /* fild m64int */
clear_C1();
- reg_load_int64(override);
+ reg_load_int64();
reg_move(&FPU_loaded_data, pop_ptr);
break;
case 030: /* fstenv m14/28byte */
- fstenv();
+ fstenv(addr_modes);
NO_NET_DATA_EFFECT;
break;
case 032: /* fsave */
- fsave();
+ fsave(addr_modes);
NO_NET_DATA_EFFECT;
break;
case 033: /* fbstp m80dec */
clear_C1();
- if ( reg_store_bcd(override) )
+ if ( reg_store_bcd() )
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
@@ -215,7 +215,7 @@ switch ( type )
break;
case 035: /* fstp m80real */
clear_C1();
- if ( reg_store_extended(override) )
+ if ( reg_store_extended() )
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
@@ -229,7 +229,7 @@ switch ( type )
break;
case 037: /* fistp m64int */
clear_C1();
- if ( reg_store_int64(override) )
+ if ( reg_store_int64() )
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
diff --git a/drivers/FPU-emu/reg_ld_str.c b/drivers/FPU-emu/reg_ld_str.c
index e8a55be..a768b4c 100644
--- a/drivers/FPU-emu/reg_ld_str.c
+++ b/drivers/FPU-emu/reg_ld_str.c
@@ -44,7 +44,7 @@ FPU_REG FPU_loaded_data;
/* Get a long double from user memory */
-int reg_load_extended(overrides override)
+int reg_load_extended(void)
{
long double *s = (long double *)FPU_data_address;
unsigned long sigl, sigh, exp;
@@ -145,7 +145,7 @@ int reg_load_extended(overrides override)
/* Get a double from user memory */
-int reg_load_double(overrides override)
+int reg_load_double(void)
{
double *dfloat = (double *)FPU_data_address;
int exp;
@@ -223,7 +223,7 @@ int reg_load_double(overrides override)
/* Get a float from user memory */
-int reg_load_single(overrides override)
+int reg_load_single(void)
{
float *single = (float *)FPU_data_address;
unsigned m32;
@@ -292,7 +292,7 @@ int reg_load_single(overrides override)
/* Get a long long from user memory */
-void reg_load_int64(overrides override)
+void reg_load_int64(void)
{
long long *_s = (long long *)FPU_data_address;
int e;
@@ -324,7 +324,7 @@ void reg_load_int64(overrides override)
/* Get a long from user memory */
-void reg_load_int32(overrides override)
+void reg_load_int32(void)
{
long *_s = (long *)FPU_data_address;
long s;
@@ -356,7 +356,7 @@ void reg_load_int32(overrides override)
/* Get a short from user memory */
-void reg_load_int16(overrides override)
+void reg_load_int16(void)
{
short *_s = (short *)FPU_data_address;
int s, e;
@@ -389,7 +389,7 @@ void reg_load_int16(overrides override)
/* Get a packed bcd array from user memory */
-void reg_load_bcd(overrides override)
+void reg_load_bcd(void)
{
char *s = (char *)FPU_data_address;
int pos;
@@ -436,7 +436,7 @@ void reg_load_bcd(overrides override)
/*===========================================================================*/
/* Put a long double into user memory */
-int reg_store_extended(overrides override)
+int reg_store_extended(void)
{
/*
The only exception raised by an attempt to store to an
@@ -475,7 +475,7 @@ int reg_store_extended(overrides override)
/* Put a double into user memory */
-int reg_store_double(overrides override)
+int reg_store_double(void)
{
double *dfloat = (double *)FPU_data_address;
unsigned long l[2];
@@ -670,7 +670,7 @@ int reg_store_double(overrides override)
/* Put a float into user memory */
-int reg_store_single(overrides override)
+int reg_store_single(void)
{
float *single = (float *)FPU_data_address;
long templ;
@@ -859,7 +859,7 @@ int reg_store_single(overrides override)
/* Put a long long into user memory */
-int reg_store_int64(overrides override)
+int reg_store_int64(void)
{
long long *d = (long long *)FPU_data_address;
FPU_REG t;
@@ -918,7 +918,7 @@ int reg_store_int64(overrides override)
/* Put a long into user memory */
-int reg_store_int32(overrides override)
+int reg_store_int32(void)
{
long *d = (long *)FPU_data_address;
FPU_REG t;
@@ -972,7 +972,7 @@ int reg_store_int32(overrides override)
/* Put a short into user memory */
-int reg_store_int16(overrides override)
+int reg_store_int16(void)
{
short *d = (short *)FPU_data_address;
FPU_REG t;
@@ -1026,7 +1026,7 @@ int reg_store_int16(overrides override)
/* Put a packed bcd array into user memory */
-int reg_store_bcd(overrides override)
+int reg_store_bcd(void)
{
char *d = (char *)FPU_data_address;
FPU_REG t;
@@ -1163,23 +1163,47 @@ int round_to_int(FPU_REG *r)
/*===========================================================================*/
-char *fldenv(void)
+char *fldenv(fpu_addr_modes addr_modes)
{
char *s = (char *)FPU_data_address;
unsigned short tag_word = 0;
unsigned char tag;
int i;
- RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, s, 0x1c);
- control_word = get_fs_word((unsigned short *) s);
- partial_status = get_fs_word((unsigned short *) (s+4));
- tag_word = get_fs_word((unsigned short *) (s+8));
- ip_offset = get_fs_long((unsigned long *) (s+0x0c));
- cs_selector = get_fs_long((unsigned long *) (s+0x10));
- data_operand_offset = get_fs_long((unsigned long *) (s+0x14));
- operand_selector = get_fs_long((unsigned long *) (s+0x18));
- RE_ENTRANT_CHECK_ON;
+ if ( addr_modes.vm86
+ || (addr_modes.override.operand_size == OP_SIZE_PREFIX) )
+ {
+ RE_ENTRANT_CHECK_OFF;
+ FPU_verify_area(VERIFY_READ, s, 0x0e);
+ control_word = get_fs_word((unsigned short *) s);
+ partial_status = get_fs_word((unsigned short *) (s+2));
+ tag_word = get_fs_word((unsigned short *) (s+4));
+ ip_offset = get_fs_word((unsigned short *) (s+6));
+ cs_selector = get_fs_word((unsigned short *) (s+8));
+ data_operand_offset = get_fs_word((unsigned short *) (s+0x0a));
+ operand_selector = get_fs_word((unsigned short *) (s+0x0c));
+ RE_ENTRANT_CHECK_ON;
+ s += 0x0e;
+ if ( addr_modes.vm86 )
+ {
+ ip_offset += (cs_selector & 0xf000) << 4;
+ data_operand_offset += (operand_selector & 0xf000) << 4;
+ }
+ }
+ else
+ {
+ RE_ENTRANT_CHECK_OFF;
+ FPU_verify_area(VERIFY_READ, s, 0x1c);
+ control_word = get_fs_word((unsigned short *) s);
+ partial_status = get_fs_word((unsigned short *) (s+4));
+ tag_word = get_fs_word((unsigned short *) (s+8));
+ ip_offset = get_fs_long((unsigned long *) (s+0x0c));
+ cs_selector = get_fs_long((unsigned long *) (s+0x10));
+ data_operand_offset = get_fs_long((unsigned long *) (s+0x14));
+ operand_selector = get_fs_long((unsigned long *) (s+0x18));
+ RE_ENTRANT_CHECK_ON;
+ s += 0x1c;
+ }
top = (partial_status >> SW_Top_Shift) & 7;
@@ -1226,21 +1250,21 @@ char *fldenv(void)
NO_NET_DATA_EFFECT;
NO_NET_INSTR_EFFECT;
- return s + 0x1c;
+ return s;
}
-void frstor(void)
+void frstor(fpu_addr_modes addr_modes)
{
int i, stnr;
unsigned char tag;
- char *s = fldenv();
+ char *s = fldenv(addr_modes);
for ( i = 0; i < 8; i++ )
{
/* Load each register. */
FPU_data_address = (void *)(s+i*10);
- reg_load_extended((overrides){0,0});
+ reg_load_extended();
stnr = (i+top) & 7;
tag = regs[stnr].tag; /* Derived from the loaded tag word. */
reg_move(&FPU_loaded_data, &regs[stnr]);
@@ -1285,46 +1309,75 @@ unsigned short tag_word(void)
}
-char *fstenv(void)
+char *fstenv(fpu_addr_modes addr_modes)
{
char *d = (char *)FPU_data_address;
- RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,d,28);
+ if ( addr_modes.vm86
+ || (addr_modes.override.operand_size == OP_SIZE_PREFIX) )
+ {
+ RE_ENTRANT_CHECK_OFF;
+ FPU_verify_area(VERIFY_WRITE,d,14);
+ put_fs_word(control_word, (unsigned short *) d);
+ put_fs_word(status_word(), (unsigned short *) (d+2));
+ put_fs_word(tag_word(), (unsigned short *) (d+4));
+ put_fs_word(ip_offset, (unsigned short *) (d+6));
+ put_fs_word(data_operand_offset, (unsigned short *) (d+0x0a));
+ if ( addr_modes.vm86 )
+ {
+ put_fs_word((ip_offset & 0xf0000) >> 4,
+ (unsigned short *) (d+8));
+ put_fs_word((data_operand_offset & 0xf0000) >> 4,
+ (unsigned short *) (d+0x0c));
+ }
+ else
+ {
+ put_fs_word(cs_selector, (unsigned short *) (d+8));
+ put_fs_word(operand_selector, (unsigned short *) (d+0x0c));
+ }
+ RE_ENTRANT_CHECK_ON;
+ d += 0x0e;
+ }
+ else
+ {
+ RE_ENTRANT_CHECK_OFF;
+ FPU_verify_area(VERIFY_WRITE,d,28);
#ifdef PECULIAR_486
- /* An 80486 sets all the reserved bits to 1. */
- put_fs_long(0xffff0040 | (control_word & ~0xe080), (unsigned long *) d);
- put_fs_long(0xffff0000 | status_word(), (unsigned long *) (d+4));
- put_fs_long(0xffff0000 | tag_word(), (unsigned long *) (d+8));
+ /* An 80486 sets all the reserved bits to 1. */
+ put_fs_long(0xffff0040 | (control_word & ~0xe080), (unsigned long *) d);
+ put_fs_long(0xffff0000 | status_word(), (unsigned long *) (d+4));
+ put_fs_long(0xffff0000 | tag_word(), (unsigned long *) (d+8));
#else
- put_fs_word(control_word, (unsigned short *) d);
- put_fs_word(status_word(), (unsigned short *) (d+4));
- put_fs_word(tag_word(), (unsigned short *) (d+8));
+ put_fs_word(control_word, (unsigned short *) d);
+ put_fs_word(status_word(), (unsigned short *) (d+4));
+ put_fs_word(tag_word(), (unsigned short *) (d+8));
#endif PECULIAR_486
- put_fs_long(ip_offset, (unsigned long *) (d+0x0c));
- put_fs_long(cs_selector & ~0xf8000000, (unsigned long *) (d+0x10));
- put_fs_long(data_operand_offset, (unsigned long *) (d+0x14));
+ put_fs_long(ip_offset, (unsigned long *) (d+0x0c));
+ put_fs_long(cs_selector & ~0xf8000000, (unsigned long *) (d+0x10));
+ put_fs_long(data_operand_offset, (unsigned long *) (d+0x14));
#ifdef PECULIAR_486
- /* An 80486 sets all the reserved bits to 1. */
- put_fs_long(0xffff0000 | operand_selector, (unsigned long *) (d+0x18));
+ /* An 80486 sets all the reserved bits to 1. */
+ put_fs_long(0xffff0000 | operand_selector, (unsigned long *) (d+0x18));
#else
- put_fs_long(operand_selector, (unsigned long *) (d+0x18));
+ put_fs_long(operand_selector, (unsigned long *) (d+0x18));
#endif PECULIAR_486
- RE_ENTRANT_CHECK_ON;
+ RE_ENTRANT_CHECK_ON;
+ d += 0x1c;
+ }
control_word |= CW_Exceptions;
partial_status &= ~(SW_Summary | SW_Backward);
- return d + 0x1c;
+ return d;
}
-void fsave(void)
+void fsave(fpu_addr_modes addr_modes)
{
char *d;
int i;
- d = fstenv();
+ d = fstenv(addr_modes);
RE_ENTRANT_CHECK_OFF;
FPU_verify_area(VERIFY_WRITE,d,80);
RE_ENTRANT_CHECK_ON;
diff --git a/drivers/FPU-emu/version.h b/drivers/FPU-emu/version.h
index d2c264d..94045f0 100644
--- a/drivers/FPU-emu/version.h
+++ b/drivers/FPU-emu/version.h
@@ -9,5 +9,5 @@
| |
+---------------------------------------------------------------------------*/
-#define FPU_VERSION "wm-FPU-emu version Beta 1.9"
+#define FPU_VERSION "wm-FPU-emu version Beta 1.10"
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 6cc4cf6..fc70286 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -139,14 +139,10 @@ static struct device atp_dev = {
#endif
/* The first device defaults to I/O base '0', which means autoprobe. */
-#ifdef EI8390
-# define ETH0_ADDR EI8390
-#else
+#ifndef ETH0_ADDR
# define ETH0_ADDR 0
#endif
-#ifdef EI8390_IRQ
-# define ETH0_IRQ EI8390_IRQ
-#else
+#ifndef ETH0_IRQ
# define ETH0_IRQ 0
#endif
/* "eth0" defaults to autoprobe, other use a base of "-0x20", "don't probe".
diff --git a/fs/binfmt_coff.c b/fs/binfmt_coff.c
index bf57016..b65f470 100644
--- a/fs/binfmt_coff.c
+++ b/fs/binfmt_coff.c
@@ -7,43 +7,12 @@
* This file is based upon code written by Eric Youndale for the ELF object
* file format.
*
- * Revision information:
- * 28 August 1993
- * Al Longyear (longyear@sii.com)
- * initial release to alpha level testing. This version does not load
- * shared libraries, but will identify them and log the file names.
+ * Author: Al Longyear (longyear@sii.com)
*
- * 4 September 1993
- * Al Longyear (longyear@sii.com)
- * Added support for shared libraries.
- *
- * 9 September 1993
- * Al Longyear (longyear@sii.com)
- * Load the FS register with the proper value prior to the call to
- * sys_uselib().
- *
- * Built the parameter and envionment strings before destroying the
- * current executable.
- *
- * 10 September 1993
- * Al Longyear (longyear@sii.com)
- * Added new parameter to the create_tables() function to allow the
- * proper creation of the IBCS environment stack when the process is
- * started.
- *
- * Added code to create_tables() which I mistakenly deleted in the
- * last patch.
- *
- * 13 September 1993
- * Al Longyear (longyear@sii.com)
- * Removed erroneous code which mistakenly folded .data with .bss for
- * a shared library.
- *
- * 8 Janurary 1994
- * Al Longyear (longyear@sii.com)
- * Corrected problem with read of library section returning the byte
- * count rather than zero. This was a change between the pl12 and
- * pl14 kernels which slipped by me.
+ * Latest Revision:
+ * 3 Feburary 1994
+ * Al Longyear (longyear@sii.com)
+ * Cleared first page of bss section using put_fs_byte.
*/
#include <linux/fs.h>
@@ -105,6 +74,37 @@ is_properly_aligned (COFF_SCNHDR *sect)
}
/*
+ * Clear the bytes in the last page of data.
+ */
+
+static
+int clear_memory (unsigned long addr, unsigned long size)
+{
+ int status;
+
+ size = (PAGE_SIZE - (addr & ~PAGE_MASK)) & ~PAGE_MASK;
+ if (size == 0)
+ status = 0;
+ else {
+
+#ifdef COFF_DEBUG
+ printk ("un-initialized storage in last page %d\n", size);
+#endif
+
+ status = verify_area (VERIFY_WRITE,
+ (void *) addr, size);
+#ifdef COFF_DEBUG
+ printk ("result from verify_area = %d\n", status);
+#endif
+
+ if (status >= 0)
+ while (size-- != 0)
+ put_fs_byte (0, addr++);
+ }
+ return status;
+}
+
+/*
* Helper function to process the load operation.
*/
@@ -521,11 +521,13 @@ load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
zeromap_page_range (PAGE_ALIGN (bss_vaddr),
PAGE_ALIGN (bss_size),
PAGE_COPY);
+
+ status = clear_memory (bss_vaddr, bss_size);
}
/*
* Load any shared library for the executable.
*/
- if (lib_ok && lib_count != 0) {
+ if (status >= 0 && lib_ok && lib_count != 0) {
int nIndex;
COFF_SCNHDR *sect_ptr = sect_bufr;
/*
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 59cb050..82f46f4 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -1,7 +1,7 @@
/*
* linux/fs/nfs/proc.c
*
- * Copyright (C) 1992 Rick Sladkey
+ * Copyright (C) 1992, 1993, 1994 Rick Sladkey
*
* OS-independent nfs remote procedure call functions
*/
@@ -41,7 +41,7 @@ static int proc_debug = 0;
#endif /* !NFS_PROC_DEBUG */
-static int *nfs_rpc_header(int *p, int procedure);
+static int *nfs_rpc_header(int *p, int procedure, int ruid);
static int *nfs_rpc_verify(int *p);
static int nfs_stat_to_errno(int stat);
@@ -192,11 +192,13 @@ int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call getattr\n");
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_GETATTR);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_GETATTR, ruid);
p = xdr_encode_fhandle(p, fhandle);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
@@ -208,8 +210,13 @@ int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
p = xdr_decode_fattr(p, fattr);
PRINTK("NFS reply getattr\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply getattr failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -219,11 +226,13 @@ int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call setattr\n");
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_SETATTR);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid);
p = xdr_encode_fhandle(p, fhandle);
p = xdr_encode_sattr(p, sattr);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
@@ -236,8 +245,13 @@ int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
p = xdr_decode_fattr(p, fattr);
PRINTK("NFS reply setattr\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply setattr failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -247,6 +261,7 @@ int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *n
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call lookup %s\n", name);
#ifdef NFS_PROC_DEBUG
@@ -255,7 +270,8 @@ int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *n
#endif
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_LOOKUP);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
@@ -269,8 +285,13 @@ int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *n
p = xdr_decode_fattr(p, fattr);
PRINTK("NFS reply lookup\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply lookup failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -280,11 +301,13 @@ int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call readlink\n");
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_READLINK);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_READLINK, ruid);
p = xdr_encode_fhandle(p, fhandle);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
@@ -300,8 +323,13 @@ int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
else
PRINTK("NFS reply readlink %s\n", res);
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply readlink failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -311,12 +339,14 @@ int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
{
int *p, *p0;
int status;
+ int ruid = 0;
int len = 0; /* = 0 is for gcc */
PRINTK("NFS call read %d @ %d\n", count, offset);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_READ);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_READ, ruid);
p = xdr_encode_fhandle(p, fhandle);
*p++ = htonl(offset);
*p++ = htonl(count);
@@ -336,8 +366,13 @@ int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
else
PRINTK("NFS reply read %d\n", len);
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply read failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return (status == NFS_OK) ? len : -nfs_stat_to_errno(status);
}
@@ -347,11 +382,13 @@ int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call write %d @ %d\n", count, offset);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_WRITE);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);
p = xdr_encode_fhandle(p, fhandle);
*p++ = htonl(offset); /* traditional, could be any value */
*p++ = htonl(offset);
@@ -367,8 +404,13 @@ int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
p = xdr_decode_fattr(p, fattr);
PRINTK("NFS reply write\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply write failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -379,11 +421,13 @@ int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call create %s\n", name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_CREATE);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_CREATE, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
p = xdr_encode_sattr(p, sattr);
@@ -398,8 +442,13 @@ int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
p = xdr_decode_fattr(p, fattr);
PRINTK("NFS reply create\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply create failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -408,11 +457,13 @@ int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *n
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call remove %s\n", name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_REMOVE);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_REMOVE, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
@@ -424,8 +475,13 @@ int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *n
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply remove\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply remove failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -436,11 +492,13 @@ int nfs_proc_rename(struct nfs_server *server,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call rename %s -> %s\n", old_name, new_name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_RENAME);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_RENAME, ruid);
p = xdr_encode_fhandle(p, old_dir);
p = xdr_encode_string(p, old_name);
p = xdr_encode_fhandle(p, new_dir);
@@ -454,8 +512,13 @@ int nfs_proc_rename(struct nfs_server *server,
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply rename\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply rename failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -465,11 +528,13 @@ int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call link %s\n", name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_LINK);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_LINK, ruid);
p = xdr_encode_fhandle(p, fhandle);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
@@ -482,8 +547,13 @@ int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply link\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply link failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -493,11 +563,13 @@ int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call symlink %s -> %s\n", name, path);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_SYMLINK);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_SYMLINK, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
p = xdr_encode_string(p, path);
@@ -511,8 +583,13 @@ int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply symlink\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply symlink failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -523,11 +600,13 @@ int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call mkdir %s\n", name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_MKDIR);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_MKDIR, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
p = xdr_encode_sattr(p, sattr);
@@ -542,8 +621,13 @@ int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
p = xdr_decode_fattr(p, fattr);
PRINTK("NFS reply mkdir\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply mkdir failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -552,11 +636,13 @@ int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *na
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call rmdir %s\n", name);
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_RMDIR);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid);
p = xdr_encode_fhandle(p, dir);
p = xdr_encode_string(p, name);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
@@ -568,8 +654,13 @@ int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *na
else if ((status = ntohl(*p++)) == NFS_OK) {
PRINTK("NFS reply rmdir\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply rmdir failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -579,6 +670,7 @@ int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
{
int *p, *p0;
int status;
+ int ruid = 0;
int i = 0; /* = 0 is for gcc */
int size;
int eof;
@@ -587,7 +679,8 @@ int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
size = server->rsize;
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_READDIR);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid);
p = xdr_encode_fhandle(p, fhandle);
*p++ = htonl(cookie);
*p++ = htonl(size);
@@ -615,8 +708,13 @@ int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
eof ? "eof" : "");
}
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply readdir failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return (status == NFS_OK) ? i : -nfs_stat_to_errno(status);
}
@@ -626,11 +724,13 @@ int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
{
int *p, *p0;
int status;
+ int ruid = 0;
PRINTK("NFS call statfs\n");
if (!(p0 = nfs_rpc_alloc()))
return -EIO;
- p = nfs_rpc_header(p0, NFSPROC_STATFS);
+retry:
+ p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid);
p = xdr_encode_fhandle(p, fhandle);
if ((status = nfs_rpc_call(server, p0, p)) < 0) {
nfs_rpc_free(p0);
@@ -642,8 +742,13 @@ int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
p = xdr_decode_fsinfo(p, res);
PRINTK("NFS reply statfs\n");
}
- else
+ else {
+ if (!ruid && current->euid == 0 && current->uid != 0) {
+ ruid = 1;
+ goto retry;
+ }
PRINTK("NFS reply statfs failed = %d\n", status);
+ }
nfs_rpc_free(p0);
return -nfs_stat_to_errno(status);
}
@@ -652,7 +757,7 @@ int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
* Here are a few RPC-assist functions.
*/
-static int *nfs_rpc_header(int *p, int procedure)
+static int *nfs_rpc_header(int *p, int procedure, int ruid)
{
int *p1, *p2;
int i;
@@ -673,7 +778,7 @@ static int *nfs_rpc_header(int *p, int procedure)
p1 = p++;
*p++ = htonl(CURRENT_TIME); /* traditional, could be anything */
p = xdr_encode_string(p, (char *) sys);
- *p++ = htonl(current->euid);
+ *p++ = htonl(ruid ? current->uid : current->euid);
*p++ = htonl(current->egid);
p2 = p++;
for (i = 0; i < 16 && i < NGROUPS && current->groups[i] != NOGROUP; i++)
diff --git a/include/linux/in_systm.h b/include/linux/in_systm.h
new file mode 100644
index 0000000..eac9a58
--- /dev/null
+++ b/include/linux/in_systm.h
@@ -0,0 +1,32 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Miscellaneous internetwork definitions for kernel.
+ *
+ * Version: @(#)in_systm.h 1.0.0 12/17/93
+ *
+ * Authors: Original taken from Berkeley BSD UNIX 4.3-RENO.
+ * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IN_SYSTM_H
+#define _LINUX_IN_SYSTM_H
+
+/*
+ * Network types.
+ * The n_ types are network-order variants of their natural
+ * equivalents. The Linux kernel NET-2 code does not use
+ * them (yet), but it might in the future. This is mostly
+ * there for compatibility with BSD user-level programs.
+ */
+typedef u_short n_short; /* short as received from the net */
+typedef u_long n_long; /* long as received from the net */
+typedef u_long n_time; /* ms since 00:00 GMT, byte rev */
+
+#endif /* _LINUX_IN_SYSTM_H */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d890096..d1ae039 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -81,7 +81,7 @@ extern unsigned long free_page_list;
extern int nr_secondary_pages;
extern unsigned long secondary_page_list;
-#define MAX_SECONDARY_PAGES 10
+#define MAX_SECONDARY_PAGES 20
/*
* This is timing-critical - most of the time in getting a new page
diff --git a/kernel/signal.c b/kernel/signal.c
index db3df6d..dde9e11 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -183,6 +183,9 @@ asmlinkage int sys_sigaction(int signum, const struct sigaction * action,
return -EINVAL;
p = signum - 1 + current->sigaction;
if (action) {
+ int err = verify_area(VERIFY_READ, action, sizeof(*action));
+ if (err)
+ return err;
memcpy_fromfs(&new_sa, action, sizeof(struct sigaction));
if (new_sa.sa_flags & SA_NOMASK)
new_sa.sa_mask = 0;
@@ -194,8 +197,10 @@ asmlinkage int sys_sigaction(int signum, const struct sigaction * action,
return -EFAULT;
}
if (oldaction) {
- if (!verify_area(VERIFY_WRITE,oldaction, sizeof(struct sigaction)))
- memcpy_tofs(oldaction, p, sizeof(struct sigaction));
+ int err = verify_area(VERIFY_WRITE, oldaction, sizeof(*oldaction));
+ if (err)
+ return err;
+ memcpy_tofs(oldaction, p, sizeof(struct sigaction));
}
if (action) {
*p = new_sa;
diff --git a/net/inet/route.c b/net/inet/route.c
index 5a67bd7..f8c2a58 100644
--- a/net/inet/route.c
+++ b/net/inet/route.c
@@ -276,9 +276,12 @@ static int rt_new(struct rtentry *r)
mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
+ if (bad_mask(mask, daddr))
+ mask = 0;
+
if (flags & RTF_HOST)
mask = 0xffffffff;
- else if (r->rt_genmask.sa_family != AF_INET)
+ else if (mask && r->rt_genmask.sa_family != AF_INET)
return -EAFNOSUPPORT;
if (flags & RTF_GATEWAY) {
@@ -292,9 +295,6 @@ static int rt_new(struct rtentry *r)
if (dev == NULL)
return -ENETUNREACH;
- if (bad_mask(mask, daddr))
- mask = 0;
-
rt_add(flags, daddr, mask, gw, dev);
return 0;
}