Commit b4c07bce authored by Lee Schermerhorn's avatar Lee Schermerhorn Committed by Linus Torvalds

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: default avatarLee Schermerhorn <lee.schermerhorn@hp.com>
Acked-by: default avatarRandy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e73a75fa
...@@ -621,6 +621,8 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) ...@@ -621,6 +621,8 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
while ((p = strsep(&options, ",")) != NULL) { while ((p = strsep(&options, ",")) != NULL) {
int token; int token;
if (!*p)
continue;
token = match_token(p, tokens, args); token = match_token(p, tokens, args);
switch (token) { switch (token) {
...@@ -665,8 +667,9 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) ...@@ -665,8 +667,9 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
break; break;
default: default:
printk(KERN_ERR "hugetlbfs: Bad mount option: %s\n", p); printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
return 1; p);
return -EINVAL;
break; break;
} }
} }
...@@ -693,7 +696,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -693,7 +696,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
config.gid = current->fsgid; config.gid = current->fsgid;
config.mode = 0755; config.mode = 0755;
ret = hugetlbfs_parse_options(data, &config); ret = hugetlbfs_parse_options(data, &config);
if (ret) if (ret)
return ret; return ret;
......
...@@ -884,6 +884,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void ...@@ -884,6 +884,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
error = type->get_sb(type, flags, name, data, mnt); error = type->get_sb(type, flags, name, data, mnt);
if (error < 0) if (error < 0)
goto out_free_secdata; goto out_free_secdata;
BUG_ON(!mnt->mnt_sb);
error = security_sb_kern_mount(mnt->mnt_sb, secdata); error = security_sb_kern_mount(mnt->mnt_sb, secdata);
if (error) if (error)
......
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