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