--- 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 @@ -87,6 +130,8 @@ int inode_setattr(struct inode * inode, inode->i_uid = attr->ia_uid; if (ia_valid & ATTR_GID) inode->i_gid = attr->ia_gid; + if (ia_valid & ATTR_XID) + inode->i_xid = attr->ia_xid; if (ia_valid & ATTR_ATIME) inode->i_atime = timespec_trunc(attr->ia_atime, inode->i_sb->s_time_gran); --- 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 @@ -118,6 +165,8 @@ int setattr_mask(unsigned int ia_valid) dn_mask |= DN_ATTRIB; if (ia_valid & ATTR_GID) dn_mask |= DN_ATTRIB; + if (ia_valid & ATTR_XID) + dn_mask |= DN_ATTRIB; if (ia_valid & ATTR_SIZE) dn_mask |= DN_MODIFY; /* both times implies a utime(s) call */ --- 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 @@ -184,7 +233,8 @@ int notify_change(struct dentry * dentry error = security_inode_setattr(dentry, attr); if (!error) { if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || - (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) + (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid) || + (ia_valid & ATTR_XID && attr->ia_xid != inode->i_xid)) error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; if (!error) error = inode_setattr(inode, attr); --- 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 @@ -1028,6 +1040,8 @@ void ext2_read_inode (struct inode * ino ino_t ino = inode->i_ino; struct buffer_head * bh; struct ext2_inode * raw_inode = ext2_get_inode(inode->i_sb, ino, &bh); + uid_t uid; + gid_t gid; int n; #ifdef CONFIG_EXT2_FS_POSIX_ACL --- 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 @@ -1038,12 +1052,17 @@ void ext2_read_inode (struct inode * ino goto bad_inode; inode->i_mode = le16_to_cpu(raw_inode->i_mode); - inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); - inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); + uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); + gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); if (!(test_opt (inode->i_sb, NO_UID32))) { - inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; - inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; + uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; + gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; } + inode->i_uid = INOXID_UID(XID_TAG(inode), uid, gid); + inode->i_gid = INOXID_GID(XID_TAG(inode), uid, gid); + inode->i_xid = INOXID_XID(XID_TAG(inode), uid, gid, + le16_to_cpu(raw_inode->i_raw_xid)); + inode->i_nlink = le16_to_cpu(raw_inode->i_links_count); inode->i_size = le32_to_cpu(raw_inode->i_size); inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime); --- 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 @@ -1136,8 +1155,8 @@ static int ext2_update_inode(struct inod struct ext2_inode_info *ei = EXT2_I(inode); struct super_block *sb = inode->i_sb; ino_t ino = inode->i_ino; - uid_t uid = inode->i_uid; - gid_t gid = inode->i_gid; + uid_t uid = XIDINO_UID(XID_TAG(inode), inode->i_uid, inode->i_xid); + gid_t gid = XIDINO_GID(XID_TAG(inode), inode->i_gid, inode->i_xid); struct buffer_head * bh; struct ext2_inode * raw_inode = ext2_get_inode(sb, ino, &bh); int n; --- 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 @@ -1172,6 +1191,9 @@ static int ext2_update_inode(struct inod raw_inode->i_uid_high = 0; raw_inode->i_gid_high = 0; } +#ifdef CONFIG_INOXID_INTERN + raw_inode->i_raw_xid = cpu_to_le16(inode->i_xid); +#endif raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); raw_inode->i_size = cpu_to_le32(inode->i_size); raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec); --- 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 @@ -1258,11 +1301,15 @@ int ext2_setattr(struct dentry *dentry, if (error) return error; if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) || - (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) { + (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid) || + (iattr->ia_valid & ATTR_XID && iattr->ia_xid != inode->i_xid)) { error = DQUOT_TRANSFER(inode, iattr) ? -EDQUOT : 0; if (error) return error; } + if (iattr->ia_valid & ATTR_ATTR_FLAG) + ext2_setattr_flags(inode, iattr->ia_attr_flags); + error = inode_setattr(inode, iattr); if (!error && (iattr->ia_valid & ATTR_MODE)) error = ext2_acl_chmod(inode); --- linux-2.6.11.11/fs/ext2/namei.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/namei.c 2005-06-01 14:34:17 +0200 @@ -81,6 +82,7 @@ static struct dentry *ext2_lookup(struct inode = iget(dir->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); + vx_propagate_xid(nd, inode); } if (inode) return d_splice_alias(inode, dentry); --- linux-2.6.11.11/fs/ext2/super.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/super.c 2005-06-01 14:34:17 +0200 @@ -259,7 +259,7 @@ enum { Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh, - Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, + Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_tagxid, Opt_ignore, Opt_err, }; --- linux-2.6.11.11/fs/ext2/super.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/super.c 2005-06-01 14:34:17 +0200 @@ -288,6 +288,7 @@ static match_table_t tokens = { {Opt_nouser_xattr, "nouser_xattr"}, {Opt_acl, "acl"}, {Opt_noacl, "noacl"}, + {Opt_tagxid, "tagxid"}, {Opt_ignore, "grpquota"}, {Opt_ignore, "noquota"}, {Opt_ignore, "quota"}, --- linux-2.6.11.11/fs/ext2/super.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/super.c 2005-06-01 14:34:17 +0200 @@ -351,6 +352,11 @@ static int parse_options (char * options case Opt_nouid32: set_opt (sbi->s_mount_opt, NO_UID32); break; +#ifndef CONFIG_INOXID_NONE + case Opt_tagxid: + set_opt (sbi->s_mount_opt, TAG_XID); + break; +#endif case Opt_check: #ifdef CONFIG_EXT2_CHECK set_opt (sbi->s_mount_opt, CHECK); --- linux-2.6.11.11/fs/ext2/super.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/super.c 2005-06-01 14:34:17 +0200 @@ -632,6 +638,8 @@ static int ext2_fill_super(struct super_ if (!parse_options ((char *) data, sbi)) goto failed_mount; + if (EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_TAG_XID) + sb->s_flags |= MS_TAGXID; sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); --- 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 @@ -2414,6 +2426,8 @@ void ext3_read_inode(struct inode * inod struct ext3_inode_info *ei = EXT3_I(inode); struct buffer_head *bh; int block; + uid_t uid; + gid_t gid; #ifdef CONFIG_EXT3_FS_POSIX_ACL ei->i_acl = EXT3_ACL_NOT_CACHED; --- 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 @@ -2426,12 +2440,17 @@ void ext3_read_inode(struct inode * inod bh = iloc.bh; raw_inode = ext3_raw_inode(&iloc); inode->i_mode = le16_to_cpu(raw_inode->i_mode); - inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); - inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); + uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); + gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); if(!(test_opt (inode->i_sb, NO_UID32))) { - inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; - inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; + uid |= le16_to_cpu(raw_inode->i_uid_high) << 16; + gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; } + inode->i_uid = INOXID_UID(XID_TAG(inode), uid, gid); + inode->i_gid = INOXID_GID(XID_TAG(inode), uid, gid); + inode->i_xid = INOXID_XID(XID_TAG(inode), uid, gid, + le16_to_cpu(raw_inode->i_raw_xid)); + inode->i_nlink = le16_to_cpu(raw_inode->i_links_count); inode->i_size = le32_to_cpu(raw_inode->i_size); inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime); --- 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 @@ -2564,6 +2583,8 @@ static int ext3_do_update_inode(handle_t struct ext3_inode *raw_inode = ext3_raw_inode(iloc); struct ext3_inode_info *ei = EXT3_I(inode); struct buffer_head *bh = iloc->bh; + uid_t uid = XIDINO_UID(XID_TAG(inode), inode->i_uid, inode->i_xid); + gid_t gid = XIDINO_GID(XID_TAG(inode), inode->i_gid, inode->i_xid); int err = 0, rc, block; /* For fields not not tracking in the in-memory 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 @@ -2573,29 +2594,32 @@ static int ext3_do_update_inode(handle_t raw_inode->i_mode = cpu_to_le16(inode->i_mode); if(!(test_opt(inode->i_sb, NO_UID32))) { - raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); - raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid)); + raw_inode->i_uid_low = cpu_to_le16(low_16_bits(uid)); + raw_inode->i_gid_low = cpu_to_le16(low_16_bits(gid)); /* * Fix up interoperability with old kernels. Otherwise, old inodes get * re-used with the upper 16 bits of the uid/gid intact */ if(!ei->i_dtime) { raw_inode->i_uid_high = - cpu_to_le16(high_16_bits(inode->i_uid)); + cpu_to_le16(high_16_bits(uid)); raw_inode->i_gid_high = - cpu_to_le16(high_16_bits(inode->i_gid)); + cpu_to_le16(high_16_bits(gid)); } else { raw_inode->i_uid_high = 0; raw_inode->i_gid_high = 0; } } else { raw_inode->i_uid_low = - cpu_to_le16(fs_high2lowuid(inode->i_uid)); + cpu_to_le16(fs_high2lowuid(uid)); raw_inode->i_gid_low = - cpu_to_le16(fs_high2lowgid(inode->i_gid)); + cpu_to_le16(fs_high2lowgid(gid)); raw_inode->i_uid_high = 0; raw_inode->i_gid_high = 0; } +#ifdef CONFIG_INOXID_INTERN + raw_inode->i_raw_xid = cpu_to_le16(inode->i_xid); +#endif raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); raw_inode->i_size = cpu_to_le32(ei->i_disksize); raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec); --- 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 @@ -2748,7 +2810,8 @@ int ext3_setattr(struct dentry *dentry, return error; if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || - (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { + (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid) || + (ia_valid & ATTR_XID && attr->ia_xid != inode->i_xid)) { handle_t *handle; /* (user+group)*(old+new) structure, inode write (sb, --- 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 @@ -2769,6 +2832,10 @@ int ext3_setattr(struct dentry *dentry, inode->i_uid = attr->ia_uid; if (attr->ia_valid & ATTR_GID) inode->i_gid = attr->ia_gid; + if ((attr->ia_valid & ATTR_XID) + && inode->i_sb + && (inode->i_sb->s_flags & MS_TAGXID)) + inode->i_xid = attr->ia_xid; error = ext3_mark_inode_dirty(handle, inode); ext3_journal_stop(handle); } --- linux-2.6.11.11/fs/ext3/namei.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/namei.c 2005-06-01 14:34:17 +0200 @@ -994,6 +995,7 @@ static struct dentry *ext3_lookup(struct if (!inode) return ERR_PTR(-EACCES); + vx_propagate_xid(nd, inode); } if (inode) return d_splice_alias(inode, dentry); --- linux-2.6.11.11/fs/ext3/super.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/super.c 2005-06-01 14:34:17 +0200 @@ -581,7 +581,7 @@ enum { Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, - Opt_ignore, Opt_barrier, Opt_err, Opt_resize, + Opt_tagxid, Opt_barrier, Opt_ignore, Opt_err, Opt_resize, }; static match_table_t tokens = { --- linux-2.6.11.11/fs/ext3/super.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/super.c 2005-06-01 14:34:17 +0200 @@ -624,6 +624,7 @@ static match_table_t tokens = { {Opt_grpjquota, "grpjquota=%s"}, {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, + {Opt_tagxid, "tagxid"}, {Opt_ignore, "grpquota"}, {Opt_ignore, "noquota"}, {Opt_ignore, "quota"}, --- linux-2.6.11.11/fs/ext3/super.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/super.c 2005-06-01 14:34:17 +0200 @@ -720,6 +721,16 @@ static int parse_options (char * options case Opt_nouid32: set_opt (sbi->s_mount_opt, NO_UID32); break; +#ifndef CONFIG_INOXID_NONE + case Opt_tagxid: + if (is_remount) { + printk(KERN_ERR "EXT3-fs: cannot specify " + "tagxid on remount\n"); + return 0; + } + set_opt (sbi->s_mount_opt, TAG_XID); + break; +#endif case Opt_check: #ifdef CONFIG_EXT3_CHECK set_opt (sbi->s_mount_opt, CHECK); --- linux-2.6.11.11/fs/ext3/super.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/super.c 2005-06-01 14:34:17 +0200 @@ -1316,6 +1327,9 @@ static int ext3_fill_super (struct super if (!parse_options ((char *) data, sb, &journal_inum, NULL, 0)) goto failed_mount; + if (EXT3_SB(sb)->s_mount_opt & EXT3_MOUNT_TAG_XID) + sb->s_flags |= MS_TAGXID; + sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | ((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); --- linux-2.6.11.11/fs/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/inode.c 2005-06-01 14:34:17 +0200 @@ -115,6 +115,9 @@ static struct inode *alloc_inode(struct struct address_space * const mapping = &inode->i_data; inode->i_sb = sb; + + /* essential because of inode slab reuse */ + inode->i_xid = 0; inode->i_blkbits = sb->s_blocksize_bits; inode->i_flags = 0; atomic_set(&inode->i_count, 1); --- linux-2.6.11.11/fs/inode.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/inode.c 2005-06-01 14:34:17 +0200 @@ -232,6 +235,8 @@ void __iget(struct inode * inode) inodes_stat.nr_unused--; } +EXPORT_SYMBOL_GPL(__iget); + /** * clear_inode - clear an inode * @inode: inode to clear --- linux-2.6.11.11/fs/jfs/jfs_imap.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/jfs/jfs_imap.c 2005-06-01 14:34:17 +0200 @@ -3098,14 +3099,21 @@ static void duplicateIXtree(struct super static int copy_from_dinode(struct dinode * dip, struct inode *ip) { struct jfs_inode_info *jfs_ip = JFS_IP(ip); + uid_t uid; + gid_t gid; jfs_ip->fileset = le32_to_cpu(dip->di_fileset); jfs_ip->mode2 = le32_to_cpu(dip->di_mode); ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff; ip->i_nlink = le32_to_cpu(dip->di_nlink); - ip->i_uid = le32_to_cpu(dip->di_uid); - ip->i_gid = le32_to_cpu(dip->di_gid); + + uid = le32_to_cpu(dip->di_uid); + gid = le32_to_cpu(dip->di_gid); + ip->i_uid = INOXID_UID(XID_TAG(ip), uid, gid); + ip->i_gid = INOXID_GID(XID_TAG(ip), uid, gid); + ip->i_xid = INOXID_XID(XID_TAG(ip), uid, gid, 0); + ip->i_size = le64_to_cpu(dip->di_size); ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec); ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec); --- linux-2.6.11.11/fs/jfs/jfs_imap.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/jfs/jfs_imap.c 2005-06-01 14:34:17 +0200 @@ -3156,6 +3164,8 @@ static int copy_from_dinode(struct dinod static void copy_to_dinode(struct dinode * dip, struct inode *ip) { struct jfs_inode_info *jfs_ip = JFS_IP(ip); + uid_t uid; + gid_t gid; dip->di_fileset = cpu_to_le32(jfs_ip->fileset); dip->di_inostamp = cpu_to_le32(JFS_SBI(ip->i_sb)->inostamp); --- linux-2.6.11.11/fs/jfs/jfs_imap.c 2005-03-02 12:38:44 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/jfs/jfs_imap.c 2005-06-01 14:34:17 +0200 @@ -3164,8 +3174,11 @@ static void copy_to_dinode(struct dinode dip->di_size = cpu_to_le64(ip->i_size); dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks)); dip->di_nlink = cpu_to_le32(ip->i_nlink); - dip->di_uid = cpu_to_le32(ip->i_uid); - dip->di_gid = cpu_to_le32(ip->i_gid); + + uid = XIDINO_UID(XID_TAG(ip), ip->i_uid, ip->i_xid); + gid = XIDINO_GID(XID_TAG(ip), ip->i_gid, ip->i_xid); + dip->di_uid = cpu_to_le32(uid); + dip->di_gid = cpu_to_le32(gid); /* * mode2 is only needed for storing the higher order bits. * Trust i_mode for the lower order ones --- linux-2.6.11.11/fs/namei.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/namei.c 2005-06-01 14:34:17 +0200 @@ -210,6 +214,24 @@ int generic_permission(struct inode *ino return -EACCES; } +static inline int xid_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + if (IS_BARRIER(inode) && !vx_check(0, VX_ADMIN)) { + vxwprintk(1, "xid=%d did hit the barrier.", + vx_current_xid()); + return -EACCES; + } + if (inode->i_xid == 0) + return 0; + if (vx_check(inode->i_xid, VX_ADMIN|VX_WATCH|VX_IDENT)) + return 0; + + vxwprintk(1, "xid=%d denied access to %p[#%d,%lu] »%s«.", + vx_current_xid(), inode, inode->i_xid, inode->i_ino, + vxd_path(nd->dentry, nd->mnt)); + return -EACCES; +} + int permission(struct inode *inode, int mask, struct nameidata *nd) { int retval, submask; --- linux-2.6.11.11/fs/namei.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/namei.c 2005-06-01 14:34:17 +0200 @@ -234,6 +256,8 @@ int permission(struct inode *inode, int /* Ordinary permission routines do not understand MAY_APPEND. */ submask = mask & ~MAY_APPEND; + if ((retval = xid_permission(inode, mask, nd))) + return retval; if (inode->i_op && inode->i_op->permission) retval = inode->i_op->permission(inode, submask, nd); else --- linux-2.6.11.11/fs/namei.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/namei.c 2005-06-01 14:34:17 +0200 @@ -603,7 +627,7 @@ static inline void follow_dotdot(struct if (*dentry == current->fs->root && *mnt == current->fs->rootmnt) { read_unlock(¤t->fs->lock); - break; + return; } read_unlock(¤t->fs->lock); spin_lock(&dcache_lock); --- linux-2.6.11.11/fs/namei.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/namei.c 2005-06-01 14:34:17 +0200 @@ -645,15 +669,33 @@ static int do_lookup(struct nameidata *n { struct vfsmount *mnt = nd->mnt; struct dentry *dentry = __d_lookup(nd->dentry, name); + struct inode *inode; if (!dentry) goto need_lookup; if (dentry->d_op && dentry->d_op->d_revalidate) goto need_revalidate; + inode = dentry->d_inode; + if (!inode) + goto done; + if (!vx_check(inode->i_xid, VX_WATCH|VX_ADMIN|VX_HOSTID|VX_IDENT)) + goto hidden; + if (inode->i_sb->s_magic == PROC_SUPER_MAGIC) { + struct proc_dir_entry *de = PDE(inode); + + if (de && !vx_hide_check(0, de->vx_flags)) + goto hidden; + } done: path->mnt = mnt; path->dentry = dentry; return 0; +hidden: + vxwprintk(1, "xid=%d did lookup hidden %p[#%d,%lu] »%s«.", + vx_current_xid(), inode, inode->i_xid, inode->i_ino, + vxd_path(dentry, mnt)); + dput(dentry); + return -ENOENT; need_lookup: dentry = real_lookup(nd->dentry, name, nd); --- linux-2.6.11.11/fs/namespace.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/namespace.c 2005-06-01 14:34:17 +0200 @@ -228,6 +260,7 @@ static int show_vfsmnt(struct seq_file * { MS_MANDLOCK, ",mand" }, { MS_NOATIME, ",noatime" }, { MS_NODIRATIME, ",nodiratime" }, + { MS_TAGXID, ",tagxid" }, { 0, NULL } }; static struct proc_fs_info mnt_info[] = { --- linux-2.6.11.11/fs/open.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/open.c 2005-06-01 14:34:17 +0200 @@ -678,14 +683,15 @@ static int chown_common(struct dentry * error = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out; + newattrs.ia_valid = ATTR_CTIME; if (user != (uid_t) -1) { newattrs.ia_valid |= ATTR_UID; - newattrs.ia_uid = user; + newattrs.ia_uid = vx_map_uid(user); } if (group != (gid_t) -1) { newattrs.ia_valid |= ATTR_GID; - newattrs.ia_gid = group; + newattrs.ia_gid = vx_map_gid(group); } if (!S_ISDIR(inode->i_mode)) newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID; --- 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 @@ -1047,6 +1048,8 @@ static void init_inode (struct inode * i struct buffer_head * bh; struct item_head * ih; __u32 rdev; + uid_t uid; + gid_t gid; //int version = ITEM_VERSION_1; bh = PATH_PLAST_BUFFER (path); --- 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 @@ -1070,12 +1073,13 @@ static void init_inode (struct inode * i struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); unsigned long blocks; + uid = sd_v1_uid(sd); + gid = sd_v1_gid(sd); + set_inode_item_key_version (inode, KEY_FORMAT_3_5); set_inode_sd_version (inode, STAT_DATA_V1); inode->i_mode = sd_v1_mode(sd); inode->i_nlink = sd_v1_nlink(sd); - inode->i_uid = sd_v1_uid(sd); - inode->i_gid = sd_v1_gid(sd); inode->i_size = sd_v1_size(sd); inode->i_atime.tv_sec = sd_v1_atime(sd); inode->i_mtime.tv_sec = sd_v1_mtime(sd); --- 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 @@ -1115,11 +1119,12 @@ static void init_inode (struct inode * i // (directories and symlinks) struct stat_data * sd = (struct stat_data *)B_I_PITEM (bh, ih); + uid = sd_v2_uid(sd); + gid = sd_v2_gid(sd); + inode->i_mode = sd_v2_mode(sd); inode->i_nlink = sd_v2_nlink(sd); - inode->i_uid = sd_v2_uid(sd); inode->i_size = sd_v2_size(sd); - inode->i_gid = sd_v2_gid(sd); inode->i_mtime.tv_sec = sd_v2_mtime(sd); inode->i_atime.tv_sec = sd_v2_atime(sd); inode->i_ctime.tv_sec = sd_v2_ctime(sd); --- 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 @@ -1146,6 +1151,9 @@ static void init_inode (struct inode * i REISERFS_I(inode)->i_attrs = sd_v2_attrs( sd ); sd_attrs_to_i_attrs( sd_v2_attrs( sd ), inode ); } + inode->i_uid = INOXID_UID(XID_TAG(inode), uid, gid); + inode->i_gid = INOXID_GID(XID_TAG(inode), uid, gid); + inode->i_xid = INOXID_XID(XID_TAG(inode), uid, gid, 0); pathrelse (path); if (S_ISREG (inode->i_mode)) { --- 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 @@ -1170,13 +1178,15 @@ static void init_inode (struct inode * i static void inode2sd (void * sd, struct inode * inode, loff_t size) { struct stat_data * sd_v2 = (struct stat_data *)sd; + uid_t uid = XIDINO_UID(XID_TAG(inode), inode->i_uid, inode->i_xid); + gid_t gid = XIDINO_GID(XID_TAG(inode), inode->i_gid, inode->i_xid); __u16 flags; + set_sd_v2_uid(sd_v2, uid ); + set_sd_v2_gid(sd_v2, gid ); set_sd_v2_mode(sd_v2, inode->i_mode ); set_sd_v2_nlink(sd_v2, inode->i_nlink ); - set_sd_v2_uid(sd_v2, inode->i_uid ); set_sd_v2_size(sd_v2, size ); - set_sd_v2_gid(sd_v2, inode->i_gid ); set_sd_v2_mtime(sd_v2, inode->i_mtime.tv_sec ); set_sd_v2_atime(sd_v2, inode->i_atime.tv_sec ); set_sd_v2_ctime(sd_v2, inode->i_ctime.tv_sec ); --- linux-2.6.11.11/fs/reiserfs/namei.c 2005-03-02 12:38:45 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/namei.c 2005-06-01 14:34:17 +0200 @@ -350,6 +351,7 @@ static struct dentry * reiserfs_lookup ( reiserfs_write_unlock(dir->i_sb); return ERR_PTR(-EACCES); } + vx_propagate_xid(nd, inode); /* Propogate the priv_object flag so we know we're in the priv tree */ if (is_reiserfs_priv_object (dir)) --- linux-2.6.11.11/fs/reiserfs/super.c 2005-03-02 12:38:46 +0100 +++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/super.c 2005-06-01 14:34:17 +0200 @@ -848,6 +848,7 @@ static int reiserfs_parse_options (struc {"user_xattr", .setmask = 1<nlink = inode->i_nlink; stat->uid = inode->i_uid; stat->gid = inode->i_gid; + stat->xid = inode->i_xid; stat->rdev = inode->i_rdev; stat->atime = inode->i_atime; stat->mtime = inode->i_mtime; --- linux-2.6.11.11/include/linux/ext2_fs.h 2004-10-23 05:06:22 +0200 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/ext2_fs.h 2005-06-01 14:34:17 +0200 @@ -240,7 +247,7 @@ struct ext2_inode { struct { __u8 l_i_frag; /* Fragment number */ __u8 l_i_fsize; /* Fragment size */ - __u16 i_pad1; + __u16 l_i_xid; /* LRU Context */ __le16 l_i_uid_high; /* these 2 fields */ __le16 l_i_gid_high; /* were reserved2[0] */ __u32 l_i_reserved2; --- linux-2.6.11.11/include/linux/ext2_fs.h 2004-10-23 05:06:22 +0200 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/ext2_fs.h 2005-06-01 14:34:17 +0200 @@ -272,6 +279,7 @@ struct ext2_inode { #define i_gid_low i_gid #define i_uid_high osd2.linux2.l_i_uid_high #define i_gid_high osd2.linux2.l_i_gid_high +#define i_raw_xid osd2.linux2.l_i_xid #define i_reserved2 osd2.linux2.l_i_reserved2 #endif --- linux-2.6.11.11/include/linux/ext2_fs.h 2004-10-23 05:06:22 +0200 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/ext2_fs.h 2005-06-01 14:34:17 +0200 @@ -312,6 +320,7 @@ struct ext2_inode { #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ #define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ #define EXT2_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ +#define EXT2_MOUNT_TAG_XID (1<<24) /* Enable Context Tags */ #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt #define set_opt(o, opt) o |= EXT2_MOUNT_##opt --- linux-2.6.11.11/include/linux/ext3_fs.h 2005-03-02 12:38:52 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/ext3_fs.h 2005-06-01 14:34:17 +0200 @@ -273,7 +283,7 @@ struct ext3_inode { struct { __u8 l_i_frag; /* Fragment number */ __u8 l_i_fsize; /* Fragment size */ - __u16 i_pad1; + __u16 l_i_xid; /* LRU Context */ __le16 l_i_uid_high; /* these 2 fields */ __le16 l_i_gid_high; /* were reserved2[0] */ __u32 l_i_reserved2; --- linux-2.6.11.11/include/linux/ext3_fs.h 2005-03-02 12:38:52 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/ext3_fs.h 2005-06-01 14:34:17 +0200 @@ -307,6 +317,7 @@ struct ext3_inode { #define i_gid_low i_gid #define i_uid_high osd2.linux2.l_i_uid_high #define i_gid_high osd2.linux2.l_i_gid_high +#define i_raw_xid osd2.linux2.l_i_xid #define i_reserved2 osd2.linux2.l_i_reserved2 #elif defined(__GNU__) --- linux-2.6.11.11/include/linux/ext3_fs.h 2005-03-02 12:38:52 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/ext3_fs.h 2005-06-01 14:34:17 +0200 @@ -357,6 +368,7 @@ struct ext3_inode { #define EXT3_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */ #define EXT3_MOUNT_RESERVATION 0x10000 /* Preallocation */ #define EXT3_MOUNT_BARRIER 0x20000 /* Use block barriers */ +#define EXT3_MOUNT_TAG_XID (1<<24) /* Enable Context Tags */ /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ #ifndef _LINUX_EXT2_FS_H --- linux-2.6.11.11/include/linux/fs.h 2005-03-02 12:38:52 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/fs.h 2005-06-01 14:34:17 +0200 @@ -103,6 +103,8 @@ extern int dir_notify_enable; #define MS_REC 16384 #define MS_VERBOSE 32768 #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ +#define MS_TAGXID (1<<24) /* tag inodes with context information */ +#define MS_XID (1<<25) /* use specific xid for this mount */ #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) --- linux-2.6.11.11/include/linux/fs.h 2005-03-02 12:38:52 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/fs.h 2005-06-01 14:34:17 +0200 @@ -259,6 +266,7 @@ typedef void (dio_iodone_t)(struct inode #define ATTR_ATTR_FLAG 1024 #define ATTR_KILL_SUID 2048 #define ATTR_KILL_SGID 4096 +#define ATTR_XID 8192 /* * This is the Inode Attributes structure, used for notify_change(). It --- linux-2.6.11.11/include/linux/fs.h 2005-03-02 12:38:52 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/fs.h 2005-06-01 14:34:17 +0200 @@ -274,6 +282,7 @@ struct iattr { umode_t ia_mode; uid_t ia_uid; gid_t ia_gid; + xid_t ia_xid; loff_t ia_size; struct timespec ia_atime; struct timespec ia_mtime; --- linux-2.6.11.11/include/linux/fs.h 2005-03-02 12:38:52 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/fs.h 2005-06-01 14:34:17 +0200 @@ -434,6 +446,7 @@ struct inode { unsigned int i_nlink; uid_t i_uid; gid_t i_gid; + xid_t i_xid; dev_t i_rdev; loff_t i_size; struct timespec i_atime; --- linux-2.6.11.11/include/linux/fs.h 2005-03-02 12:38:52 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/fs.h 2005-06-01 14:34:17 +0200 @@ -586,6 +599,7 @@ struct file { struct fown_struct f_owner; unsigned int f_uid, f_gid; struct file_ra_state f_ra; + xid_t f_xid; size_t f_maxcount; unsigned long f_version; --- linux-2.6.11.11/include/linux/mount.h 2004-12-25 01:55:29 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/mount.h 2005-06-01 14:34:17 +0200 @@ -19,6 +19,7 @@ #define MNT_NOSUID 1 #define MNT_NODEV 2 #define MNT_NOEXEC 4 +#define MNT_XID 256 struct vfsmount { --- linux-2.6.11.11/include/linux/mount.h 2004-12-25 01:55:29 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/mount.h 2005-06-01 14:34:17 +0200 @@ -36,6 +37,7 @@ struct vfsmount struct list_head mnt_list; struct list_head mnt_fslink; /* link in fs-specific expiry list */ struct namespace *mnt_namespace; /* containing namespace */ + xid_t mnt_xid; /* xid tagging used for vfsmount */ }; static inline struct vfsmount *mntget(struct vfsmount *mnt) --- linux-2.6.11.11/include/linux/reiserfs_fs_sb.h 2005-03-02 12:38:53 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/reiserfs_fs_sb.h 2005-06-01 14:34:17 +0200 @@ -461,6 +461,7 @@ enum reiserfs_mount_options { REISERFS_POSIXACL, REISERFS_BARRIER_NONE, REISERFS_BARRIER_FLUSH, + REISERFS_TAGXID, /* Actions on error */ REISERFS_ERROR_PANIC, --- linux-2.6.11.11/include/linux/stat.h 2004-08-14 12:55:10 +0200 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/stat.h 2005-06-01 14:34:17 +0200 @@ -63,6 +63,7 @@ struct kstat { unsigned int nlink; uid_t uid; gid_t gid; + xid_t xid; dev_t rdev; loff_t size; struct timespec atime; --- linux-2.6.11.11/include/linux/vserver/xid.h 1970-01-01 01:00:00 +0100 +++ linux-2.6.11.11-vs2.0-rc3/include/linux/vserver/xid.h 2005-06-01 14:34:17 +0200 @@ -0,0 +1,135 @@ +#ifndef _VX_XID_H +#define _VX_XID_H + +#ifndef CONFIG_VSERVER +#warning config options missing +#endif + +#define XID_TAG(in) (!(in) || \ + (((struct inode *)in)->i_sb && \ + (((struct inode *)in)->i_sb->s_flags & MS_TAGXID))) + +#ifdef CONFIG_XID_TAG_NFSD +#define XID_TAG_NFSD 1 +#else +#define XID_TAG_NFSD 0 +#endif + + +#ifdef CONFIG_INOXID_NONE + +#define MAX_UID 0xFFFFFFFF +#define MAX_GID 0xFFFFFFFF + +#define INOXID_XID(tag, uid, gid, xid) (0) + +#define XIDINO_UID(tag, uid, xid) (uid) +#define XIDINO_GID(tag, gid, xid) (gid) + +#endif + + +#ifdef CONFIG_INOXID_GID16 + +#define MAX_UID 0xFFFFFFFF +#define MAX_GID 0x0000FFFF + +#define INOXID_XID(tag, uid, gid, xid) \ + ((tag) ? (((gid) >> 16) & 0xFFFF) : 0) + +#define XIDINO_UID(tag, uid, xid) (uid) +#define XIDINO_GID(tag, gid, xid) \ + ((tag) ? (((gid) & 0xFFFF) | ((xid) << 16)) : (gid)) + +#endif + + +#ifdef CONFIG_INOXID_UGID24 + +#define MAX_UID 0x00FFFFFF +#define MAX_GID 0x00FFFFFF + +#define INOXID_XID(tag, uid, gid, xid) \ + ((tag) ? ((((uid) >> 16) & 0xFF00) | (((gid) >> 24) & 0xFF)) : 0) + +#define XIDINO_UID(tag, uid, xid) \ + ((tag) ? (((uid) & 0xFFFFFF) | (((xid) & 0xFF00) << 16)) : (uid)) +#define XIDINO_GID(tag, gid, xid) \ + ((tag) ? (((gid) & 0xFFFFFF) | (((xid) & 0x00FF) << 24)) : (gid)) + +#endif + + +#ifdef CONFIG_INOXID_UID16 + +#define MAX_UID 0x0000FFFF +#define MAX_GID 0xFFFFFFFF + +#define INOXID_XID(tag, uid, gid, xid) \ + ((tag) ? (((uid) >> 16) & 0xFFFF) : 0) + +#define XIDINO_UID(tag, uid, xid) \ + ((tag) ? (((uid) & 0xFFFF) | ((xid) << 16)) : (uid)) +#define XIDINO_GID(tag, gid, xid) (gid) + +#endif + + +#ifdef CONFIG_INOXID_INTERN + +#define MAX_UID 0xFFFFFFFF +#define MAX_GID 0xFFFFFFFF + +#define INOXID_XID(tag, uid, gid, xid) \ + ((tag) ? (xid) : 0) + +#define XIDINO_UID(tag, uid, xid) (uid) +#define XIDINO_GID(tag, gid, xid) (gid) + +#endif + + +#ifdef CONFIG_INOXID_RUNTIME + +#define MAX_UID 0xFFFFFFFF +#define MAX_GID 0xFFFFFFFF + +#define INOXID_XID(tag, uid, gid, xid) (0) + +#define XIDINO_UID(tag, uid, xid) (uid) +#define XIDINO_GID(tag, gid, xid) (gid) + +#endif + + +#define INOXID_UID(tag, uid, gid) \ + ((tag) ? ((uid) & MAX_UID) : (uid)) +#define INOXID_GID(tag, uid, gid) \ + ((tag) ? ((gid) & MAX_GID) : (gid)) + + +static inline uid_t vx_map_uid(uid_t uid) +{ + if ((uid > MAX_UID) && (uid != -1)) + uid = -2; + return (uid & MAX_UID); +} + +static inline gid_t vx_map_gid(gid_t gid) +{ + if ((gid > MAX_GID) && (gid != -1)) + gid = -2; + return (gid & MAX_GID); +} + + +#ifdef CONFIG_VSERVER_LEGACY +#define FIOC_GETXID _IOR('x', 1, long) +#define FIOC_SETXID _IOW('x', 2, long) +#define FIOC_SETXIDJ _IOW('x', 3, long) +#endif + +int vx_parse_xid(char *string, xid_t *xid, int remove); +void vx_propagate_xid(struct nameidata *nd, struct inode *inode); + +#endif /* _VX_XID_H */