aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/file.c29
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/fuse/inode.c2
3 files changed, 25 insertions, 9 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 36f92f181d2f..28aa81eae2cc 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -161,15 +161,25 @@ static int fuse_release(struct inode *inode, struct file *file)
161} 161}
162 162
163/* 163/*
164 * It would be nice to scramble the ID space, so that the value of the 164 * Scramble the ID space with XTEA, so that the value of the files_struct
165 * files_struct pointer is not exposed to userspace. Symmetric crypto 165 * pointer is not exposed to userspace.
166 * functions are overkill, since the inverse function doesn't need to
167 * be implemented (though it does have to exist). Is there something
168 * simpler?
169 */ 166 */
170static inline u64 fuse_lock_owner_id(fl_owner_t id) 167static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
171{ 168{
172 return (unsigned long) id; 169 u32 *k = fc->scramble_key;
170 u64 v = (unsigned long) id;
171 u32 v0 = v;
172 u32 v1 = v >> 32;
173 u32 sum = 0;
174 int i;
175
176 for (i = 0; i < 32; i++) {
177 v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
178 sum += 0x9E3779B9;
179 v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]);
180 }
181
182 return (u64) v0 + ((u64) v1 << 32);
173} 183}
174 184
175static int fuse_flush(struct file *file, fl_owner_t id) 185static int fuse_flush(struct file *file, fl_owner_t id)
@@ -190,7 +200,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
190 req = fuse_get_req_nofail(fc, file); 200 req = fuse_get_req_nofail(fc, file);
191 memset(&inarg, 0, sizeof(inarg)); 201 memset(&inarg, 0, sizeof(inarg));
192 inarg.fh = ff->fh; 202 inarg.fh = ff->fh;
193 inarg.lock_owner = fuse_lock_owner_id(id); 203 inarg.lock_owner = fuse_lock_owner_id(fc, id);
194 req->in.h.opcode = FUSE_FLUSH; 204 req->in.h.opcode = FUSE_FLUSH;
195 req->in.h.nodeid = get_node_id(inode); 205 req->in.h.nodeid = get_node_id(inode);
196 req->in.numargs = 1; 206 req->in.numargs = 1;
@@ -644,11 +654,12 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
644 const struct file_lock *fl, int opcode, pid_t pid) 654 const struct file_lock *fl, int opcode, pid_t pid)
645{ 655{
646 struct inode *inode = file->f_dentry->d_inode; 656 struct inode *inode = file->f_dentry->d_inode;
657 struct fuse_conn *fc = get_fuse_conn(inode);
647 struct fuse_file *ff = file->private_data; 658 struct fuse_file *ff = file->private_data;
648 struct fuse_lk_in *arg = &req->misc.lk_in; 659 struct fuse_lk_in *arg = &req->misc.lk_in;
649 660
650 arg->fh = ff->fh; 661 arg->fh = ff->fh;
651 arg->owner = fuse_lock_owner_id(fl->fl_owner); 662 arg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
652 arg->lk.start = fl->fl_start; 663 arg->lk.start = fl->fl_start;
653 arg->lk.end = fl->fl_end; 664 arg->lk.end = fl->fl_end;
654 arg->lk.type = fl->fl_type; 665 arg->lk.type = fl->fl_type;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index c862df58da92..0dbf96621841 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -359,6 +359,9 @@ struct fuse_conn {
359 359
360 /** O_ASYNC requests */ 360 /** O_ASYNC requests */
361 struct fasync_struct *fasync; 361 struct fasync_struct *fasync;
362
363 /** Key for lock owner ID scrambling */
364 u32 scramble_key[4];
362}; 365};
363 366
364static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) 367static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e21ef8a3ad30..5ceb8bd7a189 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -16,6 +16,7 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/parser.h> 17#include <linux/parser.h>
18#include <linux/statfs.h> 18#include <linux/statfs.h>
19#include <linux/random.h>
19 20
20MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); 21MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
21MODULE_DESCRIPTION("Filesystem in Userspace"); 22MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -387,6 +388,7 @@ static struct fuse_conn *new_conn(void)
387 fc->bdi.unplug_io_fn = default_unplug_io_fn; 388 fc->bdi.unplug_io_fn = default_unplug_io_fn;
388 fc->reqctr = 0; 389 fc->reqctr = 0;
389 fc->blocked = 1; 390 fc->blocked = 1;
391 get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
390 } 392 }
391 return fc; 393 return fc;
392} 394}