diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fuse/file.c | 29 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 3 | ||||
-rw-r--r-- | fs/fuse/inode.c | 2 |
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 | */ |
170 | static inline u64 fuse_lock_owner_id(fl_owner_t id) | 167 | static 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 | ||
175 | static int fuse_flush(struct file *file, fl_owner_t id) | 185 | static 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 | ||
364 | static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) | 367 | static 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 | ||
20 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); | 21 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); |
21 | MODULE_DESCRIPTION("Filesystem in Userspace"); | 22 | MODULE_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 | } |