summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authornatano <natano@openbsd.org>2018-12-23 10:46:51 +0000
committernatano <natano@openbsd.org>2018-12-23 10:46:51 +0000
commiteae075513215a8fc3d71561da8bc7465610a0457 (patch)
treeb92b3ef5b6f520d7dbd88f1e45924b3fc1ed03d5 /sys/ufs
parentEVP_MD_CTX_cleanup() is deprecated and doesn't free, so recommend using (diff)
downloadwireguard-openbsd-eae075513215a8fc3d71561da8bc7465610a0457.tar.xz
wireguard-openbsd-eae075513215a8fc3d71561da8bc7465610a0457.zip
Rectify some issues with the noperm mount flag; the root vnode was not
protected properly and files without any x bit set were accidentaly considered executable when checked with access(2). Issues found and reported by deraadt, halex, reyk, tb ok deraadt
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_vnops.c4
-rw-r--r--sys/ufs/ufs/ufs_lookup.c4
-rw-r--r--sys/ufs/ufs/ufs_vnops.c41
3 files changed, 26 insertions, 23 deletions
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 09ca4bd0914..f5cf41063c6 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_vnops.c,v 1.92 2018/07/21 09:35:08 anton Exp $ */
+/* $OpenBSD: ffs_vnops.c,v 1.93 2018/12/23 10:46:51 natano Exp $ */
/* $NetBSD: ffs_vnops.c,v 1.7 1996/05/11 18:27:24 mycroft Exp $ */
/*
@@ -391,7 +391,7 @@ ffs_write(void *v)
* tampering.
*/
if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0 &&
- (vp->v_mount->mnt_flag & MNT_NOPERM) == 0)
+ !vnoperm(vp))
DIP_ASSIGN(ip, mode, DIP(ip, mode) & ~(ISUID | ISGID));
if (resid > uio->uio_resid)
VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index 448edb5a3f2..3825de24188 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ufs_lookup.c,v 1.53 2018/09/06 11:50:54 jsg Exp $ */
+/* $OpenBSD: ufs_lookup.c,v 1.54 2018/12/23 10:46:51 natano Exp $ */
/* $NetBSD: ufs_lookup.c,v 1.7 1996/02/09 22:36:06 christos Exp $ */
/*
@@ -496,7 +496,7 @@ found:
if ((DIP(dp, mode) & ISVTX) &&
cred->cr_uid != 0 &&
cred->cr_uid != DIP(dp, uid) &&
- (vdp->v_mount->mnt_flag & MNT_NOPERM) == 0 &&
+ !vnoperm(vdp) &&
DIP(VTOI(tdp), uid) != cred->cr_uid) {
vput(tdp);
return (EPERM);
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 20f2a179e6b..82ebd356af0 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ufs_vnops.c,v 1.142 2018/06/21 14:17:23 visa Exp $ */
+/* $OpenBSD: ufs_vnops.c,v 1.143 2018/12/23 10:46:51 natano Exp $ */
/* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */
/*
@@ -274,9 +274,13 @@ ufs_access(void *v)
if ((mode & VWRITE) && (DIP(ip, flags) & IMMUTABLE))
return (EPERM);
- if ((vp->v_mount->mnt_flag & MNT_NOPERM) &&
- (vp->v_flag & VROOT) == 0)
- return (0);
+ if (vnoperm(vp)) {
+ /* For VEXEC, at least one of the execute bits must be set. */
+ if ((mode & VEXEC) && vp->v_type != VDIR &&
+ (DIP(ip, mode) & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)
+ return EACCES;
+ return 0;
+ }
return (vaccess(vp->v_type, DIP(ip, mode), DIP(ip, uid), DIP(ip, gid),
mode, ap->a_cred));
@@ -353,10 +357,10 @@ ufs_setattr(void *v)
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
if (cred->cr_uid != DIP(ip, uid) &&
- (vp->v_mount->mnt_flag & MNT_NOPERM) == 0 &&
+ !vnoperm(vp) &&
(error = suser_ucred(cred)))
return (error);
- if (cred->cr_uid == 0) {
+ if (cred->cr_uid == 0 || vnoperm(vp)) {
if ((DIP(ip, flags) & (SF_IMMUTABLE | SF_APPEND)) &&
securelevel > 0)
return (EPERM);
@@ -413,7 +417,7 @@ ufs_setattr(void *v)
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
if (cred->cr_uid != DIP(ip, uid) &&
- (vp->v_mount->mnt_flag & MNT_NOPERM) == 0 &&
+ !vnoperm(vp) &&
(error = suser_ucred(cred)) &&
((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
(error = VOP_ACCESS(vp, VWRITE, cred, p))))
@@ -461,11 +465,10 @@ ufs_chmod(struct vnode *vp, int mode, struct ucred *cred, struct proc *p)
int error;
if (cred->cr_uid != DIP(ip, uid) &&
- (vp->v_mount->mnt_flag & MNT_NOPERM) == 0 &&
+ !vnoperm(vp) &&
(error = suser_ucred(cred)))
return (error);
- if (cred->cr_uid &&
- (vp->v_mount->mnt_flag & MNT_NOPERM) == 0) {
+ if (cred->cr_uid && !vnoperm(vp)) {
if (vp->v_type != VDIR && (mode & S_ISTXT))
return (EFTYPE);
if (!groupmember(DIP(ip, gid), cred) && (mode & ISGID))
@@ -505,7 +508,7 @@ ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
*/
if ((cred->cr_uid != DIP(ip, uid) || uid != DIP(ip, uid) ||
(gid != DIP(ip, gid) && !groupmember(gid, cred))) &&
- (vp->v_mount->mnt_flag & MNT_NOPERM) == 0 &&
+ !vnoperm(vp) &&
(error = suser_ucred(cred)))
return (error);
ogid = DIP(ip, gid);
@@ -546,12 +549,12 @@ ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
if (ouid != uid || ogid != gid)
ip->i_flag |= IN_CHANGE;
- if (ouid != uid && cred->cr_uid != 0 &&
- (vp->v_mount->mnt_flag & MNT_NOPERM) == 0)
- DIP_AND(ip, mode, ~ISUID);
- if (ogid != gid && cred->cr_uid != 0 &&
- (vp->v_mount->mnt_flag & MNT_NOPERM) == 0)
- DIP_AND(ip, mode, ~ISGID);
+ if (!vnoperm(vp)) {
+ if (ouid != uid && cred->cr_uid != 0)
+ DIP_AND(ip, mode, ~ISUID);
+ if (ogid != gid && cred->cr_uid != 0)
+ DIP_AND(ip, mode, ~ISGID);
+ }
return (0);
error:
@@ -975,7 +978,7 @@ abortit:
if ((DIP(dp, mode) & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
tcnp->cn_cred->cr_uid != DIP(dp, uid) &&
DIP(xp, uid )!= tcnp->cn_cred->cr_uid &&
- (tdvp->v_mount->mnt_flag & MNT_NOPERM) == 0) {
+ !vnoperm(tdvp)) {
error = EPERM;
goto bad;
}
@@ -1853,7 +1856,7 @@ ufs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
softdep_change_linkcnt(ip, 0);
if ((DIP(ip, mode) & ISGID) &&
!groupmember(DIP(ip, gid), cnp->cn_cred) &&
- (dvp->v_mount->mnt_flag & MNT_NOPERM) == 0 &&
+ !vnoperm(dvp) &&
suser_ucred(cnp->cn_cred))
DIP_AND(ip, mode, ~ISGID);