diff -u --recursive --new-file linux.orig/fs/fat/inode.c linux/fs/fat/inode.c
--- linux.orig/fs/fat/inode.c	Tue Sep  5 23:07:29 2000
+++ linux/fs/fat/inode.c	Sun Nov 12 19:46:20 2000
@@ -221,6 +221,7 @@
 	opts->nocase = 0;
 	opts->utf8 = 0;
 	opts->iocharset = NULL;
+	opts->maphs = 0;
 	*debug = *fat = 0;
 
 	if (!options)
@@ -356,6 +357,10 @@
 				return 0;
 			strncpy(cvf_options,value,100);
 		}
+		else if (!strcmp(this_char,"maphs")) {
+			if (value) return 0;
+			opts->maphs = 1;
+		}
 
 		if (this_char != options) *(this_char-1) = ',';
 		if (value) *savep = save;
@@ -468,6 +473,11 @@
 	memcpy(&(sbi->options), &opts, sizeof(struct fat_mount_options));
 
 	fat_cache_init();
+	if (opts.maphs) {
+		/* If we map system and hidden files to setuid and setgid,
+		 * we don't want setuid bits to be allowed. */
+		sb->s_flags |= MS_NOSUID;
+	}
 	if( blksize > 1024 )
 	  {
 	    /* Force the superblock to a larger size here. */
@@ -779,8 +789,9 @@
 	inode->i_gid = sbi->options.fs_gid;
 	inode->i_version = ++event;
 	if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {
-		inode->i_mode = MSDOS_MKMODE(de->attr,S_IRWXUGO &
-		    ~sbi->options.fs_umask) | S_IFDIR;
+		inode->i_mode = MSDOS_MKMODE(de->attr,S_IALLUGO &
+		    ~sbi->options.fs_umask,
+		    sbi->options.maphs ) | S_IFDIR;
 		inode->i_op = sbi->dir_ops;
 		inode->i_fop = &fat_dir_operations;
 
@@ -814,8 +825,9 @@
 		    ((IS_NOEXEC(inode) || 
 		      (sbi->options.showexec &&
 		       !is_exec(de->ext)))
-		    	? S_IRUGO|S_IWUGO : S_IRWXUGO)
-		    & ~sbi->options.fs_umask) | S_IFREG;
+		    	? S_IALLUGO&~S_IXUGO : S_IALLUGO)
+		    & ~sbi->options.fs_umask,
+		    sbi->options.maphs) | S_IFREG;
 		MSDOS_I(inode)->i_start = CF_LE_W(de->start);
 		if (sbi->fat_bits == 32) {
 			MSDOS_I(inode)->i_start |=
@@ -884,8 +896,9 @@
 		raw_entry->attr = ATTR_NONE;
 		raw_entry->size = CT_LE_L(inode->i_size);
 	}
-	raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
-	    MSDOS_I(inode)->i_attrs;
+	raw_entry->attr |= ( MSDOS_SB(sb)->options.maphs ?
+	    MSDOS_MKATTR(inode->i_mode, 1) :
+	    ( MSDOS_MKATTR(inode->i_mode, 0) | MSDOS_I(inode)->i_attrs ) );
 	raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart);
 	raw_entry->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16);
 	fat_date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
@@ -928,11 +941,13 @@
 	inode_setattr(inode, attr);
 
 	if (IS_NOEXEC(inode) && !S_ISDIR(inode->i_mode))
-		inode->i_mode &= S_IFMT | S_IRUGO | S_IWUGO;
+		inode->i_mode &= S_IFMT | (S_IALLUGO & ~S_IXUGO);
 	else
 		inode->i_mode |= S_IXUGO;
 
 	inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU
+	inode->i_mode = ((inode->i_mode & (S_IFMT|S_ISUID|S_ISGID|S_ISVTX)) 
+	    | ((((inode->i_mode & S_IRWXU
 	    & ~MSDOS_SB(sb)->options.fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
 	    ~MSDOS_SB(sb)->options.fs_umask;
 	return 0;
diff -u --recursive --new-file linux.orig/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
--- linux.orig/include/linux/msdos_fs.h	Thu Jul  6 01:25:04 2000
+++ linux/include/linux/msdos_fs.h	Sun Nov 12 19:52:15 2000
@@ -57,7 +57,8 @@
 #define IS_FREE(n) (!*(n) || *(const unsigned char *) (n) == DELETED_FLAG || \
   *(const unsigned char *) (n) == FD_FILL_BYTE)
 
-#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)
+#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO | \
+	S_ISUID | S_ISGID | S_ISVTX)
 	/* valid file mode bits */
 
 #define MSDOS_SB(s) (&((s)->u.msdos_sb))
@@ -175,10 +176,17 @@
     ((mib)->data_start & 1)))
 
 /* Convert attribute bits and a mask to the UNIX mode. */
-#define MSDOS_MKMODE(a,m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO))
+#define MSDOS_MKMODE(a,m,hs) \
+	( m & ( ( a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO ) | ( hs ? \
+		( ( a & ATTR_SYS ? S_ISUID : 0 ) \
+		 |( a & ATTR_HIDDEN ? S_ISGID : 0 ) ) \
+		: 0 ) ) )
 
 /* Convert the UNIX mode to MS-DOS attribute bits. */
-#define MSDOS_MKATTR(m) ((m & S_IWUGO) ? ATTR_NONE : ATTR_RO)
+#define MSDOS_MKATTR(m, hs) ( ((m & S_IWUGO) ? ATTR_NONE : ATTR_RO) | ( hs ? \
+	    ( ( m&S_ISUID ? ATTR_SYS : ATTR_NONE ) \
+	     |( m&S_ISGID ? ATTR_HIDDEN : ATTR_NONE ) ) \
+	 : ATTR_NONE ) ) 
 
 
 #ifdef __KERNEL__
diff -u --recursive --new-file linux.orig/include/linux/msdos_fs_sb.h linux/include/linux/msdos_fs_sb.h
--- linux.orig/include/linux/msdos_fs_sb.h	Tue Sep  5 23:53:04 2000
+++ linux/include/linux/msdos_fs_sb.h	Sun Nov 12 19:47:19 2000
@@ -25,7 +25,8 @@
 		 numtail:1,       /* Does first alias have a numeric '~1' type tail? */
 		 atari:1,         /* Use Atari GEMDOS variation of MS-DOS fs */
 		 fat32:1,	  /* Is this a FAT32 partition? */
-		 nocase:1;	  /* Does this need case conversion? 0=need case conversion*/
+		 nocase:1,	  /* Does this need case conversion? 0=need case conversion*/
+		 maphs:1;
 };
 
 struct vfat_unicode {
