--- linux-2.6.11.11/fs/attr.c 2005-03-02 12:38:43 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/attr.c 2005-06-01 14:34:17 +0200 @@ -56,6 +59,28 @@ int inode_change_ok(struct inode *inode, if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) goto error; } + + /* Check for evil vserver activity */ + if (vx_check(0, VX_ADMIN)) + goto fine; + + if (IS_BARRIER(inode)) { + vxwprintk(1, "xid=%d messing with the barrier.", + vx_current_xid()); + goto error; + } + switch (inode->i_sb->s_magic) { + case PROC_SUPER_MAGIC: + vxwprintk(1, "xid=%d messing with the procfs.", + vx_current_xid()); + goto error; + case DEVPTS_SUPER_MAGIC: + if (vx_check(inode->i_xid, VX_IDENT)) + goto fine; + vxwprintk(1, "xid=%d messing with the devpts.", + vx_current_xid()); + goto error; + } fine: retval = 0; error: --- linux-2.6.11.11/fs/attr.c 2005-03-02 12:38:43 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/attr.c 2005-06-01 14:34:17 +0200 @@ -103,6 +148,8 @@ int inode_setattr(struct inode * inode, mode &= ~S_ISGID; inode->i_mode = mode; } + if (ia_valid & ATTR_ATTR_FLAG) + inode_setattr_flags(inode, attr->ia_attr_flags); mark_inode_dirty(inode); out: return error; --- linux-2.6.11.11/fs/devpts/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/devpts/inode.c 2005-06-01 14:34:17 +0200 @@ -20,8 +20,6 @@ #include #include -#define DEVPTS_SUPER_MAGIC 0x1cd1 - extern struct xattr_handler devpts_xattr_security_handler; static struct xattr_handler *devpts_xattr_handlers[] = { --- linux-2.6.11.11/fs/devpts/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/devpts/inode.c 2005-06-01 14:34:17 +0200 @@ -31,6 +29,15 @@ static struct xattr_handler *devpts_xatt NULL }; +static int devpts_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + int ret = -EACCES; + + if (vx_check(inode->i_xid, VX_IDENT)) + ret = generic_permission(inode, mask, NULL); + return ret; +} + static struct inode_operations devpts_file_inode_operations = { #ifdef CONFIG_DEVPTS_FS_XATTR .setxattr = generic_setxattr, --- linux-2.6.11.11/fs/devpts/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/devpts/inode.c 2005-06-01 14:34:17 +0200 @@ -38,6 +45,7 @@ static struct inode_operations devpts_fi .listxattr = generic_listxattr, .removexattr = generic_removexattr, #endif + .permission = devpts_permission, }; static struct vfsmount *devpts_mnt; --- linux-2.6.11.11/fs/devpts/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/devpts/inode.c 2005-06-01 14:34:17 +0200 @@ -88,6 +96,68 @@ static int devpts_remount(struct super_b return 0; } +static int devpts_readdir(struct file * filp, void * dirent, filldir_t filldir) +{ + struct dentry *dentry = filp->f_dentry; + struct dentry *cursor = filp->private_data; + struct list_head *p, *q = &cursor->d_child; + ino_t ino; + int i = filp->f_pos; + + switch (i) { + case 0: + ino = dentry->d_inode->i_ino; + if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) + break; + filp->f_pos++; + i++; + /* fallthrough */ + case 1: + ino = parent_ino(dentry); + if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) + break; + filp->f_pos++; + i++; + /* fallthrough */ + default: + spin_lock(&dcache_lock); + if (filp->f_pos == 2) { + list_del(q); + list_add(q, &dentry->d_subdirs); + } + for (p=q->next; p != &dentry->d_subdirs; p=p->next) { + struct dentry *next; + next = list_entry(p, struct dentry, d_child); + if (d_unhashed(next) || !next->d_inode) + continue; + if (!vx_check(next->d_inode->i_xid, VX_IDENT)) + continue; + + spin_unlock(&dcache_lock); + if (filldir(dirent, next->d_name.name, + next->d_name.len, filp->f_pos, + next->d_inode->i_ino, DT_CHR) < 0) + return 0; + spin_lock(&dcache_lock); + /* next is still alive */ + list_del(q); + list_add(q, p); + p = q; + filp->f_pos++; + } + spin_unlock(&dcache_lock); + } + return 0; +} + +static struct file_operations devpts_dir_operations = { + .open = dcache_dir_open, + .release = dcache_dir_close, + .llseek = dcache_dir_lseek, + .read = generic_read_dir, + .readdir = devpts_readdir, +}; + static struct super_operations devpts_sops = { .statfs = simple_statfs, .remount_fs = devpts_remount, --- linux-2.6.11.11/fs/ext2/ialloc.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/ialloc.c 2005-06-01 14:34:17 +0200 @@ -579,7 +591,8 @@ got: inode->i_blocks = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; memset(ei->i_data, 0, sizeof(ei->i_data)); - ei->i_flags = EXT2_I(dir)->i_flags & ~EXT2_BTREE_FL; + ei->i_flags = EXT2_I(dir)->i_flags & + ~(EXT2_BTREE_FL|EXT2_IUNLINK_FL|EXT2_BARRIER_FL); if (S_ISLNK(mode)) ei->i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL); /* dirsync is only applied to directories */ --- linux-2.6.11.11/fs/ext2/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c 2005-06-01 14:34:17 +0200 @@ -52,6 +53,8 @@ static inline int ext2_inode_is_fast_sym inode->i_blocks - ea_blocks == 0); } +static void ext2_truncate_nocheck (struct inode * inode); + /* * Called at the last iput() if i_nlink is zero. */ --- linux-2.6.11.11/fs/ext2/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c 2005-06-01 14:34:17 +0200 @@ -65,7 +68,7 @@ void ext2_delete_inode (struct inode * i inode->i_size = 0; if (inode->i_blocks) - ext2_truncate (inode); + ext2_truncate_nocheck(inode); ext2_free_inode (inode); return; --- linux-2.6.11.11/fs/ext2/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c 2005-06-01 14:34:17 +0200 @@ -865,7 +868,7 @@ static void ext2_free_branches(struct in ext2_free_data(inode, p, q); } -void ext2_truncate (struct inode * inode) +static void ext2_truncate_nocheck(struct inode * inode) { __le32 *i_data = EXT2_I(inode)->i_data; int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); --- linux-2.6.11.11/fs/ext2/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c 2005-06-01 14:34:17 +0200 @@ -882,8 +885,6 @@ void ext2_truncate (struct inode * inode return; if (ext2_inode_is_fast_symlink(inode)) return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; ext2_discard_prealloc(inode); --- linux-2.6.11.11/fs/ext2/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c 2005-06-01 14:34:17 +0200 @@ -1005,17 +1006,28 @@ Egdp: return ERR_PTR(-EIO); } +void ext2_truncate (struct inode * inode) +{ + if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + return; + ext2_truncate_nocheck(inode); +} + void ext2_set_inode_flags(struct inode *inode) { unsigned int flags = EXT2_I(inode)->i_flags; - inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); + inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_IUNLINK|S_BARRIER|S_NOATIME|S_DIRSYNC); if (flags & EXT2_SYNC_FL) inode->i_flags |= S_SYNC; if (flags & EXT2_APPEND_FL) inode->i_flags |= S_APPEND; if (flags & EXT2_IMMUTABLE_FL) inode->i_flags |= S_IMMUTABLE; + if (flags & EXT2_IUNLINK_FL) + inode->i_flags |= S_IUNLINK; + if (flags & EXT2_BARRIER_FL) + inode->i_flags |= S_BARRIER; if (flags & EXT2_NOATIME_FL) inode->i_flags |= S_NOATIME; if (flags & EXT2_DIRSYNC_FL) --- linux-2.6.11.11/fs/ext2/ioctl.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/ioctl.c 2005-06-01 14:34:17 +0200 @@ -49,7 +49,9 @@ int ext2_ioctl (struct inode * inode, st * * This test looks nicer. Thanks to Pauline Middelink */ - if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) { + if ((oldflags & EXT2_IMMUTABLE_FL) || + ((flags ^ oldflags) & (EXT2_APPEND_FL | + EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL))) { if (!capable(CAP_LINUX_IMMUTABLE)) return -EPERM; } --- linux-2.6.11.11/fs/ext3/ialloc.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/ialloc.c 2005-06-01 14:34:17 +0200 @@ -566,7 +578,8 @@ got: ei->i_dir_start_lookup = 0; ei->i_disksize = 0; - ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL; + ei->i_flags = EXT3_I(dir)->i_flags & + ~(EXT3_INDEX_FL|EXT3_IUNLINK_FL|EXT3_BARRIER_FL); if (S_ISLNK(mode)) ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL); /* dirsync only applies to directories */ --- linux-2.6.11.11/fs/ext3/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c 2005-06-01 14:34:17 +0200 @@ -180,6 +181,8 @@ static int ext3_journal_test_restart(han return ext3_journal_restart(handle, blocks_for_truncate(inode)); } +static void ext3_truncate_nocheck (struct inode *inode); + /* * Called at the last iput() if i_nlink is zero. */ --- linux-2.6.11.11/fs/ext3/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c 2005-06-01 14:34:17 +0200 @@ -203,7 +206,7 @@ void ext3_delete_inode (struct inode * i handle->h_sync = 1; inode->i_size = 0; if (inode->i_blocks) - ext3_truncate(inode); + ext3_truncate_nocheck(inode); /* * Kill off the orphan record which ext3_truncate created. * AKPM: I think this can be inside the above `if'. --- linux-2.6.11.11/fs/ext3/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c 2005-06-01 14:34:17 +0200 @@ -2050,7 +2053,7 @@ static void ext3_free_branches(handle_t * ext3_truncate() run will find them and release them. */ -void ext3_truncate(struct inode * inode) +void ext3_truncate_nocheck(struct inode * inode) { handle_t *handle; struct ext3_inode_info *ei = EXT3_I(inode); --- linux-2.6.11.11/fs/ext3/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c 2005-06-01 14:34:17 +0200 @@ -2071,8 +2074,6 @@ void ext3_truncate(struct inode * inode) return; if (ext3_inode_is_fast_symlink(inode)) return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; ext3_discard_reservation(inode); --- linux-2.6.11.11/fs/ext3/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c 2005-06-01 14:34:17 +0200 @@ -2390,17 +2391,28 @@ int ext3_get_inode_loc(struct inode *ino !(EXT3_I(inode)->i_state & EXT3_STATE_XATTR)); } +void ext3_truncate(struct inode * inode) +{ + if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + return; + ext3_truncate_nocheck(inode); +} + void ext3_set_inode_flags(struct inode *inode) { unsigned int flags = EXT3_I(inode)->i_flags; - inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); + inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_IUNLINK|S_BARRIER|S_NOATIME|S_DIRSYNC); if (flags & EXT3_SYNC_FL) inode->i_flags |= S_SYNC; if (flags & EXT3_APPEND_FL) inode->i_flags |= S_APPEND; if (flags & EXT3_IMMUTABLE_FL) inode->i_flags |= S_IMMUTABLE; + if (flags & EXT3_IUNLINK_FL) + inode->i_flags |= S_IUNLINK; + if (flags & EXT3_BARRIER_FL) + inode->i_flags |= S_BARRIER; if (flags & EXT3_NOATIME_FL) inode->i_flags |= S_NOATIME; if (flags & EXT3_DIRSYNC_FL) --- linux-2.6.11.11/fs/ext3/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c 2005-06-01 14:34:17 +0200 @@ -2791,6 +2858,12 @@ int ext3_setattr(struct dentry *dentry, ext3_journal_stop(handle); } + if (ia_valid & ATTR_ATTR_FLAG) { + rc = ext3_setattr_flags(inode, attr->ia_attr_flags); + if (!error) + error = rc; + } + rc = inode_setattr(inode, attr); /* If inode_setattr's call to ext3_truncate failed to get a --- linux-2.6.11.11/fs/ext3/ioctl.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/ioctl.c 2005-06-01 14:34:17 +0200 @@ -58,7 +59,9 @@ int ext3_ioctl (struct inode * inode, st * * This test looks nicer. Thanks to Pauline Middelink */ - if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { + if ((oldflags & EXT3_IMMUTABLE_FL) || + ((flags ^ oldflags) & (EXT3_APPEND_FL | + EXT3_IMMUTABLE_FL | EXT3_IUNLINK_FL))) { if (!capable(CAP_LINUX_IMMUTABLE)) return -EPERM; } --- linux-2.6.11.11/fs/nfs/inode.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/nfs/inode.c 2005-06-01 14:34:17 +0200 @@ -730,7 +738,12 @@ nfs_fhget(struct super_block *sb, struct out: return inode; - +/* FIXME +fail_dlim: + make_bad_inode(inode); + iput(inode); + inode = NULL; +*/ out_no_inode: printk("nfs_fhget: iget failed\n"); goto out; --- linux-2.6.11.11/fs/reiserfs/inode.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/inode.c 2005-06-01 14:34:17 +0200 @@ -2787,6 +2834,10 @@ int reiserfs_setattr(struct dentry *dent } error = inode_change_ok(inode, attr) ; + + if (!error && attr->ia_valid & ATTR_ATTR_FLAG) + reiserfs_setattr_flags(inode, attr->ia_attr_flags); + if (!error) { if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { --- linux-2.6.11.11/fs/reiserfs/ioctl.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/ioctl.c 2005-06-01 14:34:17 +0200 @@ -22,7 +22,7 @@ static int reiserfs_unpack (struct inode int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { - unsigned int flags; + unsigned int flags, oldflags; switch (cmd) { case REISERFS_IOC_UNPACK: --- linux-2.6.11.11/fs/reiserfs/ioctl.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/ioctl.c 2005-06-01 14:34:17 +0200 @@ -38,6 +38,7 @@ int reiserfs_ioctl (struct inode * inode case REISERFS_IOC_GETFLAGS: flags = REISERFS_I(inode) -> i_attrs; i_attrs_to_sd_attrs( inode, ( __u16 * ) &flags ); + flags &= REISERFS_FL_USER_VISIBLE; return put_user(flags, (int __user *) arg); case REISERFS_IOC_SETFLAGS: { if (IS_RDONLY(inode)) --- linux-2.6.11.11/fs/reiserfs/ioctl.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/ioctl.c 2005-06-01 14:34:17 +0200 @@ -49,8 +50,12 @@ int reiserfs_ioctl (struct inode * inode if (get_user(flags, (int __user *) arg)) return -EFAULT; - if ( ( ( flags ^ REISERFS_I(inode) -> i_attrs) & ( REISERFS_IMMUTABLE_FL | REISERFS_APPEND_FL)) && - !capable( CAP_LINUX_IMMUTABLE ) ) + oldflags = REISERFS_I(inode) -> i_attrs; + if ( ( (oldflags & REISERFS_IMMUTABLE_FL) || + ( (flags ^ oldflags) & + (REISERFS_IMMUTABLE_FL | REISERFS_IUNLINK_FL | + REISERFS_APPEND_FL) ) ) && + !capable( CAP_LINUX_IMMUTABLE ) ) return -EPERM; if( ( flags & REISERFS_NOTAIL_FL ) && --- linux-2.6.11.11/fs/reiserfs/ioctl.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/ioctl.c 2005-06-01 14:34:17 +0200 @@ -61,6 +66,9 @@ int reiserfs_ioctl (struct inode * inode if( result ) return result; } + + flags = flags & REISERFS_FL_USER_MODIFYABLE; + flags |= oldflags & ~REISERFS_FL_USER_MODIFYABLE; sd_attrs_to_i_attrs( flags, inode ); REISERFS_I(inode) -> i_attrs = flags; inode->i_ctime = CURRENT_TIME_SEC; --- linux-2.6.11.11/fs/super.c 2005-03-02 12:38:46 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/super.c 2005-06-01 14:34:17 +0200 @@ -826,6 +834,13 @@ do_kern_mount(const char *fstype, int fl sb = type->get_sb(type, flags, name, data); if (IS_ERR(sb)) goto out_free_secdata; + + error = -EPERM; + if (!capable(CAP_SYS_ADMIN) && !sb->s_bdev && + (sb->s_magic != PROC_SUPER_MAGIC) && + (sb->s_magic != DEVPTS_SUPER_MAGIC)) + goto out_sb; + error = security_sb_kern_mount(sb, secdata); if (error) goto out_sb; --- linux-2.6.11.11/fs/sysfs/mount.c 2005-03-02 12:38:46 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/sysfs/mount.c 2005-06-01 14:34:17 +0200 @@ -11,8 +11,6 @@ #include "sysfs.h" -/* Random magic number */ -#define SYSFS_MAGIC 0x62656572 struct vfsmount *sysfs_mount; struct super_block * sysfs_sb = NULL; --- linux-2.6.11.11/fs/sysfs/mount.c 2005-03-02 12:38:46 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/sysfs/mount.c 2005-06-01 14:34:17 +0200 @@ -37,7 +35,7 @@ static int sysfs_fill_super(struct super sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - sb->s_magic = SYSFS_MAGIC; + sb->s_magic = SYSFS_SUPER_MAGIC; sb->s_op = &sysfs_ops; sb->s_time_gran = 1; sysfs_sb = sb; --- linux-2.6.11.11/include/linux/devpts_fs.h 2004-08-14 12:55:59 +0200 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/devpts_fs.h 2005-06-01 14:34:17 +0200 @@ -30,5 +30,7 @@ static inline void devpts_pty_kill(int n #endif +#define DEVPTS_SUPER_MAGIC 0x00001cd1 + #endif /* _LINUX_DEVPTS_FS_H */ --- linux-2.6.11.11/include/linux/shmem_fs.h 2004-10-23 05:06:23 +0200 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/shmem_fs.h 2005-06-01 14:34:17 +0200 @@ -8,6 +8,9 @@ #define SHMEM_NR_DIRECT 16 +#define TMPFS_SUPER_MAGIC 0x01021994 + + struct shmem_inode_info { spinlock_t lock; unsigned long flags; --- linux-2.6.11.11/include/linux/sysfs.h 2005-03-02 12:38:53 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/sysfs.h 2005-06-01 14:34:17 +0200 @@ -12,6 +12,8 @@ #include +#define SYSFS_SUPER_MAGIC 0x62656572 + struct kobject; struct module; --- linux-2.6.11.11/include/linux/vserver/inode.h 1970-01-01 01:00:00 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/vserver/inode.h 2005-06-01 14:34:17 +0200 @@ -0,0 +1,41 @@ +#ifndef _VX_INODE_H +#define _VX_INODE_H + + +#define IATTR_XID 0x01000000 + +#define IATTR_ADMIN 0x00000001 +#define IATTR_WATCH 0x00000002 +#define IATTR_HIDE 0x00000004 +#define IATTR_FLAGS 0x00000007 + +#define IATTR_BARRIER 0x00010000 +#define IATTR_IUNLINK 0x00020000 +#define IATTR_IMMUTABLE 0x00040000 + +#ifdef __KERNEL__ + +#ifndef CONFIG_VSERVER +#warning config options missing +#endif + +#ifdef CONFIG_VSERVER_PROC_SECURE +#define IATTR_PROC_DEFAULT ( IATTR_ADMIN | IATTR_HIDE ) +#define IATTR_PROC_SYMLINK ( IATTR_ADMIN ) +#else +#define IATTR_PROC_DEFAULT ( IATTR_ADMIN ) +#define IATTR_PROC_SYMLINK ( IATTR_ADMIN ) +#endif + +#define vx_hide_check(c,m) (((m) & IATTR_HIDE) ? vx_check(c,m) : 1) + +#endif /* __KERNEL__ */ + +/* inode ioctls */ + +#define FIOC_GETXFLG _IOR('x', 5, long) +#define FIOC_SETXFLG _IOW('x', 6, long) + +#else /* _VX_INODE_H */ +#warning duplicate inclusion +#endif /* _VX_INODE_H */ --- linux-2.6.11.11/kernel/vserver/inode.c 1970-01-01 01:00:00 +0100 +++ linux-2.6.11.11-vs2.0-rc3/kernel/vserver/inode.c 2005-06-01 14:34:17 +0200 @@ -0,0 +1,365 @@ +/* + * linux/kernel/vserver/inode.c + * + * Virtual Server: File System Support + * + * Copyright (C) 2004-2005 Herbert Pötzl + * + * V0.01 separated from vcontext V0.05 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +static int __vc_get_iattr(struct inode *in, uint32_t *xid, uint32_t *flags, uint32_t *mask) +{ + struct proc_dir_entry *entry; + + if (!in || !in->i_sb) + return -ESRCH; + + *flags = IATTR_XID + | (IS_BARRIER(in) ? IATTR_BARRIER : 0) + | (IS_IUNLINK(in) ? IATTR_IUNLINK : 0) + | (IS_IMMUTABLE(in) ? IATTR_IMMUTABLE : 0); + *mask = IATTR_IUNLINK | IATTR_IMMUTABLE; + + if (S_ISDIR(in->i_mode)) + *mask |= IATTR_BARRIER; + + if (in->i_sb->s_flags & MS_TAGXID) { + *xid = in->i_xid; + *mask |= IATTR_XID; + } + + switch (in->i_sb->s_magic) { + case PROC_SUPER_MAGIC: + entry = PROC_I(in)->pde; + + /* check for specific inodes? */ + if (entry) + *mask |= IATTR_FLAGS; + if (entry) + *flags |= (entry->vx_flags & IATTR_FLAGS); + else + *flags |= (PROC_I(in)->vx_flags & IATTR_FLAGS); + break; + + case DEVPTS_SUPER_MAGIC: + *xid = in->i_xid; + *mask |= IATTR_XID; + break; + + default: + break; + } + return 0; +} + +int vc_get_iattr(uint32_t id, void __user *data) +{ + struct nameidata nd; + struct vcmd_ctx_iattr_v1 vc_data = { .xid = -1 }; + int ret; + + if (!vx_check(0, VX_ADMIN)) + return -ENOSYS; + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + ret = user_path_walk_link(vc_data.name, &nd); + if (!ret) { + ret = __vc_get_iattr(nd.dentry->d_inode, + &vc_data.xid, &vc_data.flags, &vc_data.mask); + path_release(&nd); + } + if (ret) + return ret; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + ret = -EFAULT; + return ret; +} + +#ifdef CONFIG_COMPAT + +int vc_get_iattr_x32(uint32_t id, void __user *data) +{ + struct nameidata nd; + struct vcmd_ctx_iattr_v1_x32 vc_data = { .xid = -1 }; + int ret; + + if (!vx_check(0, VX_ADMIN)) + return -ENOSYS; + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd); + if (!ret) { + ret = __vc_get_iattr(nd.dentry->d_inode, + &vc_data.xid, &vc_data.flags, &vc_data.mask); + path_release(&nd); + } + if (ret) + return ret; + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + ret = -EFAULT; + return ret; +} + +#endif /* CONFIG_COMPAT */ + + +static int __vc_set_iattr(struct dentry *de, uint32_t *xid, uint32_t *flags, uint32_t *mask) +{ + struct inode *in = de->d_inode; + int error = 0, is_proc = 0, has_xid = 0; + + if (!in || !in->i_sb) + return -ESRCH; + + is_proc = (in->i_sb->s_magic == PROC_SUPER_MAGIC); + if ((*mask & IATTR_FLAGS) && !is_proc) + return -EINVAL; + + has_xid = (in->i_sb->s_flags & MS_TAGXID) || + (in->i_sb->s_magic == DEVPTS_SUPER_MAGIC); + if ((*mask & IATTR_XID) && !has_xid) + return -EINVAL; + + down(&in->i_sem); + if (*mask & IATTR_XID) + in->i_xid = *xid; + + if (*mask & IATTR_FLAGS) { + struct proc_dir_entry *entry = PROC_I(in)->pde; + unsigned int iflags = PROC_I(in)->vx_flags; + + iflags = (iflags & ~(*mask & IATTR_FLAGS)) + | (*flags & IATTR_FLAGS); + PROC_I(in)->vx_flags = iflags; + if (entry) + entry->vx_flags = iflags; + } + + if (*mask & (IATTR_BARRIER | IATTR_IUNLINK | IATTR_IMMUTABLE)) { + struct iattr attr; + + attr.ia_valid = ATTR_ATTR_FLAG; + attr.ia_attr_flags = + (IS_IMMUTABLE(in) ? ATTR_FLAG_IMMUTABLE : 0) | + (IS_IUNLINK(in) ? ATTR_FLAG_IUNLINK : 0) | + (IS_BARRIER(in) ? ATTR_FLAG_BARRIER : 0); + + if (*mask & IATTR_IMMUTABLE) { + if (*flags & IATTR_IMMUTABLE) + attr.ia_attr_flags |= ATTR_FLAG_IMMUTABLE; + else + attr.ia_attr_flags &= ~ATTR_FLAG_IMMUTABLE; + } + if (*mask & IATTR_IUNLINK) { + if (*flags & IATTR_IUNLINK) + attr.ia_attr_flags |= ATTR_FLAG_IUNLINK; + else + attr.ia_attr_flags &= ~ATTR_FLAG_IUNLINK; + } + if (S_ISDIR(in->i_mode) && (*mask & IATTR_BARRIER)) { + if (*flags & IATTR_BARRIER) + attr.ia_attr_flags |= ATTR_FLAG_BARRIER; + else + attr.ia_attr_flags &= ~ATTR_FLAG_BARRIER; + } + if (in->i_op && in->i_op->setattr) + error = in->i_op->setattr(de, &attr); + else { + error = inode_change_ok(in, &attr); + if (!error) + error = inode_setattr(in, &attr); + } + } + + mark_inode_dirty(in); + up(&in->i_sem); + return 0; +} + +int vc_set_iattr(uint32_t id, void __user *data) +{ + struct nameidata nd; + struct vcmd_ctx_iattr_v1 vc_data; + int ret; + + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE)) + return -EPERM; + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + ret = user_path_walk_link(vc_data.name, &nd); + if (!ret) { + ret = __vc_set_iattr(nd.dentry, + &vc_data.xid, &vc_data.flags, &vc_data.mask); + path_release(&nd); + } + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + ret = -EFAULT; + return ret; +} + +#ifdef CONFIG_COMPAT + +int vc_set_iattr_x32(uint32_t id, void __user *data) +{ + struct nameidata nd; + struct vcmd_ctx_iattr_v1_x32 vc_data; + int ret; + + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE)) + return -EPERM; + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd); + if (!ret) { + ret = __vc_set_iattr(nd.dentry, + &vc_data.xid, &vc_data.flags, &vc_data.mask); + path_release(&nd); + } + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + ret = -EFAULT; + return ret; +} + +#endif /* CONFIG_COMPAT */ + +#ifdef CONFIG_VSERVER_LEGACY + +#define PROC_DYNAMIC_FIRST 0xF0000000UL + +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) + return -ENOTTY; + + entry = PROC_I(inode)->pde; + if (!entry) + return -ENOTTY; + + 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; +} +#endif + + +int vx_parse_xid(char *string, xid_t *xid, int remove) +{ + static match_table_t tokens = { + {1, "xid=%u"}, + {0, NULL} + }; + substring_t args[MAX_OPT_ARGS]; + int token, option = 0; + + if (!string) + return 0; + + token = match_token(string, tokens, args); + if (token && xid && !match_int(args, &option)) + *xid = option; + + vxdprintk(VXD_CBIT(xid, 7), + "vx_parse_xid(»%s«): %d:#%d", + string, token, option); + + if (token && remove) { + char *p = strstr(string, "xid="); + char *q = p; + + if (p) { + while (*q != '\0' && *q != ',') + q++; + while (*q) + *p++ = *q++; + while (*p) + *p++ = '\0'; + } + } + return token; +} + +void vx_propagate_xid(struct nameidata *nd, struct inode *inode) +{ + xid_t new_xid = 0; + struct vfsmount *mnt; + int propagate; + + if (!nd) + return; + mnt = nd->mnt; + if (!mnt) + return; + + propagate = (mnt->mnt_flags & MNT_XID); + if (propagate) + new_xid = mnt->mnt_xid; + + vxdprintk(VXD_CBIT(xid, 7), + "vx_propagate_xid(%p[#%lu.%d]): %d,%d", + inode, inode->i_ino, inode->i_xid, + new_xid, (propagate)?1:0); + + if (propagate) + inode->i_xid = new_xid; +} + +#include + +EXPORT_SYMBOL_GPL(vx_propagate_xid); + --- linux-2.6.11.11/mm/shmem.c 2005-03-02 12:39:08 +0100 +++ linux-2.6.11.11-vs2.0-rc3/mm/shmem.c 2005-06-01 14:34:17 +0200 @@ -51,7 +51,6 @@ #include /* This magic number is used in glibc for posix shared memory */ -#define TMPFS_MAGIC 0x01021994 #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long)) #define ENTRIES_PER_PAGEPAGE (ENTRIES_PER_PAGE*ENTRIES_PER_PAGE) --- linux-2.6.11.11/mm/shmem.c 2005-03-02 12:39:08 +0100 +++ linux-2.6.11.11-vs2.0-rc3/mm/shmem.c 2005-06-01 14:34:17 +0200 @@ -1604,7 +1603,7 @@ static int shmem_statfs(struct super_blo { struct shmem_sb_info *sbinfo = SHMEM_SB(sb); - buf->f_type = TMPFS_MAGIC; + buf->f_type = TMPFS_SUPER_MAGIC; buf->f_bsize = PAGE_CACHE_SIZE; buf->f_namelen = NAME_MAX; if (sbinfo) { --- linux-2.6.11.11/mm/shmem.c 2005-03-02 12:39:08 +0100 +++ linux-2.6.11.11-vs2.0-rc3/mm/shmem.c 2005-06-01 14:34:17 +0200 @@ -2002,7 +2001,7 @@ static int shmem_fill_super(struct super sb->s_maxbytes = SHMEM_MAX_BYTES; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - sb->s_magic = TMPFS_MAGIC; + sb->s_magic = TMPFS_SUPER_MAGIC; sb->s_op = &shmem_ops; inode = shmem_get_inode(sb, S_IFDIR | mode, 0); if (!inode)