Commit 414b44ba authored by Doug Graham's avatar Doug Graham Committed by James Toy

There are a few places in the Minix FS code where the "inode" field of a

minix_dir_entry is used without checking first to see if the dirent is
really a minix3_dir_entry.  The inode number in a V1/V2 dirent is 16 bits,
whereas that in a V3 dirent is 32 bits.

Accessing it as a 16 bit field when it really should be accessed as a 32
bit field probably kinda sorta works on a little-endian machine, but leads
to some rather odd behaviour on big-endian machines.
Signed-off-by: default avatarDoug Graham <dgraham@nortel.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 5d575171
...@@ -308,13 +308,17 @@ int minix_delete_entry(struct minix_dir_entry *de, struct page *page) ...@@ -308,13 +308,17 @@ int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
struct inode *inode = (struct inode*)mapping->host; struct inode *inode = (struct inode*)mapping->host;
char *kaddr = page_address(page); char *kaddr = page_address(page);
loff_t pos = page_offset(page) + (char*)de - kaddr; loff_t pos = page_offset(page) + (char*)de - kaddr;
unsigned len = minix_sb(inode->i_sb)->s_dirsize; struct minix_sb_info *sbi = minix_sb(inode->i_sb);
unsigned len = sbi->s_dirsize;
int err; int err;
lock_page(page); lock_page(page);
err = __minix_write_begin(NULL, mapping, pos, len, err = __minix_write_begin(NULL, mapping, pos, len,
AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err == 0) { if (err == 0) {
if (sbi->s_version == MINIX_V3)
((minix3_dirent *) de)->inode = 0;
else
de->inode = 0; de->inode = 0;
err = dir_commit_chunk(page, pos, len); err = dir_commit_chunk(page, pos, len);
} else { } else {
...@@ -440,6 +444,9 @@ void minix_set_link(struct minix_dir_entry *de, struct page *page, ...@@ -440,6 +444,9 @@ void minix_set_link(struct minix_dir_entry *de, struct page *page,
err = __minix_write_begin(NULL, mapping, pos, sbi->s_dirsize, err = __minix_write_begin(NULL, mapping, pos, sbi->s_dirsize,
AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (err == 0) { if (err == 0) {
if (sbi->s_version == MINIX_V3)
((minix3_dirent *) de)->inode = inode->i_ino;
else
de->inode = inode->i_ino; de->inode = inode->i_ino;
err = dir_commit_chunk(page, pos, sbi->s_dirsize); err = dir_commit_chunk(page, pos, sbi->s_dirsize);
} else { } else {
...@@ -470,6 +477,13 @@ ino_t minix_inode_by_name(struct dentry *dentry) ...@@ -470,6 +477,13 @@ ino_t minix_inode_by_name(struct dentry *dentry)
ino_t res = 0; ino_t res = 0;
if (de) { if (de) {
struct address_space *mapping = page->mapping;
struct inode *inode = (struct inode*)mapping->host;
struct minix_sb_info *sbi = minix_sb(inode->i_sb);
if (sbi->s_version == MINIX_V3)
res = ((minix3_dirent *) de)->inode;
else
res = de->inode; res = de->inode;
dir_put_page(page); dir_put_page(page);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment