--- linux/include/linux/ext2_fs.h.orig Sun Aug 4 13:38:04 1996 +++ linux/include/linux/ext2_fs.h Tue Jan 14 21:37:41 1997 @@ -11,6 +11,8 @@ * linux/include/linux/minix_fs.h * * Copyright (C) 1991, 1992 Linus Torvalds + * + * uid/gid mount options by Jean Christophe ANDRE */ #ifndef _LINUX_EXT2_FS_H @@ -296,6 +298,8 @@ #define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ +#define EXT2_MOUNT_SETUID 0x0100 /* Set the file owner */ +#define EXT2_MOUNT_SETGID 0x0200 /* Set the file group */ #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt #define set_opt(o, opt) o |= EXT2_MOUNT_##opt @@ -474,6 +478,7 @@ extern int ext2_getcluster (struct inode * inode, long block); extern void ext2_read_inode (struct inode *); +extern int ext2_notify_change (struct inode *, struct iattr *); extern void ext2_write_inode (struct inode *); extern void ext2_put_inode (struct inode *); extern int ext2_sync_inode (struct inode *); --- linux/include/linux/ext2_fs_sb.h.orig Sun Aug 4 13:38:04 1996 +++ linux/include/linux/ext2_fs_sb.h Tue Jan 14 20:42:54 1997 @@ -11,6 +11,8 @@ * linux/include/linux/minix_fs_sb.h * * Copyright (C) 1991, 1992 Linus Torvalds + * + * uid/gid mount options by Jean Christophe ANDRE */ #ifndef _LINUX_EXT2_FS_SB @@ -54,6 +56,8 @@ unsigned long s_mount_opt; unsigned short s_resuid; unsigned short s_resgid; + unsigned short s_setuid; + unsigned short s_setgid; unsigned short s_mount_state; unsigned short s_pad; int s_addr_per_block_bits; --- linux/fs/ext2/inode.c.orig Sat May 4 09:06:18 1996 +++ linux/fs/ext2/inode.c Tue Jan 14 21:37:30 1997 @@ -13,6 +13,8 @@ * Copyright (C) 1991, 1992 Linus Torvalds * * Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 + * + * uid/gid mount options by Jean Christophe ANDRE */ #include @@ -537,8 +539,14 @@ raw_inode = (struct ext2_inode *) (bh->b_data + offset); inode->i_mode = raw_inode->i_mode; - inode->i_uid = raw_inode->i_uid; - inode->i_gid = raw_inode->i_gid; + if (test_opt(inode->i_sb, SETUID)) + inode->i_uid = inode->i_sb->u.ext2_sb.s_setuid; + else + inode->i_uid = raw_inode->i_uid; + if (test_opt(inode->i_sb, SETGID)) + inode->i_gid = inode->i_sb->u.ext2_sb.s_setgid; + else + inode->i_gid = raw_inode->i_gid; inode->i_nlink = raw_inode->i_links_count; inode->i_size = raw_inode->i_size; inode->i_atime = raw_inode->i_atime; @@ -592,6 +600,21 @@ inode->i_flags |= S_IMMUTABLE; } +int ext2_notify_change (struct inode * inode, struct iattr * attr) +{ + int retval; + + if ((retval = inode_change_ok(inode,attr)) != 0) + return retval; + + if (((attr->ia_valid & ATTR_UID) && test_opt(inode->i_sb, SETUID)) || + ((attr->ia_valid & ATTR_GID) && test_opt(inode->i_sb, SETGID))) + return -EPERM; + + inode_setattr(inode, attr); + return 0; +} + static int ext2_update_inode(struct inode * inode, int do_sync) { struct buffer_head * bh; @@ -637,8 +660,10 @@ raw_inode = (struct ext2_inode *) (bh->b_data + offset); raw_inode->i_mode = inode->i_mode; - raw_inode->i_uid = inode->i_uid; - raw_inode->i_gid = inode->i_gid; + if (!test_opt(inode->i_sb, SETUID)) + raw_inode->i_uid = inode->i_uid; + if (!test_opt(inode->i_sb, SETGID)) + raw_inode->i_gid = inode->i_gid; raw_inode->i_links_count = inode->i_nlink; raw_inode->i_size = inode->i_size; raw_inode->i_atime = inode->i_atime; --- linux/fs/ext2/super.c.orig Sun Jul 7 10:06:53 1996 +++ linux/fs/ext2/super.c Tue Jan 14 21:11:45 1997 @@ -11,6 +11,8 @@ * linux/fs/minix/inode.c * * Copyright (C) 1991, 1992 Linus Torvalds + * + * uid/gid mount options by Jean Christophe ANDRE */ #include @@ -126,7 +128,7 @@ static struct super_operations ext2_sops = { ext2_read_inode, - NULL, + ext2_notify_change, ext2_write_inode, ext2_put_inode, ext2_put_super, @@ -140,6 +142,7 @@ */ static int parse_options (char * options, unsigned long * sb_block, unsigned short *resuid, unsigned short * resgid, + unsigned short * setuid, unsigned short * setgid, unsigned long * mount_options) { char * this_char; @@ -240,6 +243,30 @@ return 0; } } + else if (!strcmp (this_char, "uid")) { + if (!value) + *setuid = current->uid; + else if (*value) + *setgid = simple_strtoul (value, &value, 0); + else { + printk ("EXT2-fs: Invalid uid option: %s\n", + value); + return 0; + } + set_opt (*mount_options, SETUID); + } + else if (!strcmp (this_char, "gid")) { + if (!value) + *setgid = current->gid; + else if (*value) + *setgid = simple_strtoul (value, &value, 0); + else { + printk ("EXT2-fs: Invalid gid option: %s\n", + value); + return 0; + } + set_opt (*mount_options, SETGID); + } else if (!strcmp (this_char, "sb")) { if (!value || !*value) { printk ("EXT2-fs: the sb option requires " @@ -370,6 +398,8 @@ unsigned long sb_block = 1; unsigned short resuid = EXT2_DEF_RESUID; unsigned short resgid = EXT2_DEF_RESGID; + unsigned short setuid; + unsigned short setgid; unsigned long logic_sb_block = 1; kdev_t dev = sb->s_dev; int db_count; @@ -378,6 +408,7 @@ sb->u.ext2_sb.s_mount_opt = 0; set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL); if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, + &setuid, &setgid, &sb->u.ext2_sb.s_mount_opt)) { sb->s_dev = 0; return NULL; @@ -488,6 +518,8 @@ sb->u.ext2_sb.s_resgid = resgid; else sb->u.ext2_sb.s_resgid = es->s_def_resgid; + sb->u.ext2_sb.s_setuid = setuid; + sb->u.ext2_sb.s_setgid = setgid; sb->u.ext2_sb.s_mount_state = es->s_state; sb->u.ext2_sb.s_rename_lock = 0; sb->u.ext2_sb.s_rename_wait = NULL; @@ -635,6 +668,8 @@ struct ext2_super_block * es; unsigned short resuid = sb->u.ext2_sb.s_resuid; unsigned short resgid = sb->u.ext2_sb.s_resgid; + unsigned short setuid; + unsigned short setgid; unsigned long new_mount_opt; unsigned long tmp; @@ -643,12 +678,15 @@ */ new_mount_opt = EXT2_MOUNT_CHECK_NORMAL; if (!parse_options (data, &tmp, &resuid, &resgid, + &setuid, &setgid, &new_mount_opt)) return -EINVAL; sb->u.ext2_sb.s_mount_opt = new_mount_opt; sb->u.ext2_sb.s_resuid = resuid; sb->u.ext2_sb.s_resgid = resgid; + sb->u.ext2_sb.s_setuid = setuid; + sb->u.ext2_sb.s_setgid = setgid; es = sb->u.ext2_sb.s_es; if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) return 0;