lkml.org 
[lkml]   [2012]   [Aug]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 1/3] implement uid and gid mount options for ext2
    Date
    Signed-off-by: Ludwig Nussel <ludwig.nussel@suse.de>
    ---
    Documentation/filesystems/ext2.txt | 9 ++++
    fs/ext2/ext2.h | 8 +++
    fs/ext2/inode.c | 48 +++++++++++++-----
    fs/ext2/super.c | 95 +++++++++++++++++++++++++++++++++++-
    4 Dateien geändert, 147 Zeilen hinzugefügt(+), 13 Zeilen entfernt(-)

    diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt
    index 67639f9..fcc1002 100644
    --- a/Documentation/filesystems/ext2.txt
    +++ b/Documentation/filesystems/ext2.txt
    @@ -42,6 +42,15 @@ orlov (*) Use the Orlov block allocator.
    resuid=n The user ID which may use the reserved blocks.
    resgid=n The group ID which may use the reserved blocks.

    +uid=n[:m] Make all files appear to belong to uid n.
    + Useful for e.g. removable media with fstab
    + options 'user,uid=useruid'. The optional second
    + uid m is actually written to the file system.
    +
    +gid=n[:m] Make all files appear to belong to gid n.
    + The optional second gid m is actually written to
    + the file system.
    +
    sb=n Use alternate superblock at this location.

    user_xattr Enable "user." POSIX Extended Attributes
    diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
    index d9a17d0..160d5d8 100644
    --- a/fs/ext2/ext2.h
    +++ b/fs/ext2/ext2.h
    @@ -84,6 +84,10 @@ struct ext2_sb_info {
    unsigned long s_sb_block;
    kuid_t s_resuid;
    kgid_t s_resgid;
    + kuid_t s_uid; /* make all files appear to belong to this uid */
    + kuid_t s_diskuid; /* write this uid to disk (if s_uid != 0) */
    + kgid_t s_gid; /* make all files appear to belong to this gid */
    + kgid_t s_diskgid; /* write this gid to disk (if s_gid != 0) */
    unsigned short s_mount_state;
    unsigned short s_pad;
    int s_addr_per_block_bits;
    @@ -639,6 +643,10 @@ struct ext2_mount_options {
    unsigned long s_mount_opt;
    kuid_t s_resuid;
    kgid_t s_resgid;
    + kuid_t s_uid;
    + kuid_t s_diskuid;
    + kgid_t s_gid;
    + kgid_t s_diskgid;
    };

    /*
    diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
    index 6363ac6..b2320e4 100644
    --- a/fs/ext2/inode.c
    +++ b/fs/ext2/inode.c
    @@ -1321,8 +1321,14 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
    i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
    i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
    }
    - i_uid_write(inode, i_uid);
    - i_gid_write(inode, i_gid);
    + if (uid_valid(EXT2_SB(sb)->s_uid))
    + inode->i_uid = EXT2_SB(sb)->s_uid;
    + else
    + i_uid_write(inode, i_uid);
    + if (gid_valid(EXT2_SB(sb)->s_gid))
    + inode->i_gid = EXT2_SB(sb)->s_gid;
    + else
    + i_gid_write(inode, i_gid);
    set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
    inode->i_size = le32_to_cpu(raw_inode->i_size);
    inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
    @@ -1426,6 +1432,10 @@ static int __ext2_write_inode(struct inode *inode, int do_sync)
    struct ext2_inode * raw_inode = ext2_get_inode(sb, ino, &bh);
    int n;
    int err = 0;
    + __le16 uid_low;
    + __le16 gid_low;
    + __le16 uid_high;
    + __le16 gid_high;

    if (IS_ERR(raw_inode))
    return -EIO;
    @@ -1437,26 +1447,40 @@ static int __ext2_write_inode(struct inode *inode, int do_sync)

    ext2_get_inode_flags(ei);
    raw_inode->i_mode = cpu_to_le16(inode->i_mode);
    + if (uid_valid(EXT2_SB(sb)->s_uid))
    + uid = from_kuid(&init_user_ns, EXT2_SB(sb)->s_diskuid);
    + if (gid_valid(EXT2_SB(sb)->s_gid))
    + gid = from_kgid(&init_user_ns, EXT2_SB(sb)->s_diskgid);
    if (!(test_opt(sb, NO_UID32))) {
    - raw_inode->i_uid_low = cpu_to_le16(low_16_bits(uid));
    - raw_inode->i_gid_low = cpu_to_le16(low_16_bits(gid));
    + uid_low = cpu_to_le16(low_16_bits(uid));
    + 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(uid));
    - raw_inode->i_gid_high = cpu_to_le16(high_16_bits(gid));
    + uid_high = cpu_to_le16(high_16_bits(uid));
    + gid_high = cpu_to_le16(high_16_bits(gid));
    } else {
    - raw_inode->i_uid_high = 0;
    - raw_inode->i_gid_high = 0;
    + uid_high = 0;
    + gid_high = 0;
    }
    } else {
    - raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(uid));
    - raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(gid));
    - raw_inode->i_uid_high = 0;
    - raw_inode->i_gid_high = 0;
    + uid_low = cpu_to_le16(fs_high2lowuid(uid));
    + gid_low = cpu_to_le16(fs_high2lowgid(gid));
    + uid_high = 0;
    + gid_high = 0;
    + }
    + /* don't mangle uid/gid of existing files if override is active */
    + if (!uid_valid(EXT2_SB(sb)->s_uid) || ei->i_state & EXT2_STATE_NEW) {
    + raw_inode->i_uid_high = uid_high;
    + raw_inode->i_uid_low = uid_low;
    }
    + if (!gid_valid(EXT2_SB(sb)->s_gid) || ei->i_state & EXT2_STATE_NEW) {
    + raw_inode->i_gid_high = gid_high;
    + raw_inode->i_gid_low = gid_low;
    + }
    +
    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);
    diff --git a/fs/ext2/super.c b/fs/ext2/super.c
    index af74d9e..0f91dfb 100644
    --- a/fs/ext2/super.c
    +++ b/fs/ext2/super.c
    @@ -237,6 +237,24 @@ static int ext2_show_options(struct seq_file *seq, struct dentry *root)
    seq_printf(seq, ",resgid=%u",
    from_kgid_munged(&init_user_ns, sbi->s_resgid));
    }
    + if (uid_valid(sbi->s_uid)) {
    + if (!uid_eq(sbi->s_uid, sbi->s_diskuid))
    + seq_printf(seq, ",uid=%u:%u",
    + from_kuid_munged(&init_user_ns, sbi->s_uid),
    + from_kuid_munged(&init_user_ns, sbi->s_diskuid));
    + else
    + seq_printf(seq, ",uid=%u",
    + from_kuid_munged(&init_user_ns, sbi->s_uid));
    + }
    + if (gid_valid(sbi->s_gid)) {
    + if (!gid_eq(sbi->s_gid, sbi->s_diskgid))
    + seq_printf(seq, ",gid=%u:%u",
    + from_kgid_munged(&init_user_ns, sbi->s_gid),
    + from_kgid_munged(&init_user_ns, sbi->s_diskgid));
    + else
    + seq_printf(seq, ",gid=%u",
    + from_kgid_munged(&init_user_ns, sbi->s_gid));
    + }
    if (test_opt(sb, ERRORS_RO)) {
    int def_errors = le16_to_cpu(es->s_errors);

    @@ -390,7 +408,8 @@ enum {
    Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug,
    Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
    Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota,
    - Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation
    + Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation,
    + Opt_uid, Opt_diskuid, Opt_gid, Opt_diskgid
    };

    static const match_table_t tokens = {
    @@ -424,6 +443,10 @@ static const match_table_t tokens = {
    {Opt_usrquota, "usrquota"},
    {Opt_reservation, "reservation"},
    {Opt_noreservation, "noreservation"},
    + {Opt_uid, "uid=%u"},
    + {Opt_diskuid, "uid=%u:%u"},
    + {Opt_gid, "gid=%u"},
    + {Opt_diskgid, "gid=%u:%u"},
    {Opt_err, NULL}
    };

    @@ -578,6 +601,64 @@ static int parse_options(char *options, struct super_block *sb)
    clear_opt(sbi->s_mount_opt, RESERVATION);
    ext2_msg(sb, KERN_INFO, "reservations OFF");
    break;
    + case Opt_uid:
    + if (match_int(&args[0], &option))
    + return 0;
    + uid = make_kuid(current_user_ns(), option);
    + if (!uid_valid(uid)) {
    + ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option);
    + return -1;
    + }
    + sbi->s_uid = sbi->s_diskuid = uid;
    + break;
    + case Opt_diskuid:
    + if (match_int(&args[0], &option))
    + return 0;
    + uid = make_kuid(current_user_ns(), option);
    + if (!uid_valid(uid)) {
    + ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option);
    + return -1;
    + }
    + sbi->s_uid = uid;
    +
    + if (match_int(&args[1], &option))
    + return 0;
    + uid = make_kuid(current_user_ns(), option);
    + if (!uid_valid(uid)) {
    + ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option);
    + return -1;
    + }
    + sbi->s_diskuid = uid;
    + break;
    + case Opt_gid:
    + if (match_int(&args[0], &option))
    + return 0;
    + gid = make_kgid(current_user_ns(), option);
    + if (!gid_valid(gid)) {
    + ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option);
    + return -1;
    + }
    + sbi->s_gid = sbi->s_diskgid = gid;
    + break;
    + case Opt_diskgid:
    + if (match_int(&args[0], &option))
    + return 0;
    + gid = make_kgid(current_user_ns(), option);
    + if (!gid_valid(gid)) {
    + ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option);
    + return -1;
    + }
    + sbi->s_gid = gid;
    +
    + if (match_int(&args[1], &option))
    + return 0;
    + gid = make_kgid(current_user_ns(), option);
    + if (!gid_valid(gid)) {
    + ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option);
    + return -1;
    + }
    + sbi->s_diskgid = gid;
    + break;
    case Opt_ignore:
    break;
    default:
    @@ -853,6 +934,10 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)

    sbi->s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid));
    sbi->s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid));
    + sbi->s_uid = INVALID_UID;
    + sbi->s_gid = INVALID_GID;
    + sbi->s_diskuid = INVALID_UID;
    + sbi->s_diskgid = INVALID_GID;

    set_opt(sbi->s_mount_opt, RESERVATION);

    @@ -1256,6 +1341,10 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
    old_opts.s_mount_opt = sbi->s_mount_opt;
    old_opts.s_resuid = sbi->s_resuid;
    old_opts.s_resgid = sbi->s_resgid;
    + old_opts.s_uid = sbi->s_uid;
    + old_opts.s_diskuid = sbi->s_diskuid;
    + old_opts.s_gid = sbi->s_gid;
    + old_opts.s_diskgid = sbi->s_diskgid;

    /*
    * Allow the "check" option to be passed as a remount option.
    @@ -1342,6 +1431,10 @@ restore_opts:
    sbi->s_mount_opt = old_opts.s_mount_opt;
    sbi->s_resuid = old_opts.s_resuid;
    sbi->s_resgid = old_opts.s_resgid;
    + sbi->s_uid = old_opts.s_uid;
    + sbi->s_diskuid = old_opts.s_diskuid;
    + sbi->s_gid = old_opts.s_gid;
    + sbi->s_diskgid = old_opts.s_diskgid;
    sb->s_flags = old_sb_flags;
    spin_unlock(&sbi->s_lock);
    return err;
    --
    1.7.10.4
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2012-08-02 14:41    [W:0.059 / U:0.012 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site