/* * linux/kernel/vserver/inode.c * * Virtual Server: File System Support * * Copyright (C) 2004 Herbert Pötzl * * V0.01 separated from vcontext V0.05 * */ #include //#include //#include //#include //#include //#include #include #include #include //#include #include #include #include #include int vc_get_iattr(uint32_t id, void *data) { struct super_block *sb; struct inode *in; struct vcmd_ctx_iattr_v0 vc_data; int ret; if (!vx_check(0, VX_ADMIN)) return -ENOSYS; if (copy_from_user (&vc_data, data, sizeof(vc_data))) return -EFAULT; ret = -ESRCH; sb = get_super(to_kdev_t(id)); if (!sb) goto out; in = iget(sb, vc_data.ino); if (!in) goto out_drop_sb; vc_data.xid = in->i_xid; vc_data.flags = IATTR_XID | (IS_BARRIER(in) ? IATTR_BARRIER : 0) | (IS_IUNLINK(in) ? IATTR_IUNLINK : 0); vc_data.mask = IATTR_XID | IATTR_BARRIER | IATTR_IUNLINK; if (sb->s_magic == PROC_SUPER_MAGIC) { vc_data.flags |= (in->u.proc_i.vx_flags & IATTR_FLAGS); vc_data.mask |= IATTR_FLAGS; } ret = 0; if (copy_to_user (data, &vc_data, sizeof(vc_data))) ret = -EFAULT; iput(in); out_drop_sb: drop_super(sb); out: return ret; } int vc_set_iattr(uint32_t id, void *data) { struct super_block *sb; struct inode *in; struct vcmd_ctx_iattr_v0 vc_data; int ret; if (!vx_check(0, VX_ADMIN)) return -ENOSYS; if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE)) return -EPERM; if (copy_from_user (&vc_data, data, sizeof(vc_data))) return -EFAULT; ret = -ESRCH; sb = get_super(to_kdev_t(id)); if (!sb) goto out; ret = -ENOTSUP; if ((vc_data.mask & IATTR_FLAGS) && (sb->s_magic != PROC_SUPER_MAGIC)) goto out_drop_sb; ret = -ESRCH; in = iget(sb, vc_data.ino); if (!in) goto out_drop_sb; lock_kernel(); if (vc_data.mask & IATTR_XID) in->i_xid = vc_data.xid; if (vc_data.mask & IATTR_FLAGS) { unsigned int flags = in->u.proc_i.vx_flags; unsigned int mask = vc_data.mask; in->u.proc_i.vx_flags = (flags & ~(mask & IATTR_FLAGS)) | (vc_data.flags & IATTR_FLAGS); } if (vc_data.mask & IATTR_BARRIER) in->i_flags = (in->i_flags & ~S_BARRIER) | ((vc_data.flags & IATTR_BARRIER) ? S_BARRIER : 0); if (vc_data.mask & IATTR_IUNLINK) in->i_flags = (in->i_flags & ~S_IUNLINK) | ((vc_data.flags & IATTR_IUNLINK) ? S_IUNLINK : 0); mark_inode_dirty(in); unlock_kernel(); iput(in); out_drop_sb: drop_super(sb); out: return ret; } #include int vx_proc_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { struct proc_dir_entry *entry; int error = 0; int flags; if (inode->i_ino < PROC_DYNAMIC_FIRST || inode->i_ino >= PROC_DYNAMIC_FIRST+PROC_NDYNAMIC) return -ENOTTY; entry = (struct proc_dir_entry *) inode->u.generic_ip; switch(cmd) { case FIOC_GETXFLG: { /* fixme: if stealth, return -ENOTTY */ error = -EPERM; flags = entry->vx_flags; if (capable(CAP_CONTEXT)) error = put_user(flags, (int *) arg); break; } case FIOC_SETXFLG: { /* fixme: if stealth, return -ENOTTY */ error = -EPERM; if (!capable(CAP_CONTEXT)) break; error = -EROFS; if (IS_RDONLY(inode)) break; error = -EFAULT; if (get_user(flags, (int *) arg)) break; error = 0; entry->vx_flags = flags; break; } default: return -ENOTTY; } return error; }