Changeset View
Changeset View
Standalone View
Standalone View
sys/ufs/ufs/ufs_vnops.c
Show First 20 Lines • Show All 463 Lines • ▼ Show 20 Lines | if (I_IS_UFS1(ip)) { | ||||
vap->va_atime.tv_nsec = ip->i_din2->di_atimensec; | vap->va_atime.tv_nsec = ip->i_din2->di_atimensec; | ||||
} | } | ||||
VI_UNLOCK(vp); | VI_UNLOCK(vp); | ||||
/* | /* | ||||
* Copy from inode table | * Copy from inode table | ||||
*/ | */ | ||||
vap->va_fsid = dev2udev(ITOUMP(ip)->um_dev); | vap->va_fsid = dev2udev(ITOUMP(ip)->um_dev); | ||||
vap->va_fileid = ip->i_number; | vap->va_fileid = ip->i_number; | ||||
vap->va_mode = ip->i_mode & ~IFMT; | vap->va_mode = ip->i_mode & ~UFS_IFMT; | ||||
vap->va_nlink = ip->i_effnlink; | vap->va_nlink = ip->i_effnlink; | ||||
vap->va_uid = ip->i_uid; | vap->va_uid = ip->i_uid; | ||||
vap->va_gid = ip->i_gid; | vap->va_gid = ip->i_gid; | ||||
if (I_IS_UFS1(ip)) { | if (I_IS_UFS1(ip)) { | ||||
vap->va_rdev = ip->i_din1->di_rdev; | vap->va_rdev = ip->i_din1->di_rdev; | ||||
vap->va_size = ip->i_din1->di_size; | vap->va_size = ip->i_din1->di_size; | ||||
vap->va_mtime.tv_sec = ip->i_din1->di_mtime; | vap->va_mtime.tv_sec = ip->i_din1->di_mtime; | ||||
vap->va_mtime.tv_nsec = ip->i_din1->di_mtimensec; | vap->va_mtime.tv_nsec = ip->i_din1->di_mtimensec; | ||||
▲ Show 20 Lines • Show All 263 Lines • ▼ Show 20 Lines | ufs_chmod(vp, mode, cred, td) | ||||
* as well as set the setgid bit on a file with a group that the | * as well as set the setgid bit on a file with a group that the | ||||
* process is not a member of. Both of these are allowed in | * process is not a member of. Both of these are allowed in | ||||
* jail(8). | * jail(8). | ||||
*/ | */ | ||||
if (vp->v_type != VDIR && (mode & S_ISTXT)) { | if (vp->v_type != VDIR && (mode & S_ISTXT)) { | ||||
if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, 0)) | if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, 0)) | ||||
return (EFTYPE); | return (EFTYPE); | ||||
} | } | ||||
if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) { | if (!groupmember(ip->i_gid, cred) && (mode & UFS_ISGID)) { | ||||
error = priv_check_cred(cred, PRIV_VFS_SETGID, 0); | error = priv_check_cred(cred, PRIV_VFS_SETGID, 0); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Deny setting setuid if we are not the file owner. | * Deny setting setuid if we are not the file owner. | ||||
*/ | */ | ||||
if ((mode & ISUID) && ip->i_uid != cred->cr_uid) { | if ((mode & UFS_ISUID) && ip->i_uid != cred->cr_uid) { | ||||
error = priv_check_cred(cred, PRIV_VFS_ADMIN, 0); | error = priv_check_cred(cred, PRIV_VFS_ADMIN, 0); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
ip->i_mode &= ~ALLPERMS; | ip->i_mode &= ~ALLPERMS; | ||||
ip->i_mode |= (mode & ALLPERMS); | ip->i_mode |= (mode & ALLPERMS); | ||||
DIP_SET(ip, i_mode, ip->i_mode); | DIP_SET(ip, i_mode, ip->i_mode); | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | if (getinoquota(ip) == 0) { | ||||
(void) getinoquota(ip); | (void) getinoquota(ip); | ||||
} | } | ||||
return (error); | return (error); | ||||
good: | good: | ||||
if (getinoquota(ip)) | if (getinoquota(ip)) | ||||
panic("ufs_chown: lost quota"); | panic("ufs_chown: lost quota"); | ||||
#endif /* QUOTA */ | #endif /* QUOTA */ | ||||
ip->i_flag |= IN_CHANGE; | ip->i_flag |= IN_CHANGE; | ||||
if ((ip->i_mode & (ISUID | ISGID)) && (ouid != uid || ogid != gid)) { | if ((ip->i_mode & (UFS_ISUID | UFS_ISGID)) && | ||||
(ouid != uid || ogid != gid)) { | |||||
if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID, 0)) { | if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID, 0)) { | ||||
ip->i_mode &= ~(ISUID | ISGID); | ip->i_mode &= ~(UFS_ISUID | UFS_ISGID); | ||||
DIP_SET(ip, i_mode, ip->i_mode); | DIP_SET(ip, i_mode, ip->i_mode); | ||||
} | } | ||||
} | } | ||||
error = UFS_UPDATE(vp, 0); | error = UFS_UPDATE(vp, 0); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 369 Lines • ▼ Show 20 Lines | if (fip->i_nlink >= LINK_MAX) { | ||||
error = EMLINK; | error = EMLINK; | ||||
goto unlockout; | goto unlockout; | ||||
} | } | ||||
if ((fip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) | if ((fip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) | ||||
|| (fdp->i_flags & APPEND)) { | || (fdp->i_flags & APPEND)) { | ||||
error = EPERM; | error = EPERM; | ||||
goto unlockout; | goto unlockout; | ||||
} | } | ||||
if ((fip->i_mode & IFMT) == IFDIR) { | if ((fip->i_mode & UFS_IFMT) == UFS_IFDIR) { | ||||
/* | /* | ||||
* Avoid ".", "..", and aliases of "." for obvious reasons. | * Avoid ".", "..", and aliases of "." for obvious reasons. | ||||
*/ | */ | ||||
if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || | if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || | ||||
fdp == fip || | fdp == fip || | ||||
(fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) { | (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto unlockout; | goto unlockout; | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | if ((tdp->i_mode & S_ISTXT) && | ||||
error = EPERM; | error = EPERM; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
/* | /* | ||||
* Target must be empty if a directory and have no links | * Target must be empty if a directory and have no links | ||||
* to it. Also, ensure source and target are compatible | * to it. Also, ensure source and target are compatible | ||||
* (both directories, or both not directories). | * (both directories, or both not directories). | ||||
*/ | */ | ||||
if ((tip->i_mode & IFMT) == IFDIR) { | if ((tip->i_mode & UFS_IFMT) == UFS_IFDIR) { | ||||
if ((tip->i_effnlink > 2) || | if ((tip->i_effnlink > 2) || | ||||
!ufs_dirempty(tip, tdp->i_number, tcnp->cn_cred)) { | !ufs_dirempty(tip, tdp->i_number, tcnp->cn_cred)) { | ||||
error = ENOTEMPTY; | error = ENOTEMPTY; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
if (!doingdirectory) { | if (!doingdirectory) { | ||||
error = ENOTDIR; | error = ENOTDIR; | ||||
goto bad; | goto bad; | ||||
▲ Show 20 Lines • Show All 374 Lines • ▼ Show 20 Lines | if ((cnp->cn_flags & HASBUF) == 0) | ||||
panic("ufs_mkdir: no name"); | panic("ufs_mkdir: no name"); | ||||
#endif | #endif | ||||
dp = VTOI(dvp); | dp = VTOI(dvp); | ||||
if ((nlink_t)dp->i_nlink >= LINK_MAX) { | if ((nlink_t)dp->i_nlink >= LINK_MAX) { | ||||
error = EMLINK; | error = EMLINK; | ||||
goto out; | goto out; | ||||
} | } | ||||
dmode = vap->va_mode & 0777; | dmode = vap->va_mode & 0777; | ||||
dmode |= IFDIR; | dmode |= UFS_IFDIR; | ||||
/* | /* | ||||
* Must simulate part of ufs_makeinode here to acquire the inode, | * Must simulate part of ufs_makeinode here to acquire the inode, | ||||
* but not have it entered in the parent directory. The entry is | * but not have it entered in the parent directory. The entry is | ||||
* made later after writing "." and ".." entries. | * made later after writing "." and ".." entries. | ||||
*/ | */ | ||||
if (dp->i_effnlink < 2) { | if (dp->i_effnlink < 2) { | ||||
print_bad_link_count("ufs_mkdir", dvp); | print_bad_link_count("ufs_mkdir", dvp); | ||||
error = EINVAL; | error = EINVAL; | ||||
Show All 16 Lines | #endif | ||||
* If we are hacking owners here, (only do this where told to) | * If we are hacking owners here, (only do this where told to) | ||||
* and we are not giving it TO root, (would subvert quotas) | * and we are not giving it TO root, (would subvert quotas) | ||||
* then go ahead and give it to the other user. | * then go ahead and give it to the other user. | ||||
* The new directory also inherits the SUID bit. | * The new directory also inherits the SUID bit. | ||||
* If user's UID and dir UID are the same, | * If user's UID and dir UID are the same, | ||||
* 'give it away' so that the SUID is still forced on. | * 'give it away' so that the SUID is still forced on. | ||||
*/ | */ | ||||
if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) && | if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) && | ||||
(dp->i_mode & ISUID) && dp->i_uid) { | (dp->i_mode & UFS_ISUID) && dp->i_uid) { | ||||
dmode |= ISUID; | dmode |= UFS_ISUID; | ||||
ip->i_uid = dp->i_uid; | ip->i_uid = dp->i_uid; | ||||
DIP_SET(ip, i_uid, dp->i_uid); | DIP_SET(ip, i_uid, dp->i_uid); | ||||
#ifdef QUOTA | #ifdef QUOTA | ||||
if (dp->i_uid != cnp->cn_cred->cr_uid) { | if (dp->i_uid != cnp->cn_cred->cr_uid) { | ||||
/* | /* | ||||
* Make sure the correct user gets charged | * Make sure the correct user gets charged | ||||
* for the space. | * for the space. | ||||
* Make a dummy credential for the victim. | * Make a dummy credential for the victim. | ||||
▲ Show 20 Lines • Show All 273 Lines • ▼ Show 20 Lines | struct vop_symlink_args /* { | ||||
struct vattr *a_vap; | struct vattr *a_vap; | ||||
char *a_target; | char *a_target; | ||||
} */ *ap; | } */ *ap; | ||||
{ | { | ||||
struct vnode *vp, **vpp = ap->a_vpp; | struct vnode *vp, **vpp = ap->a_vpp; | ||||
struct inode *ip; | struct inode *ip; | ||||
int len, error; | int len, error; | ||||
error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, | error = ufs_makeinode(UFS_IFLNK | ap->a_vap->va_mode, ap->a_dvp, | ||||
vpp, ap->a_cnp, "ufs_symlink"); | vpp, ap->a_cnp, "ufs_symlink"); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
vp = *vpp; | vp = *vpp; | ||||
len = strlen(ap->a_target); | len = strlen(ap->a_target); | ||||
if (len < vp->v_mount->mnt_maxsymlinklen) { | if (len < vp->v_mount->mnt_maxsymlinklen) { | ||||
ip = VTOI(vp); | ip = VTOI(vp); | ||||
bcopy(ap->a_target, SHORTLINK(ip), len); | bcopy(ap->a_target, SHORTLINK(ip), len); | ||||
▲ Show 20 Lines • Show All 454 Lines • ▼ Show 20 Lines | ufs_makeinode(mode, dvp, vpp, cnp, callfunc) | ||||
int error; | int error; | ||||
pdir = VTOI(dvp); | pdir = VTOI(dvp); | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
if ((cnp->cn_flags & HASBUF) == 0) | if ((cnp->cn_flags & HASBUF) == 0) | ||||
panic("%s: no name", callfunc); | panic("%s: no name", callfunc); | ||||
#endif | #endif | ||||
*vpp = NULL; | *vpp = NULL; | ||||
if ((mode & IFMT) == 0) | if ((mode & UFS_IFMT) == 0) | ||||
mode |= IFREG; | mode |= UFS_IFREG; | ||||
if (pdir->i_effnlink < 2) { | if (pdir->i_effnlink < 2) { | ||||
print_bad_link_count(callfunc, dvp); | print_bad_link_count(callfunc, dvp); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp); | error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
Show All 10 Lines | #endif | ||||
/* | /* | ||||
* If we are not the owner of the directory, | * If we are not the owner of the directory, | ||||
* and we are hacking owners here, (only do this where told to) | * and we are hacking owners here, (only do this where told to) | ||||
* and we are not giving it TO root, (would subvert quotas) | * and we are not giving it TO root, (would subvert quotas) | ||||
* then go ahead and give it to the other user. | * then go ahead and give it to the other user. | ||||
* Note that this drops off the execute bits for security. | * Note that this drops off the execute bits for security. | ||||
*/ | */ | ||||
if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) && | if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) && | ||||
(pdir->i_mode & ISUID) && | (pdir->i_mode & UFS_ISUID) && | ||||
(pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) { | (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) { | ||||
ip->i_uid = pdir->i_uid; | ip->i_uid = pdir->i_uid; | ||||
DIP_SET(ip, i_uid, ip->i_uid); | DIP_SET(ip, i_uid, ip->i_uid); | ||||
mode &= ~07111; | mode &= ~07111; | ||||
#ifdef QUOTA | #ifdef QUOTA | ||||
/* | /* | ||||
* Make sure the correct user gets charged | * Make sure the correct user gets charged | ||||
* for the space. | * for the space. | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | #endif /* !SUIDDIR */ | ||||
ip->i_mode = mode; | ip->i_mode = mode; | ||||
DIP_SET(ip, i_mode, mode); | DIP_SET(ip, i_mode, mode); | ||||
tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ | tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ | ||||
ip->i_effnlink = 1; | ip->i_effnlink = 1; | ||||
ip->i_nlink = 1; | ip->i_nlink = 1; | ||||
DIP_SET(ip, i_nlink, 1); | DIP_SET(ip, i_nlink, 1); | ||||
if (DOINGSOFTDEP(tvp)) | if (DOINGSOFTDEP(tvp)) | ||||
softdep_setup_create(VTOI(dvp), ip); | softdep_setup_create(VTOI(dvp), ip); | ||||
if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && | if ((ip->i_mode & UFS_ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && | ||||
priv_check_cred(cnp->cn_cred, PRIV_VFS_SETGID, 0)) { | priv_check_cred(cnp->cn_cred, PRIV_VFS_SETGID, 0)) { | ||||
ip->i_mode &= ~ISGID; | ip->i_mode &= ~UFS_ISGID; | ||||
DIP_SET(ip, i_mode, ip->i_mode); | DIP_SET(ip, i_mode, ip->i_mode); | ||||
} | } | ||||
if (cnp->cn_flags & ISWHITEOUT) { | if (cnp->cn_flags & ISWHITEOUT) { | ||||
ip->i_flags |= UF_OPAQUE; | ip->i_flags |= UF_OPAQUE; | ||||
DIP_SET(ip, i_flags, ip->i_flags); | DIP_SET(ip, i_flags, ip->i_flags); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 141 Lines • Show Last 20 Lines |