diff options
author | Linus Torvalds <torvalds@cc.helsinki.fi> | 1994-02-14 16:51:45 +0000 |
---|---|---|
committer | Nicolas Pitre <nico@cam.org> | 2007-08-19 14:19:32 -0400 |
commit | 61119d8da02481d9744f37f62cabeec5aecac3ba (patch) | |
tree | 22bf3689b1b5559861c4c3bc5ca480c65937aa8e | |
parent | d9cc76127bcc137e3214b9166c439e02d2060cda (diff) | |
download | archive-61119d8da02481d9744f37f62cabeec5aecac3ba.tar.gz |
ALPHA-pl15d
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | drivers/FPU-emu/README | 32 | ||||
-rw-r--r-- | drivers/FPU-emu/errors.c | 9 | ||||
-rw-r--r-- | drivers/FPU-emu/fpu_emu.h | 6 | ||||
-rw-r--r-- | drivers/FPU-emu/fpu_entry.c | 90 | ||||
-rw-r--r-- | drivers/FPU-emu/fpu_proto.h | 43 | ||||
-rw-r--r-- | drivers/FPU-emu/fpu_system.h | 5 | ||||
-rw-r--r-- | drivers/FPU-emu/get_address.c | 195 | ||||
-rw-r--r-- | drivers/FPU-emu/load_store.c | 46 | ||||
-rw-r--r-- | drivers/FPU-emu/reg_ld_str.c | 151 | ||||
-rw-r--r-- | drivers/FPU-emu/version.h | 2 | ||||
-rw-r--r-- | drivers/net/Space.c | 8 | ||||
-rw-r--r-- | fs/binfmt_coff.c | 76 | ||||
-rw-r--r-- | fs/nfs/proc.c | 173 | ||||
-rw-r--r-- | include/linux/in_systm.h | 32 | ||||
-rw-r--r-- | include/linux/mm.h | 2 | ||||
-rw-r--r-- | kernel/signal.c | 9 | ||||
-rw-r--r-- | net/inet/route.c | 8 |
18 files changed, 621 insertions, 268 deletions
@@ -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, ®s[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; } |