diff options
| -rw-r--r-- | fs/romfs/internal.h | 4 | ||||
| -rw-r--r-- | fs/romfs/storage.c | 67 | ||||
| -rw-r--r-- | fs/romfs/super.c | 4 |
3 files changed, 53 insertions, 22 deletions
diff --git a/fs/romfs/internal.h b/fs/romfs/internal.h index 06044a9dc62d..95217b830118 100644 --- a/fs/romfs/internal.h +++ b/fs/romfs/internal.h | |||
| @@ -43,5 +43,5 @@ extern int romfs_dev_read(struct super_block *sb, unsigned long pos, | |||
| 43 | void *buf, size_t buflen); | 43 | void *buf, size_t buflen); |
| 44 | extern ssize_t romfs_dev_strnlen(struct super_block *sb, | 44 | extern ssize_t romfs_dev_strnlen(struct super_block *sb, |
| 45 | unsigned long pos, size_t maxlen); | 45 | unsigned long pos, size_t maxlen); |
| 46 | extern int romfs_dev_strncmp(struct super_block *sb, unsigned long pos, | 46 | extern int romfs_dev_strcmp(struct super_block *sb, unsigned long pos, |
| 47 | const char *str, size_t size); | 47 | const char *str, size_t size); |
diff --git a/fs/romfs/storage.c b/fs/romfs/storage.c index 7e3e1e12a081..66ce9ddfe504 100644 --- a/fs/romfs/storage.c +++ b/fs/romfs/storage.c | |||
| @@ -67,26 +67,35 @@ static ssize_t romfs_mtd_strnlen(struct super_block *sb, | |||
| 67 | * compare a string to one in a romfs image on MTD | 67 | * compare a string to one in a romfs image on MTD |
| 68 | * - return 1 if matched, 0 if differ, -ve if error | 68 | * - return 1 if matched, 0 if differ, -ve if error |
| 69 | */ | 69 | */ |
| 70 | static int romfs_mtd_strncmp(struct super_block *sb, unsigned long pos, | 70 | static int romfs_mtd_strcmp(struct super_block *sb, unsigned long pos, |
| 71 | const char *str, size_t size) | 71 | const char *str, size_t size) |
| 72 | { | 72 | { |
| 73 | u_char buf[16]; | 73 | u_char buf[17]; |
| 74 | size_t len, segment; | 74 | size_t len, segment; |
| 75 | int ret; | 75 | int ret; |
| 76 | 76 | ||
| 77 | /* scan the string up to 16 bytes at a time */ | 77 | /* scan the string up to 16 bytes at a time, and attempt to grab the |
| 78 | * trailing NUL whilst we're at it */ | ||
| 79 | buf[0] = 0xff; | ||
| 80 | |||
| 78 | while (size > 0) { | 81 | while (size > 0) { |
| 79 | segment = min_t(size_t, size, 16); | 82 | segment = min_t(size_t, size + 1, 17); |
| 80 | ret = ROMFS_MTD_READ(sb, pos, segment, &len, buf); | 83 | ret = ROMFS_MTD_READ(sb, pos, segment, &len, buf); |
| 81 | if (ret < 0) | 84 | if (ret < 0) |
| 82 | return ret; | 85 | return ret; |
| 86 | len--; | ||
| 83 | if (memcmp(buf, str, len) != 0) | 87 | if (memcmp(buf, str, len) != 0) |
| 84 | return 0; | 88 | return 0; |
| 89 | buf[0] = buf[len]; | ||
| 85 | size -= len; | 90 | size -= len; |
| 86 | pos += len; | 91 | pos += len; |
| 87 | str += len; | 92 | str += len; |
| 88 | } | 93 | } |
| 89 | 94 | ||
| 95 | /* check the trailing NUL was */ | ||
| 96 | if (buf[0]) | ||
| 97 | return 0; | ||
| 98 | |||
| 90 | return 1; | 99 | return 1; |
| 91 | } | 100 | } |
| 92 | #endif /* CONFIG_ROMFS_ON_MTD */ | 101 | #endif /* CONFIG_ROMFS_ON_MTD */ |
| @@ -154,28 +163,48 @@ static ssize_t romfs_blk_strnlen(struct super_block *sb, | |||
| 154 | * compare a string to one in a romfs image on a block device | 163 | * compare a string to one in a romfs image on a block device |
| 155 | * - return 1 if matched, 0 if differ, -ve if error | 164 | * - return 1 if matched, 0 if differ, -ve if error |
| 156 | */ | 165 | */ |
| 157 | static int romfs_blk_strncmp(struct super_block *sb, unsigned long pos, | 166 | static int romfs_blk_strcmp(struct super_block *sb, unsigned long pos, |
| 158 | const char *str, size_t size) | 167 | const char *str, size_t size) |
| 159 | { | 168 | { |
| 160 | struct buffer_head *bh; | 169 | struct buffer_head *bh; |
| 161 | unsigned long offset; | 170 | unsigned long offset; |
| 162 | size_t segment; | 171 | size_t segment; |
| 163 | bool x; | 172 | bool matched, terminated = false; |
| 164 | 173 | ||
| 165 | /* scan the string up to 16 bytes at a time */ | 174 | /* compare string up to a block at a time */ |
| 166 | while (size > 0) { | 175 | while (size > 0) { |
| 167 | offset = pos & (ROMBSIZE - 1); | 176 | offset = pos & (ROMBSIZE - 1); |
| 168 | segment = min_t(size_t, size, ROMBSIZE - offset); | 177 | segment = min_t(size_t, size, ROMBSIZE - offset); |
| 169 | bh = sb_bread(sb, pos >> ROMBSBITS); | 178 | bh = sb_bread(sb, pos >> ROMBSBITS); |
| 170 | if (!bh) | 179 | if (!bh) |
| 171 | return -EIO; | 180 | return -EIO; |
| 172 | x = (memcmp(bh->b_data + offset, str, segment) != 0); | 181 | matched = (memcmp(bh->b_data + offset, str, segment) == 0); |
| 173 | brelse(bh); | 182 | |
| 174 | if (x) | ||
| 175 | return 0; | ||
| 176 | size -= segment; | 183 | size -= segment; |
| 177 | pos += segment; | 184 | pos += segment; |
| 178 | str += segment; | 185 | str += segment; |
| 186 | if (matched && size == 0 && offset + segment < ROMBSIZE) { | ||
| 187 | if (!bh->b_data[offset + segment]) | ||
| 188 | terminated = true; | ||
| 189 | else | ||
| 190 | matched = false; | ||
| 191 | } | ||
| 192 | brelse(bh); | ||
| 193 | if (!matched) | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | if (!terminated) { | ||
| 198 | /* the terminating NUL must be on the first byte of the next | ||
| 199 | * block */ | ||
| 200 | BUG_ON((pos & (ROMBSIZE - 1)) != 0); | ||
| 201 | bh = sb_bread(sb, pos >> ROMBSBITS); | ||
| 202 | if (!bh) | ||
| 203 | return -EIO; | ||
| 204 | matched = !bh->b_data[0]; | ||
| 205 | brelse(bh); | ||
| 206 | if (!matched) | ||
| 207 | return 0; | ||
| 179 | } | 208 | } |
| 180 | 209 | ||
| 181 | return 1; | 210 | return 1; |
| @@ -234,10 +263,12 @@ ssize_t romfs_dev_strnlen(struct super_block *sb, | |||
| 234 | 263 | ||
| 235 | /* | 264 | /* |
| 236 | * compare a string to one in romfs | 265 | * compare a string to one in romfs |
| 266 | * - the string to be compared to, str, may not be NUL-terminated; instead the | ||
| 267 | * string is of the specified size | ||
| 237 | * - return 1 if matched, 0 if differ, -ve if error | 268 | * - return 1 if matched, 0 if differ, -ve if error |
| 238 | */ | 269 | */ |
| 239 | int romfs_dev_strncmp(struct super_block *sb, unsigned long pos, | 270 | int romfs_dev_strcmp(struct super_block *sb, unsigned long pos, |
| 240 | const char *str, size_t size) | 271 | const char *str, size_t size) |
| 241 | { | 272 | { |
| 242 | size_t limit; | 273 | size_t limit; |
| 243 | 274 | ||
| @@ -246,16 +277,16 @@ int romfs_dev_strncmp(struct super_block *sb, unsigned long pos, | |||
| 246 | return -EIO; | 277 | return -EIO; |
| 247 | if (size > ROMFS_MAXFN) | 278 | if (size > ROMFS_MAXFN) |
| 248 | return -ENAMETOOLONG; | 279 | return -ENAMETOOLONG; |
| 249 | if (size > limit - pos) | 280 | if (size + 1 > limit - pos) |
| 250 | return -EIO; | 281 | return -EIO; |
| 251 | 282 | ||
| 252 | #ifdef CONFIG_ROMFS_ON_MTD | 283 | #ifdef CONFIG_ROMFS_ON_MTD |
| 253 | if (sb->s_mtd) | 284 | if (sb->s_mtd) |
| 254 | return romfs_mtd_strncmp(sb, pos, str, size); | 285 | return romfs_mtd_strcmp(sb, pos, str, size); |
| 255 | #endif | 286 | #endif |
| 256 | #ifdef CONFIG_ROMFS_ON_BLOCK | 287 | #ifdef CONFIG_ROMFS_ON_BLOCK |
| 257 | if (sb->s_bdev) | 288 | if (sb->s_bdev) |
| 258 | return romfs_blk_strncmp(sb, pos, str, size); | 289 | return romfs_blk_strcmp(sb, pos, str, size); |
| 259 | #endif | 290 | #endif |
| 260 | return -EIO; | 291 | return -EIO; |
| 261 | } | 292 | } |
diff --git a/fs/romfs/super.c b/fs/romfs/super.c index 10ca7d984a8b..c53b5ef8a02f 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c | |||
| @@ -240,8 +240,8 @@ static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 240 | goto error; | 240 | goto error; |
| 241 | 241 | ||
| 242 | /* try to match the first 16 bytes of name */ | 242 | /* try to match the first 16 bytes of name */ |
| 243 | ret = romfs_dev_strncmp(dir->i_sb, offset + ROMFH_SIZE, name, | 243 | ret = romfs_dev_strcmp(dir->i_sb, offset + ROMFH_SIZE, name, |
| 244 | len); | 244 | len); |
| 245 | if (ret < 0) | 245 | if (ret < 0) |
| 246 | goto error; | 246 | goto error; |
| 247 | if (ret == 1) | 247 | if (ret == 1) |
