lkml.org 
[lkml]   [1996]   [Apr]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Ext2 Problem
> I could have a look at it tonight, postponing the SCSI patch by a day.
> Sounds a bit messy, however, especially if the fs turns out to be non-minix
> and we have to undo/invalidate all that was done.
> This is a very minor problem (strange, nobody ever complained that I
> noticed, and now we have three cases in one week) and not worth a lot of
> code.

Don't bother with the patch: I thinkI have something that does what I want.
It's untested, but maybe somebody could try this out?

This patch essentially makes the minix mount operation do a lot more checks
before it accepts the filesystem as a real minix filesystem. It checks that the
root inode really is a directory, and then it reads the first block of the root
directory and checks that "." and ".." exist, and have the right inode numbers.

While doing that it also checks how far apart they are, giving us the directory
entry size.. The funny thing is that while I was doing this, a m68k patch came
in that did some of this but not as complete..

I don't actually have any minix filesystems left, so could somebody else test
this out? Preferably somebody who has a filesystem that can be confused with
something else..

Linusdiff -u --recursive --new-file v1.3.91/linux/Makefile linux/Makefile
--- v1.3.91/linux/Makefile Fri Apr 19 10:07:57 1996
+++ linux/Makefile Fri Apr 19 07:35:35 1996
@@ -1,6 +1,6 @@
VERSION = 1
PATCHLEVEL = 3
-SUBLEVEL = 91
+SUBLEVEL = 92

ARCH = i386

diff -u --recursive --new-file v1.3.91/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v1.3.91/linux/arch/alpha/defconfig Mon Apr 15 12:20:17 1996
+++ linux/arch/alpha/defconfig Fri Apr 19 10:51:45 1996
@@ -75,6 +75,7 @@
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_AX25 is not set
+# CONFIG_BRIDGE is not set
# CONFIG_NETLINK is not set

#
@@ -106,6 +107,7 @@
# CONFIG_SCSI_AHA1740 is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_U14_34F is not set
@@ -114,6 +116,7 @@
CONFIG_SCSI_NCR53C7xx=y
CONFIG_SCSI_NCR53C7xx_sync=y
CONFIG_SCSI_NCR53C7xx_FAST=y
+# CONFIG_SCSI_NCR53C7xx_DISCONNECT is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_QLOGIC is not set
@@ -134,6 +137,7 @@
# CONFIG_SLIP is not set
# CONFIG_PPP is not set
# CONFIG_STRIP is not set
+# CONFIG_WIC is not set
# CONFIG_SCC is not set
# CONFIG_PLIP is not set
# CONFIG_EQUALIZER is not set
diff -u --recursive --new-file v1.3.91/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- v1.3.91/linux/arch/alpha/mm/fault.c Tue Mar 12 15:31:10 1996
+++ linux/arch/alpha/mm/fault.c Fri Apr 19 13:28:06 1996
@@ -18,6 +18,22 @@
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+
+unsigned long asn_cache = ASN_FIRST_VERSION;
+
+#ifndef BROKEN_ASN
+/*
+ * Select a new ASN and reload the context. This is
+ * not inlined as this expands to a pretty large
+ * function.
+ */
+void get_new_asn_and_reload(struct task_struct *tsk, struct mm_struct *mm)
+{
+ get_new_mmu_context(tsk, mm, asn_cache);
+ reload_context(tsk);
+}
+#endif

extern void die_if_kernel(char *,struct pt_regs *,long);

diff -u --recursive --new-file v1.3.91/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v1.3.91/linux/arch/i386/kernel/process.c Fri Apr 12 15:51:46 1996
+++ linux/arch/i386/kernel/process.c Fri Apr 19 07:35:25 1996
@@ -266,6 +266,22 @@

for (i=0 ; i<8 ; i++)
current->debugreg[i] = 0;
+
+ /*
+ * Forget coprocessor state..
+ */
+#ifdef __SMP__
+ if (current->flags & PF_USEDFPU) {
+ stts();
+ }
+#else
+ if (last_task_used_math == current) {
+ last_task_used_math = NULL;
+ stts();
+ }
+#endif
+ current->used_math = 0;
+ current->flags &= PF_USEDFPU;
}

void release_thread(struct task_struct *dead_task)
diff -u --recursive --new-file v1.3.91/linux/fs/exec.c linux/fs/exec.c
--- v1.3.91/linux/fs/exec.c Mon Apr 8 19:01:44 1996
+++ linux/fs/exec.c Fri Apr 19 07:35:25 1996
@@ -436,9 +436,6 @@
if (FD_ISSET(i,&current->files->close_on_exec))
sys_close(i);
FD_ZERO(&current->files->close_on_exec);
- if (last_task_used_math == current)
- last_task_used_math = NULL;
- current->used_math = 0;
}

/*
diff -u --recursive --new-file v1.3.91/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v1.3.91/linux/fs/minix/inode.c Mon Jan 15 07:59:11 1996
+++ linux/fs/minix/inode.c Fri Apr 19 15:07:22 1996
@@ -117,6 +117,50 @@
return 0;
}

+/*
+ * Check the root directory of the filesystem to make sure
+ * it really _is_ a minix filesystem, and to check the size
+ * of the directory entry.
+ */
+static const char * minix_checkroot(struct super_block *s)
+{
+ struct inode * dir;
+ struct buffer_head *bh;
+ struct minix_dir_entry *de;
+ const char * errmsg;
+ int dirsize;
+
+ dir = s->s_mounted;
+ if (!S_ISDIR(dir->i_mode))
+ return "root directory is not a directory";
+
+ bh = minix_bread(dir, 0, 0);
+ if (!bh)
+ return "unable to read root directory";
+
+ de = (struct minix_dir_entry *) bh->b_data;
+ errmsg = "bad root directory '.' entry";
+ dirsize = BLOCK_SIZE;
+ if (de->inode == MINIX_ROOT_INO && strcmp(de->name, ".") == 0) {
+ errmsg = "bad root directory '..' entry";
+ dirsize = 8;
+ }
+
+ while ((dirsize <<= 1) < BLOCK_SIZE) {
+ de = (struct minix_dir_entry *) (bh->b_data + dirsize);
+ if (de->inode != MINIX_ROOT_INO)
+ continue;
+ if (strcmp(de->name, ".."))
+ continue;
+ s->u.minix_sb.s_dirsize = dirsize;
+ s->u.minix_sb.s_namelen = dirsize - 2;
+ errmsg = NULL;
+ break;
+ }
+ brelse(bh);
+ return errmsg;
+}
+
struct super_block *minix_read_super(struct super_block *s,void *data,
int silent)
{
@@ -124,6 +168,7 @@
struct minix_super_block *ms;
int i, block;
kdev_t dev = s->s_dev;
+ const char * errmsg;

if (32 != sizeof (struct minix_inode))
panic("bad V1 i-node size");
@@ -186,6 +231,15 @@
s->u.minix_sb.s_imap[i] = NULL;
for (i=0;i < MINIX_Z_MAP_SLOTS;i++)
s->u.minix_sb.s_zmap[i] = NULL;
+ if (s->u.minix_sb.s_zmap_blocks > MINIX_Z_MAP_SLOTS) {
+ s->s_dev = 0;
+ unlock_super (s);
+ brelse (bh);
+ if (!silent)
+ printk ("MINIX-fs: filesystem too big\n");
+ MOD_DEC_USE_COUNT;
+ return NULL;
+ }
block=2;
for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++)
if ((s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
@@ -219,10 +273,23 @@
if (!s->s_mounted) {
s->s_dev = 0;
brelse(bh);
- printk("MINIX-fs: get root inode failed\n");
+ if (!silent)
+ printk("MINIX-fs: get root inode failed\n");
MOD_DEC_USE_COUNT;
return NULL;
}
+
+ errmsg = minix_checkroot(s);
+ if (errmsg) {
+ if (!silent)
+ printk("MINIX-fs: %s\n", errmsg);
+ iput (s->s_mounted);
+ s->s_dev = 0;
+ brelse (bh);
+ MOD_DEC_USE_COUNT;
+ return NULL;
+ }
+
if (!(s->s_flags & MS_RDONLY)) {
ms->s_state &= ~MINIX_VALID_FS;
mark_buffer_dirty(bh, 1);
@@ -314,7 +381,7 @@
return tmp;
}

-int V2_minix_bmap(struct inode * inode,int block)
+static int V2_minix_bmap(struct inode * inode,int block)
{
int i;

diff -u --recursive --new-file v1.3.91/linux/fs/nfs/nfsroot.c linux/fs/nfs/nfsroot.c
--- v1.3.91/linux/fs/nfs/nfsroot.c Wed Apr 17 09:06:32 1996
+++ linux/fs/nfs/nfsroot.c Fri Apr 19 09:19:53 1996
@@ -90,6 +90,7 @@
#include <net/route.h>
#include <net/sock.h>

+#include <asm/segment.h>

/* Range of privileged ports */
#define STARTPORT 600
diff -u --recursive --new-file v1.3.91/linux/fs/super.c linux/fs/super.c
--- v1.3.91/linux/fs/super.c Mon Apr 15 12:20:21 1996
+++ linux/fs/super.c Fri Apr 19 08:21:49 1996
@@ -796,6 +796,8 @@
vma = find_vma(current, (unsigned long) data);
if (!vma || (unsigned long) data < vma->vm_start)
return -EFAULT;
+ if (!(vma->vm_flags & VM_READ))
+ return -EFAULT;
i = vma->vm_end - (unsigned long) data;
if (PAGE_SIZE <= (unsigned long) i)
i = PAGE_SIZE-1;
diff -u --recursive --new-file v1.3.91/linux/include/asm-alpha/mmu_context.h linux/include/asm-alpha/mmu_context.h
--- v1.3.91/linux/include/asm-alpha/mmu_context.h Thu Feb 29 08:59:44 1996
+++ linux/include/asm-alpha/mmu_context.h Fri Apr 19 13:28:06 1996
@@ -36,12 +36,32 @@
#define MAX_ASN 127
#else
#define MAX_ASN 63
+#define BROKEN_ASN 1
#endif

+extern unsigned long asn_cache;
+
#define ASN_VERSION_SHIFT 16
#define ASN_VERSION_MASK ((~0UL) << ASN_VERSION_SHIFT)
#define ASN_FIRST_VERSION (1UL << ASN_VERSION_SHIFT)

+extern inline void get_new_mmu_context(struct task_struct *p,
+ struct mm_struct *mm,
+ unsigned long asn)
+{
+ /* check if it's legal.. */
+ if ((asn & ~ASN_VERSION_MASK) > MAX_ASN) {
+ /* start a new version, invalidate all old asn's */
+ tbiap(); imb();
+ asn = (asn & ASN_VERSION_MASK) + ASN_FIRST_VERSION;
+ if (!asn)
+ asn = ASN_FIRST_VERSION;
+ }
+ asn_cache = asn + 1;
+ mm->context = asn; /* full version + asn */
+ p->tss.asn = asn & ~ASN_VERSION_MASK; /* just asn */
+}
+
/*
* NOTE! The way this is set up, the high bits of the "asn_cache" (and
* the "mm->context") are the ASN _version_ code. A version of 0 is
@@ -55,28 +75,14 @@
*/
extern inline void get_mmu_context(struct task_struct *p)
{
-#ifdef CONFIG_ALPHA_EV5
- static unsigned long asn_cache = ASN_FIRST_VERSION;
+#ifndef BROKEN_ASN
struct mm_struct * mm = p->mm;

if (mm) {
- unsigned long asn = mm->context;
+ unsigned long asn = asn_cache;
/* Check if our ASN is of an older version and thus invalid */
- if ((asn_cache ^ asn) & ASN_VERSION_MASK) {
- /* get a new asn of the current version */
- asn = asn_cache++;
- /* check if it's legal.. */
- if ((asn & ~ASN_VERSION_MASK) > MAX_ASN) {
- /* start a new version, invalidate all old asn's */
- tbiap(); imb();
- asn_cache = (asn_cache & ASN_VERSION_MASK) + ASN_FIRST_VERSION;
- if (!asn_cache)
- asn_cache = ASN_FIRST_VERSION;
- asn = asn_cache++;
- }
- mm->context = asn; /* full version + asn */
- p->tss.asn = asn & ~ASN_VERSION_MASK; /* just asn */
- }
+ if ((mm->context ^ asn) & ASN_VERSION_MASK)
+ get_new_mmu_context(p, mm, asn);
}
#endif
}
diff -u --recursive --new-file v1.3.91/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- v1.3.91/linux/include/asm-alpha/pgtable.h Wed Apr 3 16:06:56 1996
+++ linux/include/asm-alpha/pgtable.h Fri Apr 19 13:38:28 1996
@@ -10,6 +10,7 @@
*/

#include <asm/system.h>
+#include <asm/mmu_context.h>

/* Caches aren't brain-dead on the alpha. */
#define flush_cache_all() do { } while (0)
@@ -19,11 +20,63 @@
#define flush_page_to_ram(page) do { } while (0)

/*
+ * Force a context reload. This is needed when we
+ * change the page table pointer or when we update
+ * the ASN of the current process.
+ */
+static inline void reload_context(struct task_struct *task)
+{
+ __asm__ __volatile__(
+ "bis %0,%0,$16\n\t"
+ "call_pal %1"
+ : /* no outputs */
+ : "r" (&task->tss), "i" (PAL_swpctx)
+ : "$0", "$1", "$16", "$22", "$23", "$24", "$25");
+}
+
+/*
+ * Use a few helper functions to hide the ugly broken ASN
+ * numbers on early alpha's (ev4 and ev45)
+ */
+#ifdef BROKEN_ASN
+
+#define flush_tlb_current(x) tbiap()
+#define flush_tlb_other(x) do { } while (0)
+
+#else
+
+extern void get_new_asn_and_reload(struct task_struct *, struct mm_struct *);
+
+#define flush_tlb_current(mm) get_new_asn_and_reload(current, mm)
+#define flush_tlb_other(mm) do { (mm)->context = 0; } while (0)
+
+#endif
+
+/*
+ * Flush just one page in the current TLB set.
+ * We need to be very careful about the icache here, there
+ * is no way to invalidate a specific icache page..
+ */
+static inline void flush_tlb_current_page(struct mm_struct * mm,
+ struct vm_area_struct *vma,
+ unsigned long addr)
+{
+#ifdef BROKEN_ASN
+ tbi(2 + ((vma->vm_flags & VM_EXEC) != 0), addr);
+#else
+ if (vma->vm_flags & VM_EXEC)
+ flush_tlb_current(mm);
+ else
+ tbi(2, addr);
+#endif
+}
+
+/*
* Flush current user mapping.
*/
static inline void flush_tlb(void)
{
- tbiap();
+ flush_tlb_current(current->mm);
}

/*
@@ -41,9 +94,9 @@
static inline void flush_tlb_mm(struct mm_struct *mm)
{
if (mm != current->mm)
- mm->context = 0;
+ flush_tlb_other(mm);
else
- tbiap();
+ flush_tlb_current(mm);
}

/*
@@ -60,9 +113,9 @@
struct mm_struct * mm = vma->vm_mm;

if (mm != current->mm)
- mm->context = 0;
+ flush_tlb_other(mm);
else
- tbi(2 + ((vma->vm_flags & VM_EXEC) != 0), addr);
+ flush_tlb_current_page(mm, vma, addr);
}

/*
@@ -72,10 +125,7 @@
static inline void flush_tlb_range(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
- if (mm != current->mm)
- mm->context = 0;
- else
- tbiap();
+ flush_tlb_mm(mm);
}

/* Certain architectures need to do special things when pte's
@@ -291,12 +341,7 @@
pgd_val(pgdir[PTRS_PER_PGD]) = pte_val(mk_pte((unsigned long) pgdir, PAGE_KERNEL));
tsk->tss.ptbr = ((unsigned long) pgdir - PAGE_OFFSET) >> PAGE_SHIFT;
if (tsk == current)
- __asm__ __volatile__(
- "bis %0,%0,$16\n\t"
- "call_pal %1"
- : /* no outputs */
- : "r" (&tsk->tss), "i" (PAL_swpctx)
- : "$0", "$1", "$16", "$22", "$23", "$24", "$25");
+ reload_context(tsk);
}

#define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
diff -u --recursive --new-file v1.3.91/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v1.3.91/linux/net/ipv4/udp.c Fri Apr 19 10:08:03 1996
+++ linux/net/ipv4/udp.c Fri Apr 19 08:13:59 1996
@@ -578,6 +578,7 @@
if(uh_cache_sk==sk)
udp_cache_zap();
release_sock(sk);
+ sk->dead = 1;
destroy_sock(sk);
}
\
 
 \ /
  Last update: 2005-03-22 13:37    [W:0.043 / U:0.324 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site