[PATCH] [2.4.24-pre3] 2/5 EXT2/3 Updates

From: Theodore Ts'o
Date: Thu Jan 01 2004 - 17:22:05 EST



# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.1357 -> 1.1358
# fs/ext2/inode.c 1.19 -> 1.20
# fs/ext3/inode.c 1.16 -> 1.17
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/01/01 tytso@xxxxxxxxxxxxxxx 1.1358
# Applied 4208-ext23-symlink-ea-compat.patch from sct@xxxxxxxxxx
#
# I found why people running SELinux on 2.6 were having trouble booting
# again on 2.4 kernels, and it's nothing to do with SELinux per-se. It's
# a compatibility problem with extended attributes.
#
# The trouble is that setting an EA on a fast symlink upsets the kernel's
# symlink detection code. Older kernels will see a symlink with non-zero
# i_blocks, and will assume that the symlink is a slow one --- ie. that
# the first direct block of the inode points to the symlink contents ---
# and will end up doing a block lookup from what is in fact the first four
# ascii chars from the symlink path.
#
# 2.6 kernels deal with this by detecting a non-zero i_file_acl field and
# subtracting the EA's blocks from i_blocks before checking if the block
# count is zero. The patch below adds the same compatibility code to
# 2.4. Booting a SELinux partition results in immediate death via access
# beyond end-of-device as soon as the kernel tries to dereference /bin/sh
# (a symlink to /bin/bash on this box); with the fix, it's fine.
#
# --------------------------------------------
#
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
--- a/fs/ext2/inode.c Thu Jan 1 16:29:13 2004
+++ b/fs/ext2/inode.c Thu Jan 1 16:29:13 2004
@@ -35,6 +35,17 @@
MODULE_DESCRIPTION("Second Extended Filesystem");
MODULE_LICENSE("GPL");

+/*
+ * Test whether an inode is a fast symlink.
+ */
+static inline int ext2_inode_is_fast_symlink(struct inode *inode)
+{
+ int ea_blocks = inode->u.ext2_i.i_file_acl ?
+ (inode->i_sb->s_blocksize >> 9) : 0;
+
+ return (S_ISLNK(inode->i_mode) &&
+ inode->i_blocks - ea_blocks == 0);
+}

static int ext2_update_inode(struct inode * inode, int do_sync);

@@ -801,6 +812,8 @@
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
+ if (ext2_inode_is_fast_symlink(inode))
+ return;
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
return;

@@ -1001,7 +1014,7 @@
inode->i_fop = &ext2_dir_operations;
inode->i_mapping->a_ops = &ext2_aops;
} else if (S_ISLNK(inode->i_mode)) {
- if (!inode->i_blocks)
+ if (ext2_inode_is_fast_symlink(inode))
inode->i_op = &ext2_fast_symlink_inode_operations;
else {
inode->i_op = &page_symlink_inode_operations;
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c Thu Jan 1 16:29:13 2004
+++ b/fs/ext3/inode.c Thu Jan 1 16:29:13 2004
@@ -39,6 +39,18 @@
*/
#undef SEARCH_FROM_ZERO

+/*
+ * Test whether an inode is a fast symlink.
+ */
+static inline int ext3_inode_is_fast_symlink(struct inode *inode)
+{
+ int ea_blocks = EXT3_I(inode)->i_file_acl ?
+ (inode->i_sb->s_blocksize >> 9) : 0;
+
+ return (S_ISLNK(inode->i_mode) &&
+ inode->i_blocks - ea_blocks == 0);
+}
+
/* The ext3 forget function must perform a revoke if we are freeing data
* which has been journaled. Metadata (eg. indirect blocks) must be
* revoked in all cases.
@@ -1870,6 +1882,8 @@
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
+ if (ext3_inode_is_fast_symlink(inode))
+ return;
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
return;

@@ -2170,7 +2184,7 @@
inode->i_op = &ext3_dir_inode_operations;
inode->i_fop = &ext3_dir_operations;
} else if (S_ISLNK(inode->i_mode)) {
- if (!inode->i_blocks)
+ if (ext3_inode_is_fast_symlink(inode))
inode->i_op = &ext3_fast_symlink_inode_operations;
else {
inode->i_op = &page_symlink_inode_operations;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/