Skip to content

Commit

Permalink
fuse: allow umask processing in userspace
Browse files Browse the repository at this point in the history
This patch lets filesystems handle masking the file mode on creation.
This is needed if filesystem is using ACLs.

 - The CREATE, MKDIR and MKNOD requests are extended with a "umask"
   parameter.

 - A new FUSE_DONT_MASK flag is added to the INIT request/reply.  With
   this the filesystem may request that the create mode is not masked.

CC: Jean-Pierre André <jean-pierre.andre@wanadoo.fr>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
  • Loading branch information
Miklos Szeredi committed Jun 30, 2009
1 parent 201fa69 commit e0a43dd
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 6 deletions.
20 changes: 17 additions & 3 deletions fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_req *req;
struct fuse_req *forget_req;
struct fuse_open_in inarg;
struct fuse_create_in inarg;
struct fuse_open_out outopen;
struct fuse_entry_out outentry;
struct fuse_file *ff;
Expand All @@ -399,15 +399,20 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
if (!ff)
goto out_put_request;

if (!fc->dont_mask)
mode &= ~current_umask();

flags &= ~O_NOCTTY;
memset(&inarg, 0, sizeof(inarg));
memset(&outentry, 0, sizeof(outentry));
inarg.flags = flags;
inarg.mode = mode;
inarg.umask = current_umask();
req->in.h.opcode = FUSE_CREATE;
req->in.h.nodeid = get_node_id(dir);
req->in.numargs = 2;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
sizeof(inarg);
req->in.args[0].value = &inarg;
req->in.args[1].size = entry->d_name.len + 1;
req->in.args[1].value = entry->d_name.name;
Expand Down Expand Up @@ -546,12 +551,17 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
if (IS_ERR(req))
return PTR_ERR(req);

if (!fc->dont_mask)
mode &= ~current_umask();

memset(&inarg, 0, sizeof(inarg));
inarg.mode = mode;
inarg.rdev = new_encode_dev(rdev);
inarg.umask = current_umask();
req->in.h.opcode = FUSE_MKNOD;
req->in.numargs = 2;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
sizeof(inarg);
req->in.args[0].value = &inarg;
req->in.args[1].size = entry->d_name.len + 1;
req->in.args[1].value = entry->d_name.name;
Expand All @@ -578,8 +588,12 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
if (IS_ERR(req))
return PTR_ERR(req);

if (!fc->dont_mask)
mode &= ~current_umask();

memset(&inarg, 0, sizeof(inarg));
inarg.mode = mode;
inarg.umask = current_umask();
req->in.h.opcode = FUSE_MKDIR;
req->in.numargs = 2;
req->in.args[0].size = sizeof(inarg);
Expand Down
3 changes: 3 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,9 @@ struct fuse_conn {
/** Do multi-page cached writes */
unsigned big_writes:1;

/** Don't apply umask to creation modes */
unsigned dont_mask:1;

/** The number of requests waiting for completion */
atomic_t num_waiting;

Expand Down
9 changes: 8 additions & 1 deletion fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
}
if (arg->flags & FUSE_BIG_WRITES)
fc->big_writes = 1;
if (arg->flags & FUSE_DONT_MASK)
fc->dont_mask = 1;
} else {
ra_pages = fc->max_read / PAGE_CACHE_SIZE;
fc->no_lock = 1;
Expand All @@ -748,7 +750,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
arg->minor = FUSE_KERNEL_MINOR_VERSION;
arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES;
FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK;
req->in.h.opcode = FUSE_INIT;
req->in.numargs = 1;
req->in.args[0].size = sizeof(*arg);
Expand Down Expand Up @@ -864,6 +866,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
if (err)
goto err_put_conn;

/* Handle umasking inside the fuse code */
if (sb->s_flags & MS_POSIXACL)
fc->dont_mask = 1;
sb->s_flags |= MS_POSIXACL;

fc->release = fuse_free_conn;
fc->flags = d.flags;
fc->user_id = d.user_id;
Expand Down
20 changes: 18 additions & 2 deletions include/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
* - add IOCTL message
* - add unsolicited notification support
* - add POLL message and NOTIFY_POLL notification
*
* 7.12
* - add umask flag to input argument of open, mknod and mkdir
*/

#ifndef _LINUX_FUSE_H
Expand All @@ -36,7 +39,7 @@
#define FUSE_KERNEL_VERSION 7

/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 11
#define FUSE_KERNEL_MINOR_VERSION 12

/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
Expand Down Expand Up @@ -112,13 +115,15 @@ struct fuse_file_lock {
* INIT request/reply flags
*
* FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
* FUSE_DONT_MASK: don't apply umask to file mode on create operations
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
#define FUSE_FILE_OPS (1 << 2)
#define FUSE_ATOMIC_O_TRUNC (1 << 3)
#define FUSE_EXPORT_SUPPORT (1 << 4)
#define FUSE_BIG_WRITES (1 << 5)
#define FUSE_DONT_MASK (1 << 6)

/**
* CUSE INIT request/reply flags
Expand Down Expand Up @@ -262,14 +267,18 @@ struct fuse_attr_out {
struct fuse_attr attr;
};

#define FUSE_COMPAT_MKNOD_IN_SIZE 8

struct fuse_mknod_in {
__u32 mode;
__u32 rdev;
__u32 umask;
__u32 padding;
};

struct fuse_mkdir_in {
__u32 mode;
__u32 padding;
__u32 umask;
};

struct fuse_rename_in {
Expand Down Expand Up @@ -300,8 +309,15 @@ struct fuse_setattr_in {
};

struct fuse_open_in {
__u32 flags;
__u32 unused;
};

struct fuse_create_in {
__u32 flags;
__u32 mode;
__u32 umask;
__u32 padding;
};

struct fuse_open_out {
Expand Down

0 comments on commit e0a43dd

Please sign in to comment.