X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fproc%2Fgeneric.c;h=72ddf0faa71813ad5c34e4aeec87166560fe488f;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=d2c88ebb1b374f94178177b3de0ca2135d58be17;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/proc/generic.c b/fs/proc/generic.c index d2c88ebb1..72ddf0faa 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -17,8 +17,10 @@ #include #include #include +#include +#include +#include #include -#include static ssize_t proc_file_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos); @@ -59,7 +61,7 @@ proc_file_read(struct file *file, char __user *buf, size_t nbytes, return -ENOMEM; while ((nbytes > 0) && !eof) { - count = min_t(ssize_t, PROC_BLOCK_SIZE, nbytes); + count = min_t(size_t, PROC_BLOCK_SIZE, nbytes); start = NULL; if (dp->get_info) { @@ -230,14 +232,21 @@ out: static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) { struct inode *inode = dentry->d_inode; - int error = inode_setattr(inode, iattr); - if (!error) { - struct proc_dir_entry *de = PDE(inode); - de->uid = inode->i_uid; - de->gid = inode->i_gid; - de->mode = inode->i_mode; - } + struct proc_dir_entry *de = PDE(inode); + int error; + + error = inode_change_ok(inode, iattr); + if (error) + goto out; + error = inode_setattr(inode, iattr); + if (error) + goto out; + + de->uid = inode->i_uid; + de->gid = inode->i_gid; + de->mode = inode->i_mode; +out: return error; } @@ -278,7 +287,7 @@ static int xlate_proc_name(const char *name, } static DEFINE_IDR(proc_inum_idr); -static spinlock_t proc_inum_lock = SPIN_LOCK_UNLOCKED; /* protects the above */ +static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */ #define PROC_DYNAMIC_FIRST 0xF0000000UL @@ -288,18 +297,20 @@ static spinlock_t proc_inum_lock = SPIN_LOCK_UNLOCKED; /* protects the above */ */ static unsigned int get_inode_number(void) { - unsigned int i, inum = 0; + int i, inum = 0; + int error; retry: if (idr_pre_get(&proc_inum_idr, GFP_KERNEL) == 0) return 0; spin_lock(&proc_inum_lock); - i = idr_get_new(&proc_inum_idr, NULL); + error = idr_get_new(&proc_inum_idr, NULL, &i); spin_unlock(&proc_inum_lock); - - if (i == -1) + if (error == -EAGAIN) goto retry; + else if (error) + return 0; inum = (i & MAX_ID_MASK) + PROC_DYNAMIC_FIRST; @@ -319,21 +330,14 @@ static void release_inode_number(unsigned int inum) spin_unlock(&proc_inum_lock); } -static int -proc_readlink(struct dentry *dentry, char __user *buffer, int buflen) -{ - char *s = PDE(dentry->d_inode)->data; - return vfs_readlink(dentry, buffer, buflen, s); -} - static int proc_follow_link(struct dentry *dentry, struct nameidata *nd) { - char *s = PDE(dentry->d_inode)->data; - return vfs_follow_link(nd, s); + nd_set_link(nd, PDE(dentry->d_inode)->data); + return 0; } static struct inode_operations proc_link_inode_operations = { - .readlink = proc_readlink, + .readlink = generic_readlink, .follow_link = proc_follow_link, }; @@ -369,11 +373,15 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam for (de = de->subdir; de ; de = de->next) { if (de->namelen != dentry->d_name.len) continue; + if (!vx_hide_check(0, de->vx_flags)) + continue; if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { unsigned int ino = de->low_ino; error = -EINVAL; inode = proc_get_inode(dir->i_sb, ino, de); + /* generic proc entries belong to the host */ + inode->i_xid = 0; break; } } @@ -445,9 +453,12 @@ int proc_readdir(struct file * filp, } do { + if (!vx_hide_check(0, de->vx_flags)) + goto skip; if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino, de->mode >> 12) < 0) goto out; + skip: filp->f_pos++; de = de->next; } while (de); @@ -548,6 +559,11 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, if (!(*parent) && xlate_proc_name(name, parent, &fn) != 0) goto out; + + /* At this point there must not be any '/' characters beyond *fn */ + if (strchr(fn, '/')) + goto out; + len = strlen(fn); ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL); @@ -559,6 +575,7 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, ent->namelen = len; ent->mode = mode; ent->nlink = nlink; + ent->vx_flags = IATTR_PROC_DEFAULT; out: return ent; } @@ -579,7 +596,8 @@ struct proc_dir_entry *proc_symlink(const char *name, kfree(ent->data); kfree(ent); ent = NULL; - } + } else + ent->vx_flags = IATTR_PROC_SYMLINK; } else { kfree(ent); ent = NULL;