#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/kernel.h>
+#include <linux/sched.h>
#ifndef KERNEL_2_6_11_PLUS
static inline loff_t page_offset(struct page *page)
if (cmd == F_GETLK) {
if (fc->no_lock) {
-#ifdef KERNEL_2_6_17_PLUS
+#ifdef KERNEL_2_6_22_PLUS
+ posix_test_lock(file, fl);
+#elif defined(KERNEL_2_6_17_PLUS)
if (!posix_test_lock(file, fl, fl))
fl->fl_type = F_UNLCK;
#else
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
# define KERNEL_2_6_21_PLUS
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+# define KERNEL_2_6_22_PLUS
+#endif
#if defined(__arm__) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
#define DCACHE_BUG
#ifndef HAVE_CONFIG_BLOCK
#define CONFIG_BLOCK
#endif
+#ifndef FS_HAS_SUBTYPE
+#define FS_HAS_SUBTYPE 0
+#endif
+#ifndef FS_SAFE
+#define FS_SAFE 0
+#endif
/** Max number of pages that can be used in a single read request */
#define FUSE_MAX_PAGES_PER_REQ 32
#include <linux/parser.h>
#include <linux/statfs.h>
#include <linux/random.h>
+#include <linux/sched.h>
MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
MODULE_DESCRIPTION("Filesystem in Userspace");
d->max_read = ~0;
d->blksize = 512;
+ /*
+ * For unprivileged mounts use current uid/gid. Still allow
+ * "user_id" and "group_id" options for compatibility, but
+ * only if they match these values.
+ */
+ if (!capable(CAP_SYS_ADMIN)) {
+ d->user_id = current->uid;
+ d->user_id_present = 1;
+ d->group_id = current->gid;
+ d->group_id_present = 1;
+
+ }
+
while ((p = strsep(&opt, ",")) != NULL) {
int token;
int value;
case OPT_USER_ID:
if (match_int(&args[0], &value))
return 0;
+ if (d->user_id_present && d->user_id != value)
+ return 0;
d->user_id = value;
d->user_id_present = 1;
break;
case OPT_GROUP_ID:
if (match_int(&args[0], &value))
return 0;
+ if (d->group_id_present && d->group_id != value)
+ return 0;
d->group_id = value;
d->group_id_present = 1;
break;
return fuse_iget(sb, 1, 0, &attr);
}
#ifndef FUSE_MAINLINE
+#ifdef HAVE_EXPORTFS_H
+#include <linux/exportfs.h>
+#endif
static struct dentry *fuse_get_dentry(struct super_block *sb, void *vobjp)
{
__u32 *objp = vobjp;
if (!parse_fuse_opt((char *) data, &d, is_bdev))
return -EINVAL;
+ /* This is a privileged option */
+ if ((d.flags & FUSE_ALLOW_OTHER) && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
if (is_bdev) {
#ifdef CONFIG_BLOCK
if (!sb_set_blocksize(sb, d.blksize))
.name = "fuse",
.get_sb = fuse_get_sb,
.kill_sb = kill_anon_super,
+ .fs_flags = FS_HAS_SUBTYPE | FS_SAFE,
};
#ifdef CONFIG_BLOCK
.name = "fuseblk",
.get_sb = fuse_get_sb_blk,
.kill_sb = kill_block_super,
- .fs_flags = FS_REQUIRES_DEV,
+ .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE,
};
static inline int register_fuseblk(void)
{
struct inode * inode = foo;
+#ifndef KERNEL_2_6_22_PLUS
if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR)
- inode_init_once(inode);
+#endif
+ inode_init_once(inode);
}
static int __init fuse_fs_init(void)
if (err)
return err;
#endif
+#ifdef KERNEL_2_6_22_PLUS
+ kobj_set_kset_s(&fuse_subsys, fs_subsys);
+#else
kset_set_kset_s(&fuse_subsys, fs_subsys);
+#endif
err = subsystem_register(&fuse_subsys);
if (err)
goto out_err;
+#ifdef KERNEL_2_6_22_PLUS
+ kobj_set_kset_s(&connections_subsys, fuse_subsys);
+#else
kset_set_kset_s(&connections_subsys, fuse_subsys);
+#endif
err = subsystem_register(&connections_subsys);
if (err)
goto out_fuse_unregister;