|
From: <jer...@gm...> - 2015-01-08 20:11:51
|
This patch adds umask, file_umask and dir_umask mount options to SquashFS to
further limit permissions from when the filesystem was created. This can be
useful in the case the filesystem was created using 777 permissions on all
files. Part of the code was taken from fs/fat kernel module.
Signed-off-by: Jérôme Poulin <jer...@gm...>
---
diff -udpr linux-source-3.13.0/fs/squashfs/inode.c linux-source-3.13.0-squashfs/fs/squashfs/inode.c
--- linux-source-3.13.0/fs/squashfs/inode.c 2014-01-19 21:40:07.000000000 -0500
+++ linux-source-3.13.0-squashfs/fs/squashfs/inode.c 2015-01-08 13:53:18.130728471 -0500
@@ -167,6 +167,7 @@ int squashfs_read_inode(struct inode *in
inode->i_size = le32_to_cpu(sqsh_ino->file_size);
inode->i_fop = &generic_ro_fops;
inode->i_mode |= S_IFREG;
+ inode->i_mode &= ~SQUASHFS_SB(inode->i_sb)->s_file_umask;
inode->i_blocks = ((inode->i_size - 1) >> 9) + 1;
squashfs_i(inode)->fragment_block = frag_blk;
squashfs_i(inode)->fragment_size = frag_size;
@@ -212,6 +213,7 @@ int squashfs_read_inode(struct inode *in
inode->i_op = &squashfs_inode_ops;
inode->i_fop = &generic_ro_fops;
inode->i_mode |= S_IFREG;
+ inode->i_mode &= ~SQUASHFS_SB(inode->i_sb)->s_file_umask;
inode->i_blocks = (inode->i_size -
le64_to_cpu(sqsh_ino->sparse) + 511) >> 9;
@@ -241,6 +243,7 @@ int squashfs_read_inode(struct inode *in
inode->i_op = &squashfs_dir_inode_ops;
inode->i_fop = &squashfs_dir_ops;
inode->i_mode |= S_IFDIR;
+ inode->i_mode &= ~SQUASHFS_SB(inode->i_sb)->s_dir_umask;
squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
squashfs_i(inode)->dir_idx_cnt = 0;
@@ -266,6 +269,7 @@ int squashfs_read_inode(struct inode *in
inode->i_op = &squashfs_dir_inode_ops;
inode->i_fop = &squashfs_dir_ops;
inode->i_mode |= S_IFDIR;
+ inode->i_mode &= ~SQUASHFS_SB(inode->i_sb)->s_dir_umask;
squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
squashfs_i(inode)->dir_idx_start = block;
@@ -293,6 +297,7 @@ int squashfs_read_inode(struct inode *in
inode->i_op = &squashfs_symlink_inode_ops;
inode->i_data.a_ops = &squashfs_symlink_aops;
inode->i_mode |= S_IFLNK;
+ inode->i_mode &= ~SQUASHFS_SB(inode->i_sb)->s_file_umask;
squashfs_i(inode)->start = block;
squashfs_i(inode)->offset = offset;
@@ -329,6 +334,7 @@ int squashfs_read_inode(struct inode *in
inode->i_mode |= S_IFCHR;
else
inode->i_mode |= S_IFBLK;
+ inode->i_mode &= ~SQUASHFS_SB(inode->i_sb)->s_file_umask;
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
rdev = le32_to_cpu(sqsh_ino->rdev);
init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
@@ -351,6 +357,7 @@ int squashfs_read_inode(struct inode *in
inode->i_mode |= S_IFCHR;
else
inode->i_mode |= S_IFBLK;
+ inode->i_mode &= ~SQUASHFS_SB(inode->i_sb)->s_file_umask;
xattr_id = le32_to_cpu(sqsh_ino->xattr);
inode->i_op = &squashfs_inode_ops;
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
@@ -374,6 +381,7 @@ int squashfs_read_inode(struct inode *in
inode->i_mode |= S_IFIFO;
else
inode->i_mode |= S_IFSOCK;
+ inode->i_mode &= ~SQUASHFS_SB(inode->i_sb)->s_file_umask;
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
init_special_inode(inode, inode->i_mode, 0);
break;
@@ -391,6 +399,7 @@ int squashfs_read_inode(struct inode *in
inode->i_mode |= S_IFIFO;
else
inode->i_mode |= S_IFSOCK;
+ inode->i_mode &= ~SQUASHFS_SB(inode->i_sb)->s_file_umask;
xattr_id = le32_to_cpu(sqsh_ino->xattr);
inode->i_op = &squashfs_inode_ops;
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
diff -udpr linux-source-3.13.0/fs/squashfs/squashfs_fs_sb.h linux-source-3.13.0-squashfs/fs/squashfs/squashfs_fs_sb.h
--- linux-source-3.13.0/fs/squashfs/squashfs_fs_sb.h 2014-01-19 21:40:07.000000000 -0500
+++ linux-source-3.13.0-squashfs/fs/squashfs/squashfs_fs_sb.h 2015-01-08 13:55:19.498804019 -0500
@@ -76,5 +76,7 @@ struct squashfs_sb_info {
long long bytes_used;
unsigned int inodes;
int xattr_ids;
+ umode_t s_file_umask;
+ umode_t s_dir_umask;
};
#endif
diff -udpr linux-source-3.13.0/fs/squashfs/squashfs.h linux-source-3.13.0-squashfs/fs/squashfs/squashfs.h
--- linux-source-3.13.0/fs/squashfs/squashfs.h 2014-01-19 21:40:07.000000000 -0500
+++ linux-source-3.13.0-squashfs/fs/squashfs/squashfs.h 2015-01-08 13:54:41.818780371 -0500
@@ -83,6 +83,9 @@ extern struct inode *squashfs_iget(struc
unsigned int);
extern int squashfs_read_inode(struct inode *, long long);
+/* super.c */
+#define SQUASHFS_SB(sb) ((struct squashfs_sb_info *)(sb)->s_fs_info)
+
/* xattr.c */
extern ssize_t squashfs_listxattr(struct dentry *, char *, size_t);
diff -udpr linux-source-3.13.0/fs/squashfs/super.c linux-source-3.13.0-squashfs/fs/squashfs/super.c
--- linux-source-3.13.0/fs/squashfs/super.c 2014-01-19 21:40:07.000000000 -0500
+++ linux-source-3.13.0-squashfs/fs/squashfs/super.c 2015-01-08 14:41:48.516639895 -0500
@@ -29,6 +29,8 @@
#include <linux/fs.h>
#include <linux/vfs.h>
+#include <linux/parser.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
@@ -47,6 +49,77 @@
static struct file_system_type squashfs_fs_type;
static const struct super_operations squashfs_super_ops;
+enum {
+ opt_umask, opt_file_umask, opt_dir_umask, opt_err
+};
+
+static const match_table_t tokens = {
+ { opt_umask, "umask=%o" },
+ { opt_file_umask, "file_umask=%o" },
+ { opt_dir_umask, "dir_umask=%o" },
+ { opt_err, NULL },
+};
+
+static int squashfs_show_options(struct seq_file *m, struct dentry *root)
+{
+ struct squashfs_sb_info *sbi = SQUASHFS_SB(root->d_sb);
+
+ if (sbi->s_file_umask != 0)
+ seq_printf(m, ",file_umask=%o", sbi->s_file_umask);
+ if (sbi->s_dir_umask != 0)
+ seq_printf(m, ",dir_umask=%o", sbi->s_dir_umask);
+ return 0;
+}
+
+static int parse_options(char *options, struct squashfs_sb_info *sbi)
+{
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+ int tmp, token;
+
+ /* initialize the sb with defaults */
+ sbi->s_file_umask = 0;
+ sbi->s_dir_umask = 0;
+
+ if (!options)
+ return 1;
+
+ while ((p = strsep(&options, ",")) != NULL) {
+ if (!*p)
+ continue;
+
+ token = match_token(p, tokens, args);
+ switch (token) {
+ case opt_umask:
+ if (match_octal(&args[0], &tmp)) {
+ pr_err("umask requires an octal value\n");
+ return 0;
+ }
+ sbi->s_file_umask = (umode_t)tmp;
+ sbi->s_dir_umask = (umode_t)tmp;
+ break;
+ case opt_file_umask:
+ if (match_octal(&args[0], &tmp)) {
+ pr_err("file_umask requires an octal value\n");
+ return 0;
+ }
+ sbi->s_file_umask = (umode_t)tmp;
+ break;
+ case opt_dir_umask:
+ if (match_octal(&args[0], &tmp)) {
+ pr_err("dir_umask requires an octal value\n");
+ return 0;
+ }
+ sbi->s_dir_umask = (umode_t)tmp;
+ break;
+ default:
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
static const struct squashfs_decompressor *supported_squashfs_filesystem(short
major, short minor, short id)
{
@@ -118,6 +191,12 @@ static int squashfs_fill_super(struct su
err = -EINVAL;
+ /* Parse mount options if any */
+ if (!parse_options((char *)data, msblk)) {
+ pr_err(KERN_ERR "squashfs: unable to parse mount options.\n");
+ goto failed_mount;
+ }
+
/* Check it is a SQUASHFS superblock */
sb->s_magic = le32_to_cpu(sblk->s_magic);
if (sb->s_magic != SQUASHFS_MAGIC) {
@@ -496,7 +575,8 @@ static const struct super_operations squ
.destroy_inode = squashfs_destroy_inode,
.statfs = squashfs_statfs,
.put_super = squashfs_put_super,
- .remount_fs = squashfs_remount
+ .remount_fs = squashfs_remount,
+ .show_options = squashfs_show_options,
};
module_init(init_squashfs_fs);
|