diff options
| author | Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz> | 2011-05-08 14:44:32 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-09 12:04:24 -0400 |
| commit | d0969d1949cc67a0f100f30ad69ec7ec1eca70d2 (patch) | |
| tree | 70b04ebba74aff1c4df3e8cc213a7be721550fe8 | |
| parent | 0b69760be6968c528869d4aec95ecf64dbf3e8bd (diff) | |
HPFS: Fix some unaligned accesses
Fix some unaligned accesses
Signed-off-by: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | fs/hpfs/ea.c | 41 | ||||
| -rw-r--r-- | fs/hpfs/hpfs.h | 3 | ||||
| -rw-r--r-- | fs/hpfs/hpfs_fn.h | 12 |
3 files changed, 32 insertions, 24 deletions
diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c index 1bbc37ddff40..7f1d90ca5eeb 100644 --- a/fs/hpfs/ea.c +++ b/fs/hpfs/ea.c | |||
| @@ -24,7 +24,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len) | |||
| 24 | } | 24 | } |
| 25 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; | 25 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; |
| 26 | if (ea->indirect) { | 26 | if (ea->indirect) { |
| 27 | if (le16_to_cpu(ea->valuelen) != 8) { | 27 | if (ea_valuelen(ea) != 8) { |
| 28 | hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x", | 28 | hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x", |
| 29 | ano ? "anode" : "sectors", a, pos); | 29 | ano ? "anode" : "sectors", a, pos); |
| 30 | return; | 30 | return; |
| @@ -33,7 +33,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len) | |||
| 33 | return; | 33 | return; |
| 34 | hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); | 34 | hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); |
| 35 | } | 35 | } |
| 36 | pos += ea->namelen + le16_to_cpu(ea->valuelen) + 5; | 36 | pos += ea->namelen + ea_valuelen(ea) + 5; |
| 37 | } | 37 | } |
| 38 | if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9); | 38 | if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9); |
| 39 | else { | 39 | else { |
| @@ -82,10 +82,10 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, | |||
| 82 | if (!strcmp(ea->name, key)) { | 82 | if (!strcmp(ea->name, key)) { |
| 83 | if (ea->indirect) | 83 | if (ea->indirect) |
| 84 | goto indirect; | 84 | goto indirect; |
| 85 | if (le16_to_cpu(ea->valuelen) >= size) | 85 | if (ea_valuelen(ea) >= size) |
| 86 | return -EINVAL; | 86 | return -EINVAL; |
| 87 | memcpy(buf, ea_data(ea), le16_to_cpu(ea->valuelen)); | 87 | memcpy(buf, ea_data(ea), ea_valuelen(ea)); |
| 88 | buf[le16_to_cpu(ea->valuelen)] = 0; | 88 | buf[ea_valuelen(ea)] = 0; |
| 89 | return 0; | 89 | return 0; |
| 90 | } | 90 | } |
| 91 | a = le32_to_cpu(fnode->ea_secno); | 91 | a = le32_to_cpu(fnode->ea_secno); |
| @@ -106,14 +106,14 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, | |||
| 106 | if (!strcmp(ea->name, key)) { | 106 | if (!strcmp(ea->name, key)) { |
| 107 | if (ea->indirect) | 107 | if (ea->indirect) |
| 108 | goto indirect; | 108 | goto indirect; |
| 109 | if (le16_to_cpu(ea->valuelen) >= size) | 109 | if (ea_valuelen(ea) >= size) |
| 110 | return -EINVAL; | 110 | return -EINVAL; |
| 111 | if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, le16_to_cpu(ea->valuelen), buf)) | 111 | if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), buf)) |
| 112 | return -EIO; | 112 | return -EIO; |
| 113 | buf[le16_to_cpu(ea->valuelen)] = 0; | 113 | buf[ea_valuelen(ea)] = 0; |
| 114 | return 0; | 114 | return 0; |
| 115 | } | 115 | } |
| 116 | pos += ea->namelen + le16_to_cpu(ea->valuelen) + 5; | 116 | pos += ea->namelen + ea_valuelen(ea) + 5; |
| 117 | } | 117 | } |
| 118 | return -ENOENT; | 118 | return -ENOENT; |
| 119 | indirect: | 119 | indirect: |
| @@ -138,12 +138,12 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si | |||
| 138 | if (!strcmp(ea->name, key)) { | 138 | if (!strcmp(ea->name, key)) { |
| 139 | if (ea->indirect) | 139 | if (ea->indirect) |
| 140 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); | 140 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); |
| 141 | if (!(ret = kmalloc((*size = le16_to_cpu(ea->valuelen)) + 1, GFP_NOFS))) { | 141 | if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { |
| 142 | printk("HPFS: out of memory for EA\n"); | 142 | printk("HPFS: out of memory for EA\n"); |
| 143 | return NULL; | 143 | return NULL; |
| 144 | } | 144 | } |
| 145 | memcpy(ret, ea_data(ea), le16_to_cpu(ea->valuelen)); | 145 | memcpy(ret, ea_data(ea), ea_valuelen(ea)); |
| 146 | ret[le16_to_cpu(ea->valuelen)] = 0; | 146 | ret[ea_valuelen(ea)] = 0; |
| 147 | return ret; | 147 | return ret; |
| 148 | } | 148 | } |
| 149 | a = le32_to_cpu(fnode->ea_secno); | 149 | a = le32_to_cpu(fnode->ea_secno); |
| @@ -164,18 +164,18 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si | |||
| 164 | if (!strcmp(ea->name, key)) { | 164 | if (!strcmp(ea->name, key)) { |
| 165 | if (ea->indirect) | 165 | if (ea->indirect) |
| 166 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); | 166 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); |
| 167 | if (!(ret = kmalloc((*size = le16_to_cpu(ea->valuelen)) + 1, GFP_NOFS))) { | 167 | if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { |
| 168 | printk("HPFS: out of memory for EA\n"); | 168 | printk("HPFS: out of memory for EA\n"); |
| 169 | return NULL; | 169 | return NULL; |
| 170 | } | 170 | } |
| 171 | if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, le16_to_cpu(ea->valuelen), ret)) { | 171 | if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), ret)) { |
| 172 | kfree(ret); | 172 | kfree(ret); |
| 173 | return NULL; | 173 | return NULL; |
| 174 | } | 174 | } |
| 175 | ret[le16_to_cpu(ea->valuelen)] = 0; | 175 | ret[ea_valuelen(ea)] = 0; |
| 176 | return ret; | 176 | return ret; |
| 177 | } | 177 | } |
| 178 | pos += ea->namelen + le16_to_cpu(ea->valuelen) + 5; | 178 | pos += ea->namelen + ea_valuelen(ea) + 5; |
| 179 | } | 179 | } |
| 180 | return NULL; | 180 | return NULL; |
| 181 | } | 181 | } |
| @@ -202,7 +202,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 202 | if (ea->indirect) { | 202 | if (ea->indirect) { |
| 203 | if (ea_len(ea) == size) | 203 | if (ea_len(ea) == size) |
| 204 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); | 204 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); |
| 205 | } else if (le16_to_cpu(ea->valuelen) == size) { | 205 | } else if (ea_valuelen(ea) == size) { |
| 206 | memcpy(ea_data(ea), data, size); | 206 | memcpy(ea_data(ea), data, size); |
| 207 | } | 207 | } |
| 208 | return; | 208 | return; |
| @@ -228,12 +228,12 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 228 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); | 228 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); |
| 229 | } | 229 | } |
| 230 | else { | 230 | else { |
| 231 | if (le16_to_cpu(ea->valuelen) == size) | 231 | if (ea_valuelen(ea) == size) |
| 232 | hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data); | 232 | hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data); |
| 233 | } | 233 | } |
| 234 | return; | 234 | return; |
| 235 | } | 235 | } |
| 236 | pos += ea->namelen + le16_to_cpu(ea->valuelen) + 5; | 236 | pos += ea->namelen + ea_valuelen(ea) + 5; |
| 237 | } | 237 | } |
| 238 | if (!le16_to_cpu(fnode->ea_offs)) { | 238 | if (!le16_to_cpu(fnode->ea_offs)) { |
| 239 | /*if (le16_to_cpu(fnode->ea_size_s)) { | 239 | /*if (le16_to_cpu(fnode->ea_size_s)) { |
| @@ -254,7 +254,8 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 254 | ea = fnode_end_ea(fnode); | 254 | ea = fnode_end_ea(fnode); |
| 255 | *(char *)ea = 0; | 255 | *(char *)ea = 0; |
| 256 | ea->namelen = strlen(key); | 256 | ea->namelen = strlen(key); |
| 257 | ea->valuelen = cpu_to_le16(size); | 257 | ea->valuelen_lo = size; |
| 258 | ea->valuelen_hi = size >> 8; | ||
| 258 | strcpy(ea->name, key); | 259 | strcpy(ea->name, key); |
| 259 | memcpy(ea_data(ea), data, size); | 260 | memcpy(ea_data(ea), data, size); |
| 260 | fnode->ea_size_s = cpu_to_le16(le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5); | 261 | fnode->ea_size_s = cpu_to_le16(le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5); |
diff --git a/fs/hpfs/hpfs.h b/fs/hpfs/hpfs.h index 91a6223893f9..8b0650aae328 100644 --- a/fs/hpfs/hpfs.h +++ b/fs/hpfs/hpfs.h | |||
| @@ -546,7 +546,8 @@ struct extended_attribute | |||
| 546 | where real value starts */ | 546 | where real value starts */ |
| 547 | #endif | 547 | #endif |
| 548 | u8 namelen; /* length of name, bytes */ | 548 | u8 namelen; /* length of name, bytes */ |
| 549 | u16 valuelen; /* length of value, bytes */ | 549 | u8 valuelen_lo; /* length of value, bytes */ |
| 550 | u8 valuelen_hi; /* length of value, bytes */ | ||
| 550 | u8 name[0]; | 551 | u8 name[0]; |
| 551 | /* | 552 | /* |
| 552 | u8 name[namelen]; ascii attrib name | 553 | u8 name[namelen]; ascii attrib name |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index f99377306b13..dd552f862c8f 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/pagemap.h> | 13 | #include <linux/pagemap.h> |
| 14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <asm/unaligned.h> | ||
| 16 | 17 | ||
| 17 | #include "hpfs.h" | 18 | #include "hpfs.h" |
| 18 | 19 | ||
| @@ -135,19 +136,24 @@ static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode) | |||
| 135 | return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s)); | 136 | return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s)); |
| 136 | } | 137 | } |
| 137 | 138 | ||
| 139 | static unsigned ea_valuelen(struct extended_attribute *ea) | ||
| 140 | { | ||
| 141 | return ea->valuelen_lo + 256 * ea->valuelen_hi; | ||
| 142 | } | ||
| 143 | |||
| 138 | static inline struct extended_attribute *next_ea(struct extended_attribute *ea) | 144 | static inline struct extended_attribute *next_ea(struct extended_attribute *ea) |
| 139 | { | 145 | { |
| 140 | return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + le16_to_cpu(ea->valuelen)); | 146 | return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea_valuelen(ea)); |
| 141 | } | 147 | } |
| 142 | 148 | ||
| 143 | static inline secno ea_sec(struct extended_attribute *ea) | 149 | static inline secno ea_sec(struct extended_attribute *ea) |
| 144 | { | 150 | { |
| 145 | return le32_to_cpu(*((secno *)((char *)ea + 9 + ea->namelen))); | 151 | return le32_to_cpu(get_unaligned((secno *)((char *)ea + 9 + ea->namelen))); |
| 146 | } | 152 | } |
| 147 | 153 | ||
| 148 | static inline secno ea_len(struct extended_attribute *ea) | 154 | static inline secno ea_len(struct extended_attribute *ea) |
| 149 | { | 155 | { |
| 150 | return le32_to_cpu(*((secno *)((char *)ea + 5 + ea->namelen))); | 156 | return le32_to_cpu(get_unaligned((secno *)((char *)ea + 5 + ea->namelen))); |
| 151 | } | 157 | } |
| 152 | 158 | ||
| 153 | static inline char *ea_data(struct extended_attribute *ea) | 159 | static inline char *ea_data(struct extended_attribute *ea) |
