summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Robertson <dan@dlrobertson.com>2021-05-09 18:52:23 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2022-10-03 22:51:23 -0400
commit7367e6c1fa00f0c00eb1e34864e46695c4749a19 (patch)
treedd8600ebfcf540bc131520ef66d93dd9628b79f0
parenta229d06105fcd21d7a88a111e6c4b51b0d25666d (diff)
bcachefs: Fix error in parsing of mount options
When parsing the mount options duplicate the given options. This is required as the options are parsed twice and strsep is used in parsing. The options will be modified into a possibly invalid options set for the second round of parsing if the options are not duplicated before parsing. Signed-off-by: Dan Robertson <dan@dlrobertson.com>
-rw-r--r--fs/bcachefs/opts.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/fs/bcachefs/opts.c b/fs/bcachefs/opts.c
index 0cfbb56a57c1..64bf5a382d63 100644
--- a/fs/bcachefs/opts.c
+++ b/fs/bcachefs/opts.c
@@ -315,11 +315,20 @@ int bch2_opts_check_may_set(struct bch_fs *c)
int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
char *options)
{
+ char *copied_opts, *copied_opts_start;
char *opt, *name, *val;
int ret, id;
u64 v;
- while ((opt = strsep(&options, ",")) != NULL) {
+ if (!options)
+ return 0;
+
+ copied_opts = kstrdup(options, GFP_KERNEL);
+ if (!copied_opts)
+ return -1;
+ copied_opts_start = copied_opts;
+
+ while ((opt = strsep(&copied_opts, ",")) != NULL) {
name = strsep(&opt, "=");
val = opt;
@@ -363,16 +372,24 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
bch2_opt_set_by_id(opts, id, v);
}
- return 0;
+ ret = 0;
+ goto out;
+
bad_opt:
pr_err("Bad mount option %s", name);
- return -1;
+ ret = -1;
+ goto out;
bad_val:
pr_err("Invalid value %s for mount option %s", val, name);
- return -1;
+ ret = -1;
+ goto out;
no_val:
pr_err("Mount option %s requires a value", name);
- return -1;
+ ret = -1;
+ goto out;
+out:
+ kfree(copied_opts_start);
+ return ret;
}
/* io opts: */