diff options
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 29 |
1 files changed, 20 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; |