Commit 21547ea6 authored by Nathan Scott's avatar Nathan Scott

[XFS] Fix an oversight in the mount option parsing code which would result in

a kernel panic on certain option strings.

SGI Modid: 2.5.x-xfs:slinx:130571a
parent 32e71bf0
...@@ -113,13 +113,9 @@ xfs_parseargs( ...@@ -113,13 +113,9 @@ xfs_parseargs(
struct xfs_mount_args *args) struct xfs_mount_args *args)
{ {
char *this_char, *value, *eov; char *this_char, *value, *eov;
int logbufs = -1;
int logbufsize = -1;
int dsunit, dswidth, vol_dsunit, vol_dswidth; int dsunit, dswidth, vol_dsunit, vol_dswidth;
int logbufs, logbufsize;
int iosize; int iosize;
int rval = 1; /* failure is default */
iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;
/* Default to 32 bit inodes on linux all the time */ /* Default to 32 bit inodes on linux all the time */
args->flags |= XFSMNT_32BITINODES; args->flags |= XFSMNT_32BITINODES;
...@@ -129,11 +125,13 @@ xfs_parseargs( ...@@ -129,11 +125,13 @@ xfs_parseargs(
args->flags |= XFSMNT_NOATIME; args->flags |= XFSMNT_NOATIME;
if (!options) { if (!options) {
args->logbufs = logbufs; args->logbufs = args->logbufsize = -1;
args->logbufsize = logbufsize;
return 0; return 0;
} }
logbufs = logbufsize = -1;
iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;
while ((this_char = strsep(&options, ",")) != NULL) { while ((this_char = strsep(&options, ",")) != NULL) {
if (!*this_char) if (!*this_char)
continue; continue;
...@@ -141,10 +139,20 @@ xfs_parseargs( ...@@ -141,10 +139,20 @@ xfs_parseargs(
*value++ = 0; *value++ = 0;
if (!strcmp(this_char, MNTOPT_LOGBUFS)) { if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
MNTOPT_LOGBUFS);
return -EINVAL;
}
logbufs = simple_strtoul(value, &eov, 10); logbufs = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
int in_kilobytes = 0; int in_kilobytes = 0;
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
MNTOPT_LOGBSIZE);
return -EINVAL;
}
if (toupper(value[strlen(value)-1]) == 'K') { if (toupper(value[strlen(value)-1]) == 'K') {
in_kilobytes = 1; in_kilobytes = 1;
value[strlen(value)-1] = '\0'; value[strlen(value)-1] = '\0';
...@@ -153,8 +161,18 @@ xfs_parseargs( ...@@ -153,8 +161,18 @@ xfs_parseargs(
if (in_kilobytes) if (in_kilobytes)
logbufsize = logbufsize * 1024; logbufsize = logbufsize * 1024;
} else if (!strcmp(this_char, MNTOPT_LOGDEV)) { } else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
MNTOPT_LOGDEV);
return -EINVAL;
}
strncpy(args->logname, value, MAXNAMELEN); strncpy(args->logname, value, MAXNAMELEN);
} else if (!strcmp(this_char, MNTOPT_MTPT)) { } else if (!strcmp(this_char, MNTOPT_MTPT)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
MNTOPT_MTPT);
return -EINVAL;
}
strncpy(args->mtpt, value, MAXNAMELEN); strncpy(args->mtpt, value, MAXNAMELEN);
#if CONFIG_XFS_DMAPI #if CONFIG_XFS_DMAPI
} else if (!strcmp(this_char, MNTOPT_DMAPI)) { } else if (!strcmp(this_char, MNTOPT_DMAPI)) {
...@@ -168,8 +186,18 @@ xfs_parseargs( ...@@ -168,8 +186,18 @@ xfs_parseargs(
return rval; return rval;
#endif #endif
} else if (!strcmp(this_char, MNTOPT_RTDEV)) { } else if (!strcmp(this_char, MNTOPT_RTDEV)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
MNTOPT_RTDEV);
return -EINVAL;
}
strncpy(args->rtname, value, MAXNAMELEN); strncpy(args->rtname, value, MAXNAMELEN);
} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
MNTOPT_BIOSIZE);
return -EINVAL;
}
iosize = simple_strtoul(value, &eov, 10); iosize = simple_strtoul(value, &eov, 10);
args->flags |= XFSMNT_IOSIZE; args->flags |= XFSMNT_IOSIZE;
args->iosizelog = (uint8_t) iosize; args->iosizelog = (uint8_t) iosize;
...@@ -183,8 +211,9 @@ xfs_parseargs( ...@@ -183,8 +211,9 @@ xfs_parseargs(
#ifdef XFS_BIG_FILESYSTEMS #ifdef XFS_BIG_FILESYSTEMS
args->flags |= XFSMNT_INO64; args->flags |= XFSMNT_INO64;
#else #else
printk("XFS: ino64 option not allowed on this system\n"); printk("XFS: %s option not allowed on this system\n",
return rval; MNTOPT_INO64);
return -EINVAL;
#endif #endif
} else if (!strcmp(this_char, MNTOPT_UQUOTA)) { } else if (!strcmp(this_char, MNTOPT_UQUOTA)) {
args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF; args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
...@@ -204,8 +233,18 @@ xfs_parseargs( ...@@ -204,8 +233,18 @@ xfs_parseargs(
} else if (!strcmp(this_char, MNTOPT_NOALIGN)) { } else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
args->flags |= XFSMNT_NOALIGN; args->flags |= XFSMNT_NOALIGN;
} else if (!strcmp(this_char, MNTOPT_SUNIT)) { } else if (!strcmp(this_char, MNTOPT_SUNIT)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
MNTOPT_SUNIT);
return -EINVAL;
}
dsunit = simple_strtoul(value, &eov, 10); dsunit = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_SWIDTH)) { } else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
MNTOPT_SWIDTH);
return -EINVAL;
}
dswidth = simple_strtoul(value, &eov, 10); dswidth = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_NOUUID)) { } else if (!strcmp(this_char, MNTOPT_NOUUID)) {
args->flags |= XFSMNT_NOUUID; args->flags |= XFSMNT_NOUUID;
...@@ -218,33 +257,33 @@ printk("XFS: osyncisdsync is now the default, option is deprecated.\n"); ...@@ -218,33 +257,33 @@ printk("XFS: osyncisdsync is now the default, option is deprecated.\n");
printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n"); printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");
} else { } else {
printk("XFS: unknown mount option [%s].\n", this_char); printk("XFS: unknown mount option [%s].\n", this_char);
return rval; return -EINVAL;
} }
} }
if (args->flags & XFSMNT_NORECOVERY) { if (args->flags & XFSMNT_NORECOVERY) {
if ((flags & MS_RDONLY) == 0) { if ((flags & MS_RDONLY) == 0) {
printk("XFS: no-recovery mounts must be read-only.\n"); printk("XFS: no-recovery mounts must be read-only.\n");
return rval; return -EINVAL;
} }
} }
if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) { if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {
printk( printk(
"XFS: sunit and swidth options incompatible with the noalign option\n"); "XFS: sunit and swidth options incompatible with the noalign option\n");
return rval; return -EINVAL;
} }
if ((dsunit && !dswidth) || (!dsunit && dswidth)) { if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
printk("XFS: sunit and swidth must be specified together\n"); printk("XFS: sunit and swidth must be specified together\n");
return rval; return -EINVAL;
} }
if (dsunit && (dswidth % dsunit != 0)) { if (dsunit && (dswidth % dsunit != 0)) {
printk( printk(
"XFS: stripe width (%d) must be a multiple of the stripe unit (%d)\n", "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)\n",
dswidth, dsunit); dswidth, dsunit);
return rval; return -EINVAL;
} }
if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) { if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
......
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