From c26c14d8db2072ca1ddc9f9f3133edb3f1c564aa Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 9 Apr 2004 17:48:32 +0000 Subject: [PATCH] limit checking --- ChangeLog | 4 ++ include/linux/fuse.h | 4 ++ kernel/dev.c | 124 +++++++++++++++++++------------------ kernel/dir.c | 141 +++++++++++++++++++++++-------------------- kernel/file.c | 54 ++++++++--------- kernel/inode.c | 36 +++++------ kernel/util.c | 6 +- 7 files changed, 193 insertions(+), 176 deletions(-) diff --git a/ChangeLog b/ChangeLog index d0c7061..3d78ca5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-04-09 Miklos Szeredi + + * Check some limits so userspace won't get too big requests + 2004-04-05 Miklos Szeredi * Kill compile warning diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 8467ed6..bee2930 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -123,6 +123,10 @@ enum fuse_opcode { /* Conservative buffer size for the client */ #define FUSE_MAX_IN 8192 +#define FUSE_NAME_MAX 1024 +#define FUSE_SYMLINK_MAX 4096 +#define FUSE_XATTR_SIZE_MAX 4096 + struct fuse_entry_out { unsigned long ino; /* Inode number */ unsigned long generation; /* Inode generation: ino:gen must diff --git a/kernel/dev.c b/kernel/dev.c index d8535e7..afc9f4c 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -24,7 +24,7 @@ static struct fuse_req *request_new(void) struct fuse_req *req; req = (struct fuse_req *) kmem_cache_alloc(fuse_req_cachep, SLAB_NOFS); - if(req) { + if (req) { INIT_LIST_HEAD(&req->list); req->issync = 0; req->locked = 0; @@ -46,7 +46,7 @@ static void request_free(struct fuse_req *req) static int request_restartable(enum fuse_opcode opcode) { - switch(opcode) { + switch (opcode) { case FUSE_LOOKUP: case FUSE_GETATTR: case FUSE_READLINK: @@ -69,11 +69,11 @@ static void request_wait_answer(struct fuse_req *req) spin_unlock(&fuse_lock); intr = wait_event_interruptible(req->waitq, req->finished); spin_lock(&fuse_lock); - if(!intr) + if (!intr) return; /* Request interrupted... Wait for it to be unlocked */ - if(req->locked) { + if (req->locked) { req->interrupted = 1; spin_unlock(&fuse_lock); wait_event(req->waitq, !req->locked); @@ -83,7 +83,7 @@ static void request_wait_answer(struct fuse_req *req) /* Operations which modify the filesystem cannot safely be restarted, because it is uncertain whether the operation has completed or not... */ - if(req->sent && !request_restartable(req->in->h.opcode)) + if (req->sent && !request_restartable(req->in->h.opcode)) req->out->h.error = -EINTR; else req->out->h.error = -ERESTARTSYS; @@ -92,7 +92,7 @@ static void request_wait_answer(struct fuse_req *req) static int get_unique(struct fuse_conn *fc) { do fc->reqctr++; - while(!fc->reqctr); + while (!fc->reqctr); return fc->reqctr; } @@ -101,7 +101,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) { fuse_reqend_t endfunc = req->end; - if(!endfunc) { + if (!endfunc) { wake_up(&req->waitq); spin_unlock(&fuse_lock); } else { @@ -118,12 +118,12 @@ void request_send(struct fuse_conn *fc, struct fuse_in *in, struct fuse_req *req; out->h.error = -ERESTARTSYS; - if(down_interruptible(&fc->outstanding)) + if (down_interruptible(&fc->outstanding)) return; out->h.error = -ENOMEM; req = request_new(); - if(req) { + if (req) { req->in = in; req->out = out; req->issync = 1; @@ -131,7 +131,7 @@ void request_send(struct fuse_conn *fc, struct fuse_in *in, spin_lock(&fuse_lock); out->h.error = -ENOTCONN; - if(fc->file) { + if (fc->file) { in->h.unique = get_unique(fc); list_add_tail(&req->list, &fc->pending); wake_up(&fc->waitq); @@ -148,7 +148,7 @@ void request_send(struct fuse_conn *fc, struct fuse_in *in, static inline void destroy_request(struct fuse_req *req) { - if(req) { + if (req) { kfree(req->in); request_free(req); } @@ -162,14 +162,14 @@ int request_send_noreply(struct fuse_conn *fc, struct fuse_in *in) struct fuse_req *req; req = request_new(); - if(!req) + if (!req) return -ENOMEM; req->in = in; req->issync = 0; spin_lock(&fuse_lock); - if(!fc->file) { + if (!fc->file) { spin_unlock(&fuse_lock); request_free(req); return -ENOTCONN; @@ -189,12 +189,12 @@ int request_send_nonblock(struct fuse_conn *fc, struct fuse_in *in, BUG_ON(!end); - if(down_trylock(&fc->outstanding)) + if (down_trylock(&fc->outstanding)) return -EWOULDBLOCK; err = -ENOMEM; req = request_new(); - if(req) { + if (req) { req->in = in; req->out = out; req->issync = 1; @@ -203,7 +203,7 @@ int request_send_nonblock(struct fuse_conn *fc, struct fuse_in *in, spin_lock(&fuse_lock); err = -ENOTCONN; - if(fc->file) { + if (fc->file) { in->h.unique = get_unique(fc); list_add_tail(&req->list, &fc->pending); wake_up(&fc->waitq); @@ -222,9 +222,9 @@ static void request_wait(struct fuse_conn *fc) DECLARE_WAITQUEUE(wait, current); add_wait_queue_exclusive(&fc->waitq, &wait); - while(fc->sb != NULL && list_empty(&fc->pending)) { + while (fc->sb != NULL && list_empty(&fc->pending)) { set_current_state(TASK_INTERRUPTIBLE); - if(signal_pending(current)) + if (signal_pending(current)) break; spin_unlock(&fuse_lock); @@ -238,12 +238,12 @@ static void request_wait(struct fuse_conn *fc) static inline int copy_in_one(const void *src, size_t srclen, char **dstp, size_t *dstlenp) { - if(*dstlenp < srclen) { + if (*dstlenp < srclen) { printk("fuse_dev_read: buffer too small\n"); return -EINVAL; } - if(copy_to_user(*dstp, src, srclen)) + if (srclen && copy_to_user(*dstp, src, srclen)) return -EFAULT; *dstp += srclen; @@ -259,13 +259,13 @@ static inline int copy_in_args(struct fuse_in *in, char *buf, size_t nbytes) size_t orignbytes = nbytes; err = copy_in_one(&in->h, sizeof(in->h), &buf, &nbytes); - if(err) + if (err) return err; - for(i = 0; i < in->numargs; i++) { + for (i = 0; i < in->numargs; i++) { struct fuse_in_arg *arg = &in->args[i]; err = copy_in_one(arg->value, arg->size, &buf, &nbytes); - if(err) + if (err) return err; } @@ -281,21 +281,21 @@ static ssize_t fuse_dev_read(struct file *file, char *buf, size_t nbytes, spin_lock(&fuse_lock); request_wait(fc); - if(fc->sb != NULL && !list_empty(&fc->pending)) { + if (fc->sb != NULL && !list_empty(&fc->pending)) { req = list_entry(fc->pending.next, struct fuse_req, list); list_del_init(&req->list); req->locked = 1; } spin_unlock(&fuse_lock); - if(fc->sb == NULL) + if (fc->sb == NULL) return -ENODEV; - if(req == NULL) + if (req == NULL) return -EINTR; ret = copy_in_args(req->in, buf, nbytes); spin_lock(&fuse_lock); - if(req->issync) { - if(ret < 0) { + if (req->issync) { + if (ret < 0) { req->out->h.error = -EPROTO; req->finished = 1; } else { @@ -303,7 +303,7 @@ static ssize_t fuse_dev_read(struct file *file, char *buf, size_t nbytes, req->sent = 1; } req->locked = 0; - if(ret < 0 || req->interrupted) + if (ret < 0 || req->interrupted) /* Unlocks fuse_lock: */ request_end(fc, req); else @@ -323,7 +323,7 @@ static struct fuse_req *request_find(struct fuse_conn *fc, unsigned int unique) list_for_each(entry, &fc->processing) { struct fuse_req *tmp; tmp = list_entry(entry, struct fuse_req, list); - if(tmp->in->h.unique == unique) { + if (tmp->in->h.unique == unique) { req = tmp; break; } @@ -343,18 +343,16 @@ static inline int copy_out_one(struct fuse_out_arg *arg, const char **srcp, size_t *srclenp, int allowvar) { size_t dstlen = arg->size; - if(*srclenp < dstlen) { - if(!allowvar) { + if (*srclenp < dstlen) { + if (!allowvar) { printk("fuse_dev_write: write is short\n"); return -EINVAL; } dstlen = *srclenp; } - if(dstlen) { - if(copy_from_user(arg->value, *srcp, dstlen)) - return -EFAULT; - } + if (dstlen && copy_from_user(arg->value, *srcp, dstlen)) + return -EFAULT; *srcp += dstlen; *srclenp -= dstlen; @@ -372,23 +370,23 @@ static inline int copy_out_args(struct fuse_out *out, const char *buf, buf += sizeof(struct fuse_out_header); nbytes -= sizeof(struct fuse_out_header); - if(!out->h.error) { - for(i = 0; i < out->numargs; i++) { + if (!out->h.error) { + for (i = 0; i < out->numargs; i++) { struct fuse_out_arg *arg = &out->args[i]; int allowvar; - if(out->argvar && i == out->numargs - 1) + if (out->argvar && i == out->numargs - 1) allowvar = 1; else allowvar = 0; err = copy_out_one(arg, &buf, &nbytes, allowvar); - if(err) + if (err) return err; } } - if(nbytes != 0) { + if (nbytes != 0) { printk("fuse_dev_write: write is long\n"); return -EINVAL; } @@ -399,12 +397,12 @@ static inline int copy_out_args(struct fuse_out *out, const char *buf, static inline int copy_out_header(struct fuse_out_header *oh, const char *buf, size_t nbytes) { - if(nbytes < sizeof(struct fuse_out_header)) { + if (nbytes < sizeof(struct fuse_out_header)) { printk("fuse_dev_write: write is short\n"); return -EINVAL; } - if(copy_from_user(oh, buf, sizeof(struct fuse_out_header))) + if (copy_from_user(oh, buf, sizeof(struct fuse_out_header))) return -EFAULT; return 0; @@ -425,8 +423,8 @@ static int fuse_invalidate(struct fuse_conn *fc, struct fuse_user_header *uh) { struct inode *inode = iget(fc->sb, uh->ino); int err = -ENOENT; - if(inode) { - if(inode->u.generic_ip) { + if (inode) { + if (inode->u.generic_ip) { invalidate_inode_pages(inode); err = 0; } @@ -447,10 +445,10 @@ static int fuse_user_request(struct fuse_conn *fc, const char *buf, return -EINVAL; } - if(copy_from_user(&uh, buf, sizeof(struct fuse_out_header))) + if (copy_from_user(&uh, buf, sizeof(struct fuse_out_header))) return -EFAULT; - switch(uh.opcode) { + switch (uh.opcode) { case FUSE_INVALIDATE: err = fuse_invalidate(fc, &uh); break; @@ -470,11 +468,11 @@ static ssize_t fuse_dev_write(struct file *file, const char *buf, struct fuse_req *req; struct fuse_out_header oh; - if(!fc->sb) + if (!fc->sb) return -EPERM; err = copy_out_header(&oh, buf, nbytes); - if(err) + if (err) return err; if (!oh.unique) { @@ -489,23 +487,23 @@ static ssize_t fuse_dev_write(struct file *file, const char *buf, spin_lock(&fuse_lock); req = request_find(fc, oh.unique); - if(req != NULL) { + if (req != NULL) { list_del_init(&req->list); req->locked = 1; } spin_unlock(&fuse_lock); - if(!req) + if (!req) return -ENOENT; req->out->h = oh; err = copy_out_args(req->out, buf, nbytes); spin_lock(&fuse_lock); - if(err) + if (err) req->out->h.error = -EPROTO; else { /* fget() needs to be done in this context */ - if(req->in->h.opcode == FUSE_GETDIR && !oh.error) + if (req->in->h.opcode == FUSE_GETDIR && !oh.error) process_getdir(req); } req->finished = 1; @@ -514,7 +512,7 @@ static ssize_t fuse_dev_write(struct file *file, const char *buf, request_end(fc, req); out: - if(!err) + if (!err) return nbytes; else return err; @@ -526,7 +524,7 @@ static unsigned int fuse_dev_poll(struct file *file, poll_table *wait) struct fuse_conn *fc = DEV_FC(file); unsigned int mask = POLLOUT | POLLWRNORM; - if(!fc->sb) + if (!fc->sb) return -EPERM; poll_wait(file, &fc->waitq, wait); @@ -544,7 +542,7 @@ static struct fuse_conn *new_conn(void) struct fuse_conn *fc; fc = kmalloc(sizeof(*fc), GFP_KERNEL); - if(fc != NULL) { + if (fc != NULL) { fc->sb = NULL; fc->file = NULL; fc->flags = 0; @@ -563,7 +561,7 @@ static int fuse_dev_open(struct inode *inode, struct file *file) struct fuse_conn *fc; fc = new_conn(); - if(!fc) + if (!fc) return -ENOMEM; fc->file = file; @@ -574,11 +572,11 @@ static int fuse_dev_open(struct inode *inode, struct file *file) static void end_requests(struct fuse_conn *fc, struct list_head *head) { - while(!list_empty(head)) { + while (!list_empty(head)) { struct fuse_req *req; req = list_entry(head->next, struct fuse_req, list); list_del_init(&req->list); - if(req->issync) { + if (req->issync) { req->out->h.error = -ECONNABORTED; req->finished = 1; /* Unlocks fuse_lock: */ @@ -628,17 +626,17 @@ int fuse_dev_init() fuse_req_cachep = kmem_cache_create("fuser_request", sizeof(struct fuse_req), 0, 0, NULL, NULL); - if(!fuse_req_cachep) + if (!fuse_req_cachep) return -ENOMEM; proc_fs_fuse = proc_mkdir("fuse", proc_root_fs); - if(proc_fs_fuse) { + if (proc_fs_fuse) { struct proc_dir_entry *de; proc_fs_fuse->owner = THIS_MODULE; proc_fuse_dev = create_proc_entry("dev", S_IFSOCK | 0666, proc_fs_fuse); - if(proc_fuse_dev) { + if (proc_fuse_dev) { proc_fuse_dev->owner = THIS_MODULE; proc_fuse_dev->proc_fops = &fuse_dev_operations; } @@ -653,7 +651,7 @@ int fuse_dev_init() void fuse_dev_cleanup() { - if(proc_fs_fuse) { + if (proc_fs_fuse) { remove_proc_entry("dev", proc_fs_fuse); remove_proc_entry("version", proc_fs_fuse); remove_proc_entry("fuse", proc_root_fs); diff --git a/kernel/dir.c b/kernel/dir.c index d5d79b1..73f8043 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -27,7 +27,7 @@ static struct dentry_operations fuse_dentry_operations; static void change_attributes(struct inode *inode, struct fuse_attr *attr) { - if(S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) { + if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) { #ifdef KERNEL_2_6 invalidate_inode_pages(inode->i_mapping); #else @@ -60,19 +60,19 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) { inode->i_mode = attr->mode & S_IFMT; i_size_write(inode, attr->size); - if(S_ISREG(inode->i_mode)) { + if (S_ISREG(inode->i_mode)) { inode->i_op = &fuse_file_inode_operations; fuse_init_file_inode(inode); } - else if(S_ISDIR(inode->i_mode)) { + else if (S_ISDIR(inode->i_mode)) { inode->i_op = &fuse_dir_inode_operations; inode->i_fop = &fuse_dir_operations; } - else if(S_ISLNK(inode->i_mode)) { + else if (S_ISLNK(inode->i_mode)) { inode->i_op = &fuse_symlink_inode_operations; } - else if(S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || - S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)){ + else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || + S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)){ inode->i_op = &fuse_file_inode_operations; init_special_inode(inode, inode->i_mode, new_decode_dev(attr->rdev)); @@ -88,11 +88,11 @@ struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation, struct inode *inode; inode = iget(sb, ino); - if(inode) { - if(!inode->u.generic_ip) { + if (inode) { + if (!inode->u.generic_ip) { inode->i_generation = generation; fuse_init_inode(inode, attr); - } else if(inode->i_generation != generation) + } else if (inode->i_generation != generation) printk("fuse_iget: bad generation for ino %lu\n", ino); change_attributes(inode, attr); @@ -109,6 +109,10 @@ static int fuse_do_lookup(struct inode *dir, struct dentry *entry, struct fuse_in in = FUSE_IN_INIT; struct fuse_out out = FUSE_OUT_INIT; + + if (entry->d_name.len > FUSE_NAME_MAX) + return -ENAMETOOLONG; + in.h.opcode = FUSE_LOOKUP; in.h.ino = dir->i_ino; in.numargs = 1; @@ -127,7 +131,7 @@ static inline unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) { /* prevent wrapping of jiffies */ - if(sec + 1 >= LONG_MAX / HZ) + if (sec + 1 >= LONG_MAX / HZ) return 0; return jiffies + sec * HZ + nsec / (1000000000 / HZ); @@ -142,12 +146,12 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry, struct inode *inode = NULL; err = fuse_do_lookup(dir, entry, &outarg, &version); - if(!err) { + if (!err) { inode = fuse_iget(dir->i_sb, outarg.ino, outarg.generation, &outarg.attr, version); - if(!inode) + if (!inode) return -ENOMEM; - } else if(err != -ENOENT) + } else if (err != -ENOENT) return err; entry->d_time = time_to_jiffies(outarg.entry_valid, @@ -164,11 +168,11 @@ static int lookup_new_entry(struct inode *dir, struct dentry *entry, struct inode *inode; inode = fuse_iget(dir->i_sb, outarg->ino, outarg->generation, &outarg->attr, version); - if(!inode) + if (!inode) return -ENOMEM; /* Don't allow userspace to do really stupid things... */ - if((inode->i_mode ^ mode) & S_IFMT) { + if ((inode->i_mode ^ mode) & S_IFMT) { iput(inode); printk("fuse_mknod: inode has wrong type\n"); return -EINVAL; @@ -204,7 +208,7 @@ static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode, out.args[0].value = &outarg; request_send(fc, &in, &out); - if(out.h.error) + if (out.h.error) return out.h.error; return lookup_new_entry(dir, entry, &outarg, out.h.unique, mode); @@ -238,7 +242,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode) out.args[0].size = sizeof(outarg); out.args[0].value = &outarg; request_send(fc, &in, &out); - if(out.h.error) + if (out.h.error) return out.h.error; return lookup_new_entry(dir, entry, &outarg, out.h.unique, S_IFDIR); @@ -251,19 +255,23 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, struct fuse_in in = FUSE_IN_INIT; struct fuse_out out = FUSE_OUT_INIT; struct fuse_entry_out outarg; + unsigned int len = strlen(link) + 1; + + if (len > FUSE_SYMLINK_MAX) + return -ENAMETOOLONG; in.h.opcode = FUSE_SYMLINK; in.h.ino = dir->i_ino; in.numargs = 2; in.args[0].size = entry->d_name.len + 1; in.args[0].value = entry->d_name.name; - in.args[1].size = strlen(link) + 1; + in.args[1].size = len; in.args[1].value = link; out.numargs = 1; out.args[0].size = sizeof(outarg); out.args[0].value = &outarg; request_send(fc, &in, &out); - if(out.h.error) + if (out.h.error) return out.h.error; return lookup_new_entry(dir, entry, &outarg, out.h.unique, S_IFLNK); @@ -282,7 +290,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) in.args[0].value = entry->d_name.name; request_send(fc, &in, &out); - if(!out.h.error) { + if (!out.h.error) { /* Set nlink to zero so the inode can be cleared, if the inode does have more links this will be discovered at the next lookup/getattr */ @@ -305,7 +313,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) in.args[0].size = entry->d_name.len + 1; in.args[0].value = entry->d_name.name; request_send(fc, &in, &out); - if(!out.h.error) + if (!out.h.error) entry->d_inode->i_nlink = 0; return out.h.error; @@ -360,7 +368,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, out.args[0].size = sizeof(outarg); out.args[0].value = &outarg; request_send(fc, &in, &out); - if(out.h.error) + if (out.h.error) return out.h.error; /* Invalidate old entry, so attributes are refreshed */ @@ -383,7 +391,7 @@ int fuse_do_getattr(struct inode *inode) out.args[0].value = &arg; request_send(fc, &in, &out); - if(!out.h.error) + if (!out.h.error) change_attributes(inode, &arg.attr); return out.h.error; @@ -394,11 +402,11 @@ static int fuse_revalidate(struct dentry *entry) struct inode *inode = entry->d_inode; struct fuse_conn *fc = INO_FC(inode); - if(inode->i_ino == FUSE_ROOT_INO) { - if(!(fc->flags & FUSE_ALLOW_OTHER) && - current->fsuid != fc->uid) + if (inode->i_ino == FUSE_ROOT_INO) { + if (!(fc->flags & FUSE_ALLOW_OTHER) && + current->fsuid != fc->uid) return -EACCES; - } else if(!entry->d_time || time_before_eq(jiffies, entry->d_time)) + } else if (!entry->d_time || time_before_eq(jiffies, entry->d_time)) return 0; return fuse_do_getattr(inode); @@ -408,18 +416,18 @@ static int _fuse_permission(struct inode *inode, int mask) { struct fuse_conn *fc = INO_FC(inode); - if(!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid) + if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid) return -EACCES; - else if(fc->flags & FUSE_DEFAULT_PERMISSIONS) { + else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { int err = vfs_permission(inode, mask); /* If permission is denied, try to refresh file attributes. This is also needed, because the root node will at first have no permissions */ - if(err == -EACCES) { + if (err == -EACCES) { err = fuse_do_getattr(inode); - if(!err) + if (!err) err = vfs_permission(inode, mask); } @@ -440,20 +448,20 @@ static int _fuse_permission(struct inode *inode, int mask) static int parse_dirfile(char *buf, size_t nbytes, struct file *file, void *dstbuf, filldir_t filldir) { - while(nbytes >= FUSE_NAME_OFFSET) { + while (nbytes >= FUSE_NAME_OFFSET) { struct fuse_dirent *dirent = (struct fuse_dirent *) buf; size_t reclen = FUSE_DIRENT_SIZE(dirent); int over; - if(dirent->namelen > NAME_MAX) { + if (dirent->namelen > NAME_MAX) { printk("fuse_readdir: name too long\n"); return -EPROTO; } - if(reclen > nbytes) + if (reclen > nbytes) break; over = filldir(dstbuf, dirent->name, dirent->namelen, file->f_pos, dirent->ino, dirent->type); - if(over) + if (over) break; buf += reclen; @@ -471,15 +479,15 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) char *buf; int ret; - if(!cfile) + if (!cfile) return -EISDIR; buf = kmalloc(DIR_BUFSIZE, GFP_KERNEL); - if(!buf) + if (!buf) return -ENOMEM; ret = kernel_read(cfile, file->f_pos, buf, DIR_BUFSIZE); - if(ret < 0) + if (ret < 0) printk("fuse_readdir: failed to read container file\n"); else ret = parse_dirfile(buf, ret, file, dstbuf, filldir); @@ -497,7 +505,7 @@ static char *read_link(struct dentry *dentry) char *link; link = (char *) __get_free_page(GFP_KERNEL); - if(!link) + if (!link) return ERR_PTR(-ENOMEM); in.h.opcode = FUSE_READLINK; @@ -507,7 +515,7 @@ static char *read_link(struct dentry *dentry) out.args[0].size = PAGE_SIZE - 1; out.args[0].value = link; request_send(fc, &in, &out); - if(out.h.error) { + if (out.h.error) { free_page((unsigned long) link); return ERR_PTR(out.h.error); } @@ -518,7 +526,7 @@ static char *read_link(struct dentry *dentry) static void free_link(char *link) { - if(!IS_ERR(link)) + if (!IS_ERR(link)) free_page((unsigned long) link); } @@ -557,15 +565,15 @@ static int fuse_dir_open(struct inode *inode, struct file *file) out.args[0].size = sizeof(struct fuse_getdir_out); out.args[0].value = &outarg; request_send(fc, &in, &out); - if(!out.h.error) { + if (!out.h.error) { struct file *cfile = outarg.file; struct inode *inode; - if(!cfile) { + if (!cfile) { printk("fuse_getdir: invalid file\n"); return -EPROTO; } inode = cfile->f_dentry->d_inode; - if(!S_ISREG(inode->i_mode)) { + if (!S_ISREG(inode->i_mode)) { printk("fuse_getdir: not a regular file\n"); fput(cfile); return -EPROTO; @@ -581,7 +589,7 @@ static int fuse_dir_release(struct inode *inode, struct file *file) { struct file *cfile = file->private_data; - if(cfile) + if (cfile) fput(cfile); return 0; @@ -595,16 +603,16 @@ static unsigned int iattr_to_fattr(struct iattr *iattr, memset(fattr, 0, sizeof(*fattr)); - if(ivalid & ATTR_MODE) + if (ivalid & ATTR_MODE) fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode; - if(ivalid & ATTR_UID) + if (ivalid & ATTR_UID) fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid; - if(ivalid & ATTR_GID) + if (ivalid & ATTR_GID) fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid; - if(ivalid & ATTR_SIZE) + if (ivalid & ATTR_SIZE) fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size; /* You can only _set_ these together (they may change by themselves) */ - if((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) { + if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) { fvalid |= FATTR_ATIME | FATTR_MTIME; #ifdef KERNEL_2_6 fattr->atime = iattr->ia_atime.tv_sec; @@ -640,9 +648,9 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) out.args[0].value = &outarg; request_send(fc, &in, &out); - if(!out.h.error) { - if(attr->ia_valid & ATTR_SIZE && - outarg.attr.size < i_size_read(inode)) + if (!out.h.error) { + if (attr->ia_valid & ATTR_SIZE && + outarg.attr.size < i_size_read(inode)) vmtruncate(inode, outarg.attr.size); change_attributes(inode, &outarg.attr); @@ -652,9 +660,9 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) static int _fuse_dentry_revalidate(struct dentry *entry) { - if(!entry->d_inode) + if (!entry->d_inode) return 0; - else if(entry->d_time && time_after(jiffies, entry->d_time)) { + else if (entry->d_time && time_after(jiffies, entry->d_time)) { struct inode *inode = entry->d_inode; struct fuse_entry_out outarg; int version; @@ -662,10 +670,10 @@ static int _fuse_dentry_revalidate(struct dentry *entry) ret = fuse_do_lookup(entry->d_parent->d_inode, entry, &outarg, &version); - if(ret) + if (ret) return 0; - if(outarg.ino != inode->i_ino) + if (outarg.ino != inode->i_ino) return 0; change_attributes(inode, &outarg.attr); @@ -685,7 +693,7 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, { struct inode *inode = entry->d_inode; int err = fuse_revalidate(entry); - if(!err) + if (!err) generic_fillattr(inode, stat); return err; @@ -727,6 +735,9 @@ static int fuse_setxattr(struct dentry *entry, const char *name, struct fuse_out out = FUSE_OUT_INIT; struct fuse_setxattr_in inarg; + if (size > FUSE_XATTR_SIZE_MAX) + return -E2BIG; + memset(&inarg, 0, sizeof(inarg)); inarg.size = size; inarg.flags = flags; @@ -766,7 +777,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name, in.args[1].value = name; /* This is really two different operations rolled into one */ out.numargs = 1; - if(size) { + if (size) { out.argvar = 1; out.args[0].size = size; out.args[0].value = value; @@ -775,7 +786,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name, out.args[0].value = &outarg; } request_send(fc, &in, &out); - if(!out.h.error) + if (!out.h.error) return size ? out.args[0].size : outarg.size; else return out.h.error; @@ -800,7 +811,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) in.args[0].value = &inarg; /* This is really two different operations rolled into one */ out.numargs = 1; - if(size) { + if (size) { out.argvar = 1; out.args[0].size = size; out.args[0].value = list; @@ -809,7 +820,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) out.args[0].value = &outarg; } request_send(fc, &in, &out); - if(!out.h.error) + if (!out.h.error) return size ? out.args[0].size : outarg.size; else return out.h.error; @@ -843,11 +854,11 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry) struct dentry *alias; int err = fuse_lookup_iget(dir, entry, &inode); - if(err) + if (err) return ERR_PTR(err); - if(inode && S_ISDIR(inode->i_mode) && - (alias = d_find_alias(inode)) != NULL) { + if (inode && S_ISDIR(inode->i_mode) && + (alias = d_find_alias(inode)) != NULL) { dput(alias); iput(inode); printk("fuse: cannot assign an existing directory\n"); diff --git a/kernel/file.c b/kernel/file.c index 8e24a01..2c9473f 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -19,7 +19,7 @@ #ifndef NO_MM #define filemap_fdatawrite filemap_fdatasync #else -#define filemap_fdatawrite do {} while(0) +#define filemap_fdatawrite do {} while (0) #endif #endif @@ -32,14 +32,14 @@ static int fuse_open(struct inode *inode, struct file *file) int err; err = generic_file_open(inode, file); - if(err) + if (err) return err; /* If opening the root node, no lookup has been performed on it, so the attributes must be refreshed */ - if(inode->i_ino == FUSE_ROOT_INO) { + if (inode->i_ino == FUSE_ROOT_INO) { int err = fuse_do_getattr(inode); - if(err) + if (err) return err; } @@ -52,7 +52,7 @@ static int fuse_open(struct inode *inode, struct file *file) in.args[0].size = sizeof(inarg); in.args[0].value = &inarg; request_send(fc, &in, &out); - if(!out.h.error && !(fc->flags & FUSE_KERNEL_CACHE)) { + if (!out.h.error && !(fc->flags & FUSE_KERNEL_CACHE)) { #ifdef KERNEL_2_6 invalidate_inode_pages(inode->i_mapping); #else @@ -70,11 +70,11 @@ static int fuse_release(struct inode *inode, struct file *file) struct fuse_open_in *inarg = NULL; unsigned int s = sizeof(struct fuse_in) + sizeof(struct fuse_open_in); - if(file->f_mode & FMODE_WRITE) + if (file->f_mode & FMODE_WRITE) filemap_fdatawrite(inode->i_mapping); in = kmalloc(s, GFP_NOFS); - if(!in) + if (!in) return -ENOMEM; memset(in, 0, s); inarg = (struct fuse_open_in *) (in + 1); @@ -85,7 +85,7 @@ static int fuse_release(struct inode *inode, struct file *file) in->numargs = 1; in->args[0].size = sizeof(struct fuse_open_in); in->args[0].value = inarg; - if(!request_send_noreply(fc, in)) + if (!request_send_noreply(fc, in)) return 0; kfree(in); @@ -142,9 +142,9 @@ static int fuse_readpage(struct file *file, struct page *page) out.args[0].value = buffer; request_send(fc, &in, &out); - if(!out.h.error) { + if (!out.h.error) { size_t outsize = out.args[0].size; - if(outsize < PAGE_CACHE_SIZE) + if (outsize < PAGE_CACHE_SIZE) memset(buffer + outsize, 0, PAGE_CACHE_SIZE - outsize); flush_dcache_page(page); SetPageUptodate(page); @@ -287,7 +287,7 @@ static ssize_t fuse_file_read(struct file *filp, char *buf, struct inode *inode = mapping->host; struct fuse_conn *fc = INO_FC(inode); - if(fc->flags & FUSE_LARGE_READ) + if (fc->flags & FUSE_LARGE_READ) fuse_file_bigread(mapping, inode, *ppos, count); return generic_file_read(filp, buf, count, ppos); @@ -318,7 +318,7 @@ static int write_buffer(struct inode *inode, struct page *page, in.args[1].value = buffer + offset; request_send(fc, &in, &out); kunmap(page); - if(out.h.error) + if (out.h.error) SetPageError(page); return out.h.error; @@ -331,11 +331,11 @@ static int get_write_count(struct inode *inode, struct page *page) int count; end_index = size >> PAGE_CACHE_SHIFT; - if(page->index < end_index) + if (page->index < end_index) count = PAGE_CACHE_SIZE; else { count = size & (PAGE_CACHE_SIZE - 1); - if(page->index > end_index || count == 0) + if (page->index > end_index || count == 0) return 0; } return count; @@ -349,9 +349,9 @@ static void write_buffer_end(struct fuse_conn *fc, struct fuse_in *in, struct page *page = (struct page *) _page; lock_page(page); - if(out->h.error) { + if (out->h.error) { SetPageError(page); - if(out->h.error == -ENOSPC) + if (out->h.error == -ENOSPC) set_bit(AS_ENOSPC, &page->mapping->flags); else set_bit(AS_EIO, &page->mapping->flags); @@ -375,7 +375,7 @@ static int write_buffer_nonblock(struct inode *inode, struct page *page, sizeof(struct fuse_write_in); in = kmalloc(s, GFP_NOFS); - if(!in) + if (!in) return -ENOMEM; memset(in, 0, s); out = (struct fuse_out *)(in + 1); @@ -394,8 +394,8 @@ static int write_buffer_nonblock(struct inode *inode, struct page *page, in->args[1].size = count; in->args[1].value = buffer + offset; err = request_send_nonblock(fc, in, out, write_buffer_end, page); - if(err) { - if(err != -EWOULDBLOCK) + if (err) { + if (err != -EWOULDBLOCK) SetPageError(page); kunmap(page); kfree(in); @@ -410,14 +410,14 @@ static int fuse_writepage(struct page *page, struct writeback_control *wbc) unsigned count = get_write_count(inode, page); err = -EINVAL; - if(count) { + if (count) { /* FIXME: check sync_mode, and wait for previous writes (or signal userspace to do this) */ - if(wbc->nonblocking) { + if (wbc->nonblocking) { err = write_buffer_nonblock(inode, page, 0, count); - if(!err) + if (!err) SetPageWriteback(page); - else if(err == -EWOULDBLOCK) { + else if (err == -EWOULDBLOCK) { __set_page_dirty_nobuffers(page); err = 0; } @@ -435,7 +435,7 @@ static int fuse_writepage(struct page *page) struct inode *inode = page->mapping->host; int count = get_write_count(inode, page); err = -EINVAL; - if(count) + if (count) err = write_buffer(inode, page, 0, count); unlock_page(page); @@ -457,9 +457,9 @@ static int fuse_commit_write(struct file *file, struct page *page, struct inode *inode = page->mapping->host; err = write_buffer(inode, page, offset, to - offset); - if(!err) { + if (!err) { loff_t pos = (page->index << PAGE_CACHE_SHIFT) + to; - if(pos > i_size_read(inode)) + if (pos > i_size_read(inode)) i_size_write(inode, pos); } return err; @@ -490,7 +490,7 @@ void fuse_init_file_inode(struct inode *inode) struct fuse_conn *fc = INO_FC(inode); /* Readahead somehow defeats big reads on 2.6 (says Michael Grigoriev) */ - if(fc->flags & FUSE_LARGE_READ) + if (fc->flags & FUSE_LARGE_READ) inode->i_mapping->backing_dev_info->ra_pages = 0; #endif inode->i_fop = &fuse_file_operations; diff --git a/kernel/inode.c b/kernel/inode.c index 22b424a..17c0f60 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -42,11 +42,11 @@ static void fuse_clear_inode(struct inode *inode) struct fuse_forget_in *inarg = NULL; unsigned int s = sizeof(struct fuse_in) + sizeof(struct fuse_forget_in); - if(fc == NULL) + if (fc == NULL) return; in = kmalloc(s, GFP_NOFS); - if(!in) + if (!in) return; memset(in, 0, s); inarg = (struct fuse_forget_in *) (in + 1); @@ -58,7 +58,7 @@ static void fuse_clear_inode(struct inode *inode) in->args[0].size = sizeof(struct fuse_forget_in); in->args[0].value = inarg; - if(!request_send_noreply(fc, in)) + if (!request_send_noreply(fc, in)) return; kfree(in); @@ -105,7 +105,7 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf) out.args[0].size = sizeof(outarg); out.args[0].value = &outarg; request_send(fc, &in, &out); - if(!out.h.error) + if (!out.h.error) convert_fuse_statfs(buf, &outarg.st); return out.h.error; @@ -117,17 +117,17 @@ static struct fuse_conn *get_conn(struct fuse_mount_data *d) struct file *file; struct inode *ino; - if(d == NULL) { + if (d == NULL) { printk("fuse_read_super: Bad mount data\n"); return NULL; } file = fget(d->fd); ino = NULL; - if(file) + if (file) ino = file->f_dentry->d_inode; - if(!ino || !proc_fuse_dev || proc_fuse_dev->low_ino != ino->i_ino) { + if (!ino || !proc_fuse_dev || proc_fuse_dev->low_ino != ino->i_ino) { printk("fuse_read_super: Bad file: %i\n", d->fd); goto out; } @@ -160,15 +160,15 @@ static struct dentry *fuse_get_dentry(struct super_block *sb, void *vobjp) struct inode *inode; struct dentry *entry; - if(ino == 0) + if (ino == 0) return ERR_PTR(-ESTALE); inode = ilookup(sb, ino); - if(!inode || inode->i_generation != generation) + if (!inode || inode->i_generation != generation) return ERR_PTR(-ESTALE); entry = d_alloc_anon(inode); - if(!entry) { + if (!entry) { iput(inode); return ERR_PTR(-ENOMEM); } @@ -194,8 +194,8 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent) struct inode *root; struct fuse_mount_data *d = data; - if(!capable(CAP_SYS_ADMIN)) { - if(d->flags & FUSE_ALLOW_OTHER) + if (!capable(CAP_SYS_ADMIN)) { + if (d->flags & FUSE_ALLOW_OTHER) return -EPERM; } @@ -209,10 +209,10 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent) #endif fc = get_conn(d); - if(fc == NULL) + if (fc == NULL) return -EINVAL; spin_lock(&fuse_lock); - if(fc->sb != NULL) { + if (fc->sb != NULL) { printk("fuse_read_super: connection already mounted\n"); spin_unlock(&fuse_lock); return -EINVAL; @@ -227,13 +227,13 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent) SB_FC(sb) = fc; root = get_root_inode(sb, d->rootmode); - if(root == NULL) { + if (root == NULL) { printk("fuse_read_super: failed to get root inode\n"); return -EINVAL; } sb->s_root = d_alloc_root(root); - if(!sb->s_root) + if (!sb->s_root) return -EINVAL; return 0; @@ -259,7 +259,7 @@ static struct super_block *fuse_read_super_compat(struct super_block *sb, void *data, int silent) { int err = fuse_read_super(sb, data, silent); - if(err) + if (err) return NULL; else return sb; @@ -273,7 +273,7 @@ int fuse_fs_init() int res; res = register_filesystem(&fuse_fs_type); - if(res) + if (res) printk("fuse: failed to register filesystem\n"); return res; diff --git a/kernel/util.c b/kernel/util.c index 6764157..faffb08 100644 --- a/kernel/util.c +++ b/kernel/util.c @@ -22,7 +22,7 @@ spinlock_t fuse_lock = SPIN_LOCK_UNLOCKED; /* Must be called with the fuse lock held */ void fuse_release_conn(struct fuse_conn *fc) { - if(fc->sb == NULL && fc->file == NULL) { + if (fc->sb == NULL && fc->file == NULL) { kfree(fc); } } @@ -36,11 +36,11 @@ int __init fuse_init(void) FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); res = fuse_fs_init(); - if(res) + if (res) goto err; res = fuse_dev_init(); - if(res) + if (res) goto err_fs_cleanup; return 0; -- 2.30.2