diff options
Diffstat (limited to 'fs/affs/super.c')
| -rw-r--r-- | fs/affs/super.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/fs/affs/super.c b/fs/affs/super.c index 104fdcb3a7fc..d41e9673cd97 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
| @@ -203,7 +203,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s | |||
| 203 | switch (token) { | 203 | switch (token) { |
| 204 | case Opt_bs: | 204 | case Opt_bs: |
| 205 | if (match_int(&args[0], &n)) | 205 | if (match_int(&args[0], &n)) |
| 206 | return -EINVAL; | 206 | return 0; |
| 207 | if (n != 512 && n != 1024 && n != 2048 | 207 | if (n != 512 && n != 1024 && n != 2048 |
| 208 | && n != 4096) { | 208 | && n != 4096) { |
| 209 | printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); | 209 | printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); |
| @@ -213,7 +213,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s | |||
| 213 | break; | 213 | break; |
| 214 | case Opt_mode: | 214 | case Opt_mode: |
| 215 | if (match_octal(&args[0], &option)) | 215 | if (match_octal(&args[0], &option)) |
| 216 | return 1; | 216 | return 0; |
| 217 | *mode = option & 0777; | 217 | *mode = option & 0777; |
| 218 | *mount_opts |= SF_SETMODE; | 218 | *mount_opts |= SF_SETMODE; |
| 219 | break; | 219 | break; |
| @@ -221,8 +221,6 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s | |||
| 221 | *mount_opts |= SF_MUFS; | 221 | *mount_opts |= SF_MUFS; |
| 222 | break; | 222 | break; |
| 223 | case Opt_prefix: | 223 | case Opt_prefix: |
| 224 | /* Free any previous prefix */ | ||
| 225 | kfree(*prefix); | ||
| 226 | *prefix = match_strdup(&args[0]); | 224 | *prefix = match_strdup(&args[0]); |
| 227 | if (!*prefix) | 225 | if (!*prefix) |
| 228 | return 0; | 226 | return 0; |
| @@ -233,21 +231,21 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s | |||
| 233 | break; | 231 | break; |
| 234 | case Opt_reserved: | 232 | case Opt_reserved: |
| 235 | if (match_int(&args[0], reserved)) | 233 | if (match_int(&args[0], reserved)) |
| 236 | return 1; | 234 | return 0; |
| 237 | break; | 235 | break; |
| 238 | case Opt_root: | 236 | case Opt_root: |
| 239 | if (match_int(&args[0], root)) | 237 | if (match_int(&args[0], root)) |
| 240 | return 1; | 238 | return 0; |
| 241 | break; | 239 | break; |
| 242 | case Opt_setgid: | 240 | case Opt_setgid: |
| 243 | if (match_int(&args[0], &option)) | 241 | if (match_int(&args[0], &option)) |
| 244 | return 1; | 242 | return 0; |
| 245 | *gid = option; | 243 | *gid = option; |
| 246 | *mount_opts |= SF_SETGID; | 244 | *mount_opts |= SF_SETGID; |
| 247 | break; | 245 | break; |
| 248 | case Opt_setuid: | 246 | case Opt_setuid: |
| 249 | if (match_int(&args[0], &option)) | 247 | if (match_int(&args[0], &option)) |
| 250 | return -EINVAL; | 248 | return 0; |
| 251 | *uid = option; | 249 | *uid = option; |
| 252 | *mount_opts |= SF_SETUID; | 250 | *mount_opts |= SF_SETUID; |
| 253 | break; | 251 | break; |
| @@ -311,11 +309,14 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 311 | return -ENOMEM; | 309 | return -ENOMEM; |
| 312 | sb->s_fs_info = sbi; | 310 | sb->s_fs_info = sbi; |
| 313 | mutex_init(&sbi->s_bmlock); | 311 | mutex_init(&sbi->s_bmlock); |
| 312 | spin_lock_init(&sbi->symlink_lock); | ||
| 314 | 313 | ||
| 315 | if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, | 314 | if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, |
| 316 | &blocksize,&sbi->s_prefix, | 315 | &blocksize,&sbi->s_prefix, |
| 317 | sbi->s_volume, &mount_flags)) { | 316 | sbi->s_volume, &mount_flags)) { |
| 318 | printk(KERN_ERR "AFFS: Error parsing options\n"); | 317 | printk(KERN_ERR "AFFS: Error parsing options\n"); |
| 318 | kfree(sbi->s_prefix); | ||
| 319 | kfree(sbi); | ||
| 319 | return -EINVAL; | 320 | return -EINVAL; |
| 320 | } | 321 | } |
| 321 | /* N.B. after this point s_prefix must be released */ | 322 | /* N.B. after this point s_prefix must be released */ |
| @@ -516,14 +517,18 @@ affs_remount(struct super_block *sb, int *flags, char *data) | |||
| 516 | unsigned long mount_flags; | 517 | unsigned long mount_flags; |
| 517 | int res = 0; | 518 | int res = 0; |
| 518 | char *new_opts = kstrdup(data, GFP_KERNEL); | 519 | char *new_opts = kstrdup(data, GFP_KERNEL); |
| 520 | char volume[32]; | ||
| 521 | char *prefix = NULL; | ||
| 519 | 522 | ||
| 520 | pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data); | 523 | pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data); |
| 521 | 524 | ||
| 522 | *flags |= MS_NODIRATIME; | 525 | *flags |= MS_NODIRATIME; |
| 523 | 526 | ||
| 527 | memcpy(volume, sbi->s_volume, 32); | ||
| 524 | if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block, | 528 | if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block, |
| 525 | &blocksize, &sbi->s_prefix, sbi->s_volume, | 529 | &blocksize, &prefix, volume, |
| 526 | &mount_flags)) { | 530 | &mount_flags)) { |
| 531 | kfree(prefix); | ||
| 527 | kfree(new_opts); | 532 | kfree(new_opts); |
| 528 | return -EINVAL; | 533 | return -EINVAL; |
| 529 | } | 534 | } |
| @@ -534,6 +539,14 @@ affs_remount(struct super_block *sb, int *flags, char *data) | |||
| 534 | sbi->s_mode = mode; | 539 | sbi->s_mode = mode; |
| 535 | sbi->s_uid = uid; | 540 | sbi->s_uid = uid; |
| 536 | sbi->s_gid = gid; | 541 | sbi->s_gid = gid; |
| 542 | /* protect against readers */ | ||
| 543 | spin_lock(&sbi->symlink_lock); | ||
| 544 | if (prefix) { | ||
| 545 | kfree(sbi->s_prefix); | ||
| 546 | sbi->s_prefix = prefix; | ||
| 547 | } | ||
| 548 | memcpy(sbi->s_volume, volume, 32); | ||
| 549 | spin_unlock(&sbi->symlink_lock); | ||
| 537 | 550 | ||
| 538 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { | 551 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { |
| 539 | unlock_kernel(); | 552 | unlock_kernel(); |
