aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Schermerhorn <Lee.Schermerhorn@hp.com>2007-07-16 02:40:54 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 12:05:46 -0400
commitb4c07bce796833401317519e44075889c5fd4d5f (patch)
tree569448b0cc6e0eb1516e38c98bc770ad73308880
parente73a75fa7f062b52d015f1c961685dcaac57f710 (diff)
hugetlbfs: handle empty options string
I was seeing a null pointer deref in fs/super.c:vfs_kern_mount(). Some file system get_sb() handler was returning NULL mnt_sb with a non-negative return value. I also noticed a "hugetlbfs: Bad mount option:" message in the log. Turns out that hugetlbfs_parse_options() was not checking for an empty option string after call to strsep(). On failure, hugetlbfs_parse_options() returns 1. hugetlbfs_fill_super() just passed this return code back up the call stack where vfs_kern_mount() missed the error and proceeded with a NULL mnt_sb. Apparently introduced by patch: hugetlbfs-use-lib-parser-fix-docs.patch The problem was exposed by this line in my fstab: none /huge hugetlbfs defaults 0 0 It can also be demonstrated by invoking mount of hugetlbfs directly with no options or a bogus option. This patch: 1) adds the check for empty option to hugetlbfs_parse_options(), 2) enhances the error message to bracket any unrecognized option with quotes , 3) modifies hugetlbfs_parse_options() to return -EINVAL on any unrecognized option, 4) adds a BUG_ON() to vfs_kern_mount() to catch any get_sb() handler that returns a NULL mnt->mnt_sb with a return value >= 0. Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com> Acked-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/hugetlbfs/inode.c8
-rw-r--r--fs/super.c1
2 files changed, 6 insertions, 3 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 711b801fbcdf..d145cb79c30a 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -621,6 +621,8 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
621 621
622 while ((p = strsep(&options, ",")) != NULL) { 622 while ((p = strsep(&options, ",")) != NULL) {
623 int token; 623 int token;
624 if (!*p)
625 continue;
624 626
625 token = match_token(p, tokens, args); 627 token = match_token(p, tokens, args);
626 switch (token) { 628 switch (token) {
@@ -665,8 +667,9 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
665 break; 667 break;
666 668
667 default: 669 default:
668 printk(KERN_ERR "hugetlbfs: Bad mount option: %s\n", p); 670 printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
669 return 1; 671 p);
672 return -EINVAL;
670 break; 673 break;
671 } 674 }
672 } 675 }
@@ -693,7 +696,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
693 config.gid = current->fsgid; 696 config.gid = current->fsgid;
694 config.mode = 0755; 697 config.mode = 0755;
695 ret = hugetlbfs_parse_options(data, &config); 698 ret = hugetlbfs_parse_options(data, &config);
696
697 if (ret) 699 if (ret)
698 return ret; 700 return ret;
699 701
diff --git a/fs/super.c b/fs/super.c
index 5260d620c555..fc8ebedc6bed 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -884,6 +884,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
884 error = type->get_sb(type, flags, name, data, mnt); 884 error = type->get_sb(type, flags, name, data, mnt);
885 if (error < 0) 885 if (error < 0)
886 goto out_free_secdata; 886 goto out_free_secdata;
887 BUG_ON(!mnt->mnt_sb);
887 888
888 error = security_sb_kern_mount(mnt->mnt_sb, secdata); 889 error = security_sb_kern_mount(mnt->mnt_sb, secdata);
889 if (error) 890 if (error)