tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

patch to support >16 bit g/uids on ext2fs



hi folks.

i recently had need to recover some data from an ext3 that used
uids greater than 16 bits, and discovered they were incorrectly
represented as only 16 bits.

after a bit of searching, i noticed that linux has a per-mount
option to disable 32 bit but otherwise has it there by default.

since we don't have a similar mount option, i've made it non
optional in our kernel (simple ways to add it welcome.)

any objections to commiting this?


.mrg.


Index: ext2fs/ext2fs_alloc.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_alloc.c,v
retrieving revision 1.36
diff -p -r1.36 ext2fs_alloc.c
*** ext2fs/ext2fs_alloc.c       16 May 2008 09:22:00 -0000      1.36
--- ext2fs/ext2fs_alloc.c       21 Nov 2008 21:02:58 -0000
*************** ext2fs_blkfree(struct inode *ip, daddr_t
*** 516,522 ****
        if ((u_int)bno >= fs->e2fs.e2fs_bcount) {
                printf("bad block %lld, ino %llu\n", (long long)bno,
                    (unsigned long long)ip->i_number);
!               ext2fs_fserr(fs, ip->i_e2fs_uid, "bad block");
                return;
        }
        error = bread(ip->i_devvp,
--- 516,522 ----
        if ((u_int)bno >= fs->e2fs.e2fs_bcount) {
                printf("bad block %lld, ino %llu\n", (long long)bno,
                    (unsigned long long)ip->i_number);
!               ext2fs_fserr(fs, ip->i_uid, "bad block");
                return;
        }
        error = bread(ip->i_devvp,
Index: ext2fs/ext2fs_bswap.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_bswap.c,v
retrieving revision 1.13
diff -p -r1.13 ext2fs_bswap.c
*** ext2fs/ext2fs_bswap.c       17 Nov 2007 08:34:38 -0000      1.13
--- ext2fs/ext2fs_bswap.c       21 Nov 2008 21:02:58 -0000
*************** void e2fs_i_bswap(struct ext2fs_dinode *
*** 118,123 ****
--- 118,125 ----
        new->e2di_facl          =       bswap32(old->e2di_facl);
        new->e2di_dacl          =       bswap32(old->e2di_dacl);
        new->e2di_faddr         =       bswap32(old->e2di_faddr);
+       new->e2di_uid_high      =       bswap16(old->e2di_uid_high);
+       new->e2di_gid_high      =       bswap16(old->e2di_gid_high);
        memcpy(&new->e2di_blocks[0], &old->e2di_blocks[0],
            (NDADDR + NIADDR) * sizeof(uint32_t));
  }
Index: ext2fs/ext2fs_dinode.h
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_dinode.h,v
retrieving revision 1.16
diff -p -r1.16 ext2fs_dinode.h
*** ext2fs/ext2fs_dinode.h      17 Nov 2007 08:51:51 -0000      1.16
--- ext2fs/ext2fs_dinode.h      21 Nov 2008 21:02:58 -0000
*************** struct ext2fs_dinode {
*** 117,123 ****
        u_int8_t        e2di_nfrag;     /* 116: fragment number */
        u_int8_t        e2di_fsize;     /* 117: fragment size */
        u_int16_t       e2di_linux_reserved2; /* 118 */
!       u_int32_t       e2di_linux_reserved3[2]; /* 120 */
  };
  
  
--- 117,125 ----
        u_int8_t        e2di_nfrag;     /* 116: fragment number */
        u_int8_t        e2di_fsize;     /* 117: fragment size */
        u_int16_t       e2di_linux_reserved2; /* 118 */
!       u_int16_t       e2di_uid_high;  /* 120: Owner UID top 16 bits */
!       u_int16_t       e2di_gid_high;  /* 122: Owner GID top 16 bits */
!       u_int32_t       e2di_linux_reserved3; /* 124 */
  };
  
  
Index: ext2fs/ext2fs_lookup.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_lookup.c,v
retrieving revision 1.55
diff -p -r1.55 ext2fs_lookup.c
*** ext2fs/ext2fs_lookup.c      8 Dec 2007 19:29:53 -0000       1.55
--- ext2fs/ext2fs_lookup.c      21 Nov 2008 21:02:58 -0000
*************** found:
*** 603,610 ****
                 */
                if ((dp->i_e2fs_mode & ISVTX) &&
                    kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) 
&&
!                   kauth_cred_geteuid(cred) != dp->i_e2fs_uid &&
!                   VTOI(tdp)->i_e2fs_uid != kauth_cred_geteuid(cred)) {
                        vput(tdp);
                        return (EPERM);
                }
--- 603,610 ----
                 */
                if ((dp->i_e2fs_mode & ISVTX) &&
                    kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) 
&&
!                   kauth_cred_geteuid(cred) != dp->i_uid &&
!                   VTOI(tdp)->i_uid != kauth_cred_geteuid(cred)) {
                        vput(tdp);
                        return (EPERM);
                }
Index: ext2fs/ext2fs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v
retrieving revision 1.139
diff -p -r1.139 ext2fs_vfsops.c
*** ext2fs/ext2fs_vfsops.c      13 Nov 2008 11:10:41 -0000      1.139
--- ext2fs/ext2fs_vfsops.c      21 Nov 2008 21:02:58 -0000
*************** extern kmutex_t ufs_hashlock;
*** 113,118 ****
--- 113,119 ----
  
  int ext2fs_sbupdate(struct ufsmount *, int);
  static int ext2fs_checksb(struct ext2fs *, int);
+ static void ext2fs_set_inode_guid(struct inode *);
  
  static struct sysctllog *ext2fs_sysctl_log;
  
*************** static const struct ufs_ops ext2fs_ufsop
*** 169,174 ****
--- 170,184 ----
        .uo_unmark_vnode = (void (*)(vnode_t *))nullop,
  };
  
+ /* Fill in the inode uid/gid from ext2 halves.  */
+ static void
+ ext2fs_set_inode_guid(struct inode *ip)
+ {
+ 
+       ip->i_gid = ip->i_e2fs_gid | (ip->i_e2fs_gid_high << 16);
+       ip->i_uid = ip->i_e2fs_uid | (ip->i_e2fs_uid_high << 16);
+ }
+ 
  static int
  ext2fs_modcmd(modcmd_t cmd, void *arg)
  {
*************** loop:
*** 628,633 ****
--- 638,644 ----
                cp = (char *)bp->b_data +
                    (ino_to_fsbo(fs, ip->i_number) * EXT2_DINODE_SIZE);
                e2fs_iload((struct ext2fs_dinode *)cp, ip->i_din.e2fs_din);
+               ext2fs_set_inode_guid(ip);
                brelse(bp, 0);
                vput(vp);
                mutex_enter(&mntvnode_lock);
*************** retry:
*** 1060,1065 ****
--- 1071,1077 ----
        cp = (char *)bp->b_data + (ino_to_fsbo(fs, ino) * EXT2_DINODE_SIZE);
        ip->i_din.e2fs_din = pool_get(&ext2fs_dinode_pool, PR_WAITOK);
        e2fs_iload((struct ext2fs_dinode *)cp, ip->i_din.e2fs_din);
+       ext2fs_set_inode_guid(ip);
        brelse(bp, 0);
  
        /* If the inode was deleted, reset all fields */
Index: ext2fs/ext2fs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_vnops.c,v
retrieving revision 1.82
diff -p -r1.82 ext2fs_vnops.c
*** ext2fs/ext2fs_vnops.c       29 Apr 2008 18:18:09 -0000      1.82
--- ext2fs/ext2fs_vnops.c       21 Nov 2008 21:02:58 -0000
*************** ext2fs_access(void *v)
*** 259,265 ****
                return (EPERM);
  
        return (vaccess(vp->v_type, ip->i_e2fs_mode & ALLPERMS,
!                       ip->i_e2fs_uid, ip->i_e2fs_gid, mode, ap->a_cred));
  }
  
  /* ARGSUSED */
--- 259,265 ----
                return (EPERM);
  
        return (vaccess(vp->v_type, ip->i_e2fs_mode & ALLPERMS,
!                       ip->i_uid, ip->i_gid, mode, ap->a_cred));
  }
  
  /* ARGSUSED */
*************** ext2fs_getattr(void *v)
*** 283,290 ****
        vap->va_fileid = ip->i_number;
        vap->va_mode = ip->i_e2fs_mode & ALLPERMS;
        vap->va_nlink = ip->i_e2fs_nlink;
!       vap->va_uid = ip->i_e2fs_uid;
!       vap->va_gid = ip->i_e2fs_gid;
        vap->va_rdev = (dev_t)fs2h32(ip->i_din.e2fs_din->e2di_rdev);
        vap->va_size = vp->v_size;
        vap->va_atime.tv_sec = ip->i_e2fs_atime;
--- 283,290 ----
        vap->va_fileid = ip->i_number;
        vap->va_mode = ip->i_e2fs_mode & ALLPERMS;
        vap->va_nlink = ip->i_e2fs_nlink;
!       vap->va_uid = ip->i_uid;
!       vap->va_gid = ip->i_gid;
        vap->va_rdev = (dev_t)fs2h32(ip->i_din.e2fs_din->e2di_rdev);
        vap->va_size = vp->v_size;
        vap->va_atime.tv_sec = ip->i_e2fs_atime;
*************** ext2fs_setattr(void *v)
*** 344,350 ****
        if (vap->va_flags != VNOVAL) {
                if (vp->v_mount->mnt_flag & MNT_RDONLY)
                        return (EROFS);
!               if (kauth_cred_geteuid(cred) != ip->i_e2fs_uid &&
                    (error = kauth_authorize_generic(cred, 
KAUTH_GENERIC_ISSUSER,
                    NULL)))
                        return (error);
--- 344,350 ----
        if (vap->va_flags != VNOVAL) {
                if (vp->v_mount->mnt_flag & MNT_RDONLY)
                        return (EROFS);
!               if (kauth_cred_geteuid(cred) != ip->i_uid &&
                    (error = kauth_authorize_generic(cred, 
KAUTH_GENERIC_ISSUSER,
                    NULL)))
                        return (error);
*************** ext2fs_setattr(void *v)
*** 408,414 ****
        if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
                if (vp->v_mount->mnt_flag & MNT_RDONLY)
                        return (EROFS);
!               if (kauth_cred_geteuid(cred) != ip->i_e2fs_uid &&
                        (error = kauth_authorize_generic(cred, 
KAUTH_GENERIC_ISSUSER, 
                        NULL)) &&
                        ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
--- 408,414 ----
        if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
                if (vp->v_mount->mnt_flag & MNT_RDONLY)
                        return (EROFS);
!               if (kauth_cred_geteuid(cred) != ip->i_uid &&
                        (error = kauth_authorize_generic(cred, 
KAUTH_GENERIC_ISSUSER, 
                        NULL)) &&
                        ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
*************** ext2fs_chmod(struct vnode *vp, int mode,
*** 444,457 ****
        struct inode *ip = VTOI(vp);
        int error, ismember = 0;
  
!       if (kauth_cred_geteuid(cred) != ip->i_e2fs_uid &&
            (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
            NULL)))
                return (error);
        if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL)) {
                if (vp->v_type != VDIR && (mode & S_ISTXT))
                        return (EFTYPE);
!               if ((kauth_cred_ismember_gid(cred, ip->i_e2fs_gid, &ismember) 
!= 0 ||
                    !ismember) && (mode & ISGID))
                        return (EPERM);
        }
--- 444,457 ----
        struct inode *ip = VTOI(vp);
        int error, ismember = 0;
  
!       if (kauth_cred_geteuid(cred) != ip->i_uid &&
            (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
            NULL)))
                return (error);
        if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL)) {
                if (vp->v_type != VDIR && (mode & S_ISTXT))
                        return (EFTYPE);
!               if ((kauth_cred_ismember_gid(cred, ip->i_gid, &ismember) != 0 ||
                    !ismember) && (mode & ISGID))
                        return (EPERM);
        }
*************** ext2fs_chown(struct vnode *vp, uid_t uid
*** 475,499 ****
        int error = 0, ismember = 0;
  
        if (uid == (uid_t)VNOVAL)
!               uid = ip->i_e2fs_uid;
        if (gid == (gid_t)VNOVAL)
!               gid = ip->i_e2fs_gid;
        /*
         * If we don't own the file, are trying to change the owner
         * of the file, or are not a member of the target group,
         * the caller must be superuser or the call fails.
         */
!       if ((kauth_cred_geteuid(cred) != ip->i_e2fs_uid || uid != 
ip->i_e2fs_uid ||
!           (gid != ip->i_e2fs_gid &&
            !(kauth_cred_getegid(cred) == gid ||
            (kauth_cred_ismember_gid(cred, gid, &ismember) == 0 && ismember)))) 
&&
            (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, 
NULL)))
                return (error);
!       ogid = ip->i_e2fs_gid;
!       ouid = ip->i_e2fs_uid;
  
!       ip->i_e2fs_gid = gid;
!       ip->i_e2fs_uid = uid;
        if (ouid != uid || ogid != gid)
                ip->i_flag |= IN_CHANGE;
        if (ouid != uid && kauth_authorize_generic(cred,
--- 475,501 ----
        int error = 0, ismember = 0;
  
        if (uid == (uid_t)VNOVAL)
!               uid = ip->i_uid;
        if (gid == (gid_t)VNOVAL)
!               gid = ip->i_gid;
        /*
         * If we don't own the file, are trying to change the owner
         * of the file, or are not a member of the target group,
         * the caller must be superuser or the call fails.
         */
!       if ((kauth_cred_geteuid(cred) != ip->i_uid || uid != ip->i_uid ||
!           (gid != ip->i_gid &&
            !(kauth_cred_getegid(cred) == gid ||
            (kauth_cred_ismember_gid(cred, gid, &ismember) == 0 && ismember)))) 
&&
            (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, 
NULL)))
                return (error);
!       ogid = ip->i_gid;
!       ouid = ip->i_uid;
  
!       ip->i_e2fs_gid = gid & 0xffff;
!       ip->i_e2fs_uid = uid & 0xffff;
!       ip->i_e2fs_gid_high = (gid >> 16) & 0xffff;
!       ip->i_e2fs_uid_high = (uid >> 16) & 0xffff;
        if (ouid != uid || ogid != gid)
                ip->i_flag |= IN_CHANGE;
        if (ouid != uid && kauth_authorize_generic(cred,
*************** abortit:
*** 865,872 ****
                if ((dp->i_e2fs_mode & S_ISTXT) &&
                    kauth_authorize_generic(tcnp->cn_cred,
                     KAUTH_GENERIC_ISSUSER, NULL) != 0 &&
!                   kauth_cred_geteuid(tcnp->cn_cred) != dp->i_e2fs_uid &&
!                   xp->i_e2fs_uid != kauth_cred_geteuid(tcnp->cn_cred)) {
                        error = EPERM;
                        goto bad;
                }
--- 867,874 ----
                if ((dp->i_e2fs_mode & S_ISTXT) &&
                    kauth_authorize_generic(tcnp->cn_cred,
                     KAUTH_GENERIC_ISSUSER, NULL) != 0 &&
!                   kauth_cred_geteuid(tcnp->cn_cred) != dp->i_uid &&
!                   xp->i_uid != kauth_cred_geteuid(tcnp->cn_cred)) {
                        error = EPERM;
                        goto bad;
                }
*************** ext2fs_mkdir(void *v)
*** 1069,1076 ****
        if ((error = ext2fs_valloc(dvp, dmode, cnp->cn_cred, &tvp)) != 0)
                goto out;
        ip = VTOI(tvp);
!       ip->i_e2fs_uid = kauth_cred_geteuid(cnp->cn_cred);
        ip->i_e2fs_gid = dp->i_e2fs_gid;
        ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
        ip->i_e2fs_mode = dmode;
        tvp->v_type = VDIR;     /* Rest init'd in getnewvnode(). */
--- 1071,1081 ----
        if ((error = ext2fs_valloc(dvp, dmode, cnp->cn_cred, &tvp)) != 0)
                goto out;
        ip = VTOI(tvp);
!       ip->i_uid = kauth_cred_geteuid(cnp->cn_cred);
!       ip->i_e2fs_uid = ip->i_uid & 0xffff;
!       ip->i_e2fs_uid_high = (ip->i_uid >> 16) & 0xffff;
        ip->i_e2fs_gid = dp->i_e2fs_gid;
+       ip->i_e2fs_gid_high = dp->i_e2fs_gid_high;
        ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
        ip->i_e2fs_mode = dmode;
        tvp->v_type = VDIR;     /* Rest init'd in getnewvnode(). */
*************** ext2fs_makeinode(int mode, struct vnode 
*** 1423,1435 ****
        }
        ip = VTOI(tvp);
        ip->i_e2fs_gid = pdir->i_e2fs_gid;
!       ip->i_e2fs_uid = kauth_cred_geteuid(cnp->cn_cred);
        ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
        ip->i_e2fs_mode = mode;
        tvp->v_type = IFTOVT(mode);     /* Rest init'd in getnewvnode(). */
        ip->i_e2fs_nlink = 1;
        if ((ip->i_e2fs_mode & ISGID) && (kauth_cred_ismember_gid(cnp->cn_cred,
!           ip->i_e2fs_gid, &ismember) != 0 || !ismember) &&
            kauth_authorize_generic(cnp->cn_cred, KAUTH_GENERIC_ISSUSER, NULL))
                ip->i_e2fs_mode &= ~ISGID;
  
--- 1428,1444 ----
        }
        ip = VTOI(tvp);
        ip->i_e2fs_gid = pdir->i_e2fs_gid;
!       ip->i_e2fs_gid_high = pdir->i_e2fs_gid_high;
!       ip->i_gid = ip->i_e2fs_gid | (ip->i_e2fs_gid_high << 16);
!       ip->i_uid = kauth_cred_geteuid(cnp->cn_cred);
!       ip->i_e2fs_uid = ip->i_uid & 0xffff;
!       ip->i_e2fs_uid_high = (ip->i_uid >> 16) & 0xffff;
        ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
        ip->i_e2fs_mode = mode;
        tvp->v_type = IFTOVT(mode);     /* Rest init'd in getnewvnode(). */
        ip->i_e2fs_nlink = 1;
        if ((ip->i_e2fs_mode & ISGID) && (kauth_cred_ismember_gid(cnp->cn_cred,
!           ip->i_gid, &ismember) != 0 || !ismember) &&
            kauth_authorize_generic(cnp->cn_cred, KAUTH_GENERIC_ISSUSER, NULL))
                ip->i_e2fs_mode &= ~ISGID;
  
Index: ufs/inode.h
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/inode.h,v
retrieving revision 1.54
diff -p -r1.54 inode.h
*** ufs/inode.h 23 Sep 2008 12:37:05 -0000      1.54
--- ufs/inode.h 21 Nov 2008 21:02:58 -0000
*************** struct inode {
*** 210,215 ****
--- 210,217 ----
  #define       i_e2fs_nfrag            i_din.e2fs_din->e2di_nfrag
  #define       i_e2fs_fsize            i_din.e2fs_din->e2di_fsize
  #define       i_e2fs_rdev             i_din.e2fs_din->e2di_rdev
+ #define       i_e2fs_uid_high         i_din.e2fs_din->e2di_uid_high
+ #define       i_e2fs_gid_high         i_din.e2fs_din->e2di_gid_high
  
  /* These flags are kept in i_flag. */
  #define       IN_ACCESS       0x0001          /* Access time update request. 
*/


Home | Main Index | Thread Index | Old Index