From af7b05375e299d712b700ae4b49b92009bc66980 Mon Sep 17 00:00:00 2001 From: Erez Zadok Date: Sat, 8 Dec 2007 13:44:27 -0500 Subject: [PATCH] Unionfs: cleanup/consolidate branch-mode parsing code Also a bug fix: disallow unrecognized branch modes at mount time, instead of defaulting to "rw". Signed-off-by: Erez Zadok --- fs/unionfs/main.c | 44 ++++++++++++++++++++++---------------------- fs/unionfs/super.c | 12 ++++++++---- fs/unionfs/union.h | 3 +-- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c index 66ddfc6945..fa3ad4fe06 100644 --- a/fs/unionfs/main.c +++ b/fs/unionfs/main.c @@ -276,30 +276,21 @@ static int is_branch_overlap(struct dentry *dent1, struct dentry *dent2) } /* - * Parse branch mode helper function + * Parse "ro" or "rw" options, but default to "rw" if no mode options was + * specified. Fill the mode bits in @perms. If encounter an unknown + * string, return -EINVAL. Otherwise return 0. */ -int __parse_branch_mode(const char *name) +int parse_branch_mode(const char *name, int *perms) { - if (!name) + if (!name || !strcmp(name, "rw")) { + *perms = MAY_READ | MAY_WRITE; return 0; - if (!strcmp(name, "ro")) - return MAY_READ; - if (!strcmp(name, "rw")) - return (MAY_READ | MAY_WRITE); - return 0; -} - -/* - * Parse "ro" or "rw" options, but default to "rw" of no mode options - * was specified. - */ -int parse_branch_mode(const char *name) -{ - int perms = __parse_branch_mode(name); - - if (perms == 0) - perms = MAY_READ | MAY_WRITE; - return perms; + } + if (!strcmp(name, "ro")) { + *perms = MAY_READ; + return 0; + } + return -EINVAL; } /* @@ -371,8 +362,17 @@ static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info if (mode) *mode++ = '\0'; - perms = parse_branch_mode(mode); + err = parse_branch_mode(mode, &perms); + if (err) { + printk(KERN_ERR "unionfs: invalid mode \"%s\" for " + "branch %d\n", mode, bindex); + goto out; + } + /* ensure that leftmost branch is writeable */ if (!bindex && !(perms & MAY_WRITE)) { + printk(KERN_ERR "unionfs: leftmost branch cannot be " + "read-only (use \"-o ro\" to create a " + "read-only union)\n"); err = -EINVAL; goto out; } diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c index bbf7060996..5903ce51de 100644 --- a/fs/unionfs/super.c +++ b/fs/unionfs/super.c @@ -174,8 +174,8 @@ static noinline int do_remount_mode_option(char *optarg, int cur_branches, goto out; } *modename++ = '\0'; - perms = __parse_branch_mode(modename); - if (perms == 0) { + err = parse_branch_mode(modename, &perms); + if (err) { printk(KERN_ERR "unionfs: invalid mode \"%s\" for \"%s\"\n", modename, optarg); goto out; @@ -343,13 +343,17 @@ found_insertion_point: modename = strchr(new_branch, '='); if (modename) *modename++ = '\0'; - perms = parse_branch_mode(modename); - if (!new_branch || !*new_branch) { printk(KERN_ERR "unionfs: null new branch\n"); err = -EINVAL; goto out; } + err = parse_branch_mode(modename, &perms); + if (err) { + printk(KERN_ERR "unionfs: invalid mode \"%s\" for " + "branch \"%s\"\n", modename, new_branch); + goto out; + } err = path_lookup(new_branch, LOOKUP_FOLLOW, &nd); if (err) { printk(KERN_ERR "unionfs: error accessing " diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h index 399ab96bed..8bc1b51803 100644 --- a/fs/unionfs/union.h +++ b/fs/unionfs/union.h @@ -474,8 +474,7 @@ static inline int is_robranch(const struct dentry *dentry) * EXTERNALS: */ extern int check_branch(struct nameidata *nd); -extern int __parse_branch_mode(const char *name); -extern int parse_branch_mode(const char *name); +extern int parse_branch_mode(const char *name, int *perms); /* * These two functions are here because it is kind of daft to copy and paste -- 2.43.0