2008-12-16 15:51:56

by Duane Griffin

[permalink] [raw]
Subject: [PATCH] ext3: ensure fast symlinks are NUL-terminated

Ensure fast symlink targets are NUL-terminated, even if corrupted
on-disk.

Cc: Andrew Morton <[email protected]>
Cc: Stephen Tweedie <[email protected]>
Cc: [email protected]
Signed-off-by: Duane Griffin <[email protected]>
---
fs/ext3/inode.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index f8424ad..24aacdf 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -37,6 +37,7 @@
#include <linux/uio.h>
#include <linux/bio.h>
#include <linux/fiemap.h>
+#include <linux/namei.h>
#include "xattr.h"
#include "acl.h"

@@ -2817,9 +2818,11 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino)
inode->i_op = &ext3_dir_inode_operations;
inode->i_fop = &ext3_dir_operations;
} else if (S_ISLNK(inode->i_mode)) {
- if (ext3_inode_is_fast_symlink(inode))
+ if (ext3_inode_is_fast_symlink(inode)) {
inode->i_op = &ext3_fast_symlink_inode_operations;
- else {
+ nd_terminate_link(ei->i_data, inode->i_size,
+ sizeof(ei->i_data));
+ } else {
inode->i_op = &ext3_symlink_inode_operations;
ext3_set_aops(inode);
}
--
1.6.0.4



2008-12-16 15:52:17

by Duane Griffin

[permalink] [raw]
Subject: [PATCH] ext4: ensure fast symlinks are NUL-terminated

Ensure fast symlink targets are NUL-terminated, even if corrupted
on-disk.

Cc: Andrew Morton <[email protected]>
Cc: Theodore Ts'o <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Duane Griffin <[email protected]>
---
fs/ext4/inode.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index ca88060..f0e6bfb 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -34,6 +34,7 @@
#include <linux/writeback.h>
#include <linux/pagevec.h>
#include <linux/mpage.h>
+#include <linux/namei.h>
#include <linux/uio.h>
#include <linux/bio.h>
#include "ext4_jbd2.h"
@@ -4200,9 +4201,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
inode->i_op = &ext4_dir_inode_operations;
inode->i_fop = &ext4_dir_operations;
} else if (S_ISLNK(inode->i_mode)) {
- if (ext4_inode_is_fast_symlink(inode))
+ if (ext4_inode_is_fast_symlink(inode)) {
inode->i_op = &ext4_fast_symlink_inode_operations;
- else {
+ nd_terminate_link(ei->i_data, inode->i_size,
+ sizeof(ei->i_data));
+ } else {
inode->i_op = &ext4_symlink_inode_operations;
ext4_set_aops(inode);
}
--
1.6.0.4


2008-12-16 23:46:45

by Andreas Dilger

[permalink] [raw]
Subject: Re: [PATCH] vfs: introduce helper function to safely NUL-terminate symlinks

On Dec 16, 2008 15:51 +0000, Duane Griffin wrote:
> A number of filesystems were potentially triggering kernel bugs due to
> corrupted symlink names on disk. This helper helps safely terminate the
> names.
>
> +static inline void nd_terminate_link(void *name,unsigned len,unsigned maxlen)
> +{
> + ((char *) name)[min(len, maxlen)] = '\0';
> +}

> @@ -4200,9 +4201,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
> } else if (S_ISLNK(inode->i_mode)) {
> + if (ext4_inode_is_fast_symlink(inode)) {
> inode->i_op = &ext4_fast_symlink_inode_operations;
> + nd_terminate_link(ei->i_data, inode->i_size,
> + sizeof(ei->i_data));
> + } else {
> inode->i_op = &ext4_symlink_inode_operations;
> ext4_set_aops(inode);
> }

With sizeof(ei->i_data) = 15 * 4 = 60 bytes, this will set ei->i_data[60]
as NUL, which is writing 1 byte beyond the end of the array.

Note that in ext[234]_symlink() the check for fast symlinks is:

l = strlen(symname)+1;
if (l > sizeof (EXT3_I(inode)->i_data)) {
inode->i_op = &ext3_symlink_inode_operations;
} else {
inode->i_op = &ext3_fast_symlink_inode_operations;
inode->i_size = l-1;
}

so in fact the fast symlinks should always have space for a trailing NUL
character, and "sizeof(ei->i_data) - 1" is the right maxlen to use for
ext[234].

That might not be true for other filesystems, in which case you would
need to add a "padding" field after the symlink name in memory to hold
the trailing NUL.

Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.


2008-12-17 00:26:57

by Duane Griffin

[permalink] [raw]
Subject: Re: [PATCH] vfs: introduce helper function to safely NUL-terminate symlinks

2008/12/16 Andreas Dilger <[email protected]>:
> On Dec 16, 2008 15:51 +0000, Duane Griffin wrote:
>> A number of filesystems were potentially triggering kernel bugs due to
>> corrupted symlink names on disk. This helper helps safely terminate the
>> names.
>>
>> +static inline void nd_terminate_link(void *name,unsigned len,unsigned maxlen)
>> +{
>> + ((char *) name)[min(len, maxlen)] = '\0';
>> +}
>
>> @@ -4200,9 +4201,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
>> } else if (S_ISLNK(inode->i_mode)) {
>> + if (ext4_inode_is_fast_symlink(inode)) {
>> inode->i_op = &ext4_fast_symlink_inode_operations;
>> + nd_terminate_link(ei->i_data, inode->i_size,
>> + sizeof(ei->i_data));
>> + } else {
>> inode->i_op = &ext4_symlink_inode_operations;
>> ext4_set_aops(inode);
>> }
>
> With sizeof(ei->i_data) = 15 * 4 = 60 bytes, this will set ei->i_data[60]
> as NUL, which is writing 1 byte beyond the end of the array.

Argh, you are correct, of course.

> Note that in ext[234]_symlink() the check for fast symlinks is:
>
> l = strlen(symname)+1;
> if (l > sizeof (EXT3_I(inode)->i_data)) {
> inode->i_op = &ext3_symlink_inode_operations;
> } else {
> inode->i_op = &ext3_fast_symlink_inode_operations;
> inode->i_size = l-1;
> }
>
> so in fact the fast symlinks should always have space for a trailing NUL
> character, and "sizeof(ei->i_data) - 1" is the right maxlen to use for
> ext[234].
>
> That might not be true for other filesystems, in which case you would
> need to add a "padding" field after the symlink name in memory to hold
> the trailing NUL.

It is true for sysv, too. The ufs code also, but that has other
issues, anyway. The generic page symlink and freevxfs patches should
be fine, though.

Cheers,
Duane.

--
"I never could learn to drink that blood and call it wine" - Bob Dylan

2008-12-19 15:03:52

by Duane Griffin

[permalink] [raw]
Subject: Re: [PATCH] vfs: introduce helper function to safely NUL-terminate symlinks

2008/12/17 Duane Griffin <[email protected]>:
> It is true for sysv, too. The ufs code also, but that has other
> issues, anyway. The generic page symlink and freevxfs patches should
> be fine, though.

Before I fire off another set of patches, should I be sending out the
complete set again or just the ones that need to be updated?

Cheers,
Duane.

--
"I never could learn to drink that blood and call it wine" - Bob Dylan

2008-12-19 19:29:10

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] vfs: introduce helper function to safely NUL-terminate symlinks

On Fri, 19 Dec 2008 15:03:52 +0000
"Duane Griffin" <[email protected]> wrote:

> 2008/12/17 Duane Griffin <[email protected]>:
> > It is true for sysv, too. The ufs code also, but that has other
> > issues, anyway. The generic page symlink and freevxfs patches should
> > be fine, though.
>
> Before I fire off another set of patches, should I be sending out the
> complete set again or just the ones that need to be updated?
>

It's more reliable to resend everything.

2008-12-19 19:43:39

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH] vfs: introduce helper function to safely NUL-terminate symlinks

On Fri, Dec 19, 2008 at 03:03:52PM +0000, Duane Griffin wrote:
> 2008/12/17 Duane Griffin <[email protected]>:
> > It is true for sysv, too. The ufs code also, but that has other
> > issues, anyway. The generic page symlink and freevxfs patches should
> > be fine, though.
>
> Before I fire off another set of patches, should I be sending out the
> complete set again or just the ones that need to be updated?

Complete set, please...