#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/idr.h>
+#include <linux/namei.h>
+#include <linux/vs_base.h>
+#include <linux/vserver/inode.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
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;
}
*/
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;
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,
};
return 1;
}
+static int proc_revalidate_dentry(struct dentry *de, struct nameidata *nd)
+{
+ /* maybe add a check if it's really necessary? */
+ return 0;
+}
+
static struct dentry_operations proc_dentry_operations =
{
+ .d_revalidate = proc_revalidate_dentry,
.d_delete = proc_delete_dentry,
};
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);
+ inode->i_xid = vx_current_xid();
break;
}
}
}
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);
ent->namelen = len;
ent->mode = mode;
ent->nlink = nlink;
+ ent->vx_flags = IATTR_PROC_DEFAULT;
out:
return ent;
}
kfree(ent->data);
kfree(ent);
ent = NULL;
- }
+ } else
+ ent->vx_flags = IATTR_PROC_SYMLINK;
} else {
kfree(ent);
ent = NULL;
parent->nlink--;
proc_kill_inodes(de);
de->nlink = 0;
- WARN_ON(de->subdir);
+ BUG_ON(de->subdir);
if (!atomic_read(&de->count))
free_proc_entry(de);
else {