[PATCH] fuse: scramble lock owner ID
[linux-2.6.git] / fs / fuse / file.c
index 36f92f1..28aa81e 100644 (file)
@@ -161,15 +161,25 @@ static int fuse_release(struct inode *inode, struct file *file)
 }
 
 /*
- * It would be nice to scramble the ID space, so that the value of the
- * files_struct pointer is not exposed to userspace.  Symmetric crypto
- * functions are overkill, since the inverse function doesn't need to
- * be implemented (though it does have to exist).  Is there something
- * simpler?
+ * Scramble the ID space with XTEA, so that the value of the files_struct
+ * pointer is not exposed to userspace.
  */
-static inline u64 fuse_lock_owner_id(fl_owner_t id)
+static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
 {
-       return (unsigned long) id;
+       u32 *k = fc->scramble_key;
+       u64 v = (unsigned long) id;
+       u32 v0 = v;
+       u32 v1 = v >> 32;
+       u32 sum = 0;
+       int i;
+
+       for (i = 0; i < 32; i++) {
+               v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
+               sum += 0x9E3779B9;
+               v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]);
+       }
+
+       return (u64) v0 + ((u64) v1 << 32);
 }
 
 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)
        req = fuse_get_req_nofail(fc, file);
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
-       inarg.lock_owner = fuse_lock_owner_id(id);
+       inarg.lock_owner = fuse_lock_owner_id(fc, id);
        req->in.h.opcode = FUSE_FLUSH;
        req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
@@ -644,11 +654,12 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
                         const struct file_lock *fl, int opcode, pid_t pid)
 {
        struct inode *inode = file->f_dentry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_lk_in *arg = &req->misc.lk_in;
 
        arg->fh = ff->fh;
-       arg->owner = fuse_lock_owner_id(fl->fl_owner);
+       arg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
        arg->lk.start = fl->fl_start;
        arg->lk.end = fl->fl_end;
        arg->lk.type = fl->fl_type;