summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2000-08-29 14:45:49 +0000
committerrwatson <rwatson@FreeBSD.org>2000-08-29 14:45:49 +0000
commite54ea574fa306bcc87580c0dc4b763933d819988 (patch)
tree03289d8b1f7f7b111b10a7a131dc2ecbb9a39ae4
parent07eb06526c07cae0b06e3631398a15e4a2c65102 (diff)
downloadFreeBSD-src-e54ea574fa306bcc87580c0dc4b763933d819988.zip
FreeBSD-src-e54ea574fa306bcc87580c0dc4b763933d819988.tar.gz
o Restructure vaccess() so as to check for DAC permission to modify the
object before falling back on privilege. Make vaccess() accept an additional optional argument, privused, to determine whether privilege was required for vaccess() to return 0. Add commented out capability checks for reference. Rename some variables to make it more clear which modes/uids/etc are associated with the object, and which with the access mode. o Update file system use of vaccess() to pass NULL as the optional privused argument. Once additional patches are applied, suser() will no longer set ASU, so privused will permit passing of privilege information up the stack to the caller. Reviewed by: bde, green, phk, -security, others Obtained from: TrustedBSD Project
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c2
-rw-r--r--sys/fs/devfs/devfs_vnops.c2
-rw-r--r--sys/fs/hpfs/hpfs_vnops.c2
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c2
-rw-r--r--sys/fs/ntfs/ntfs_vnops.c2
-rw-r--r--sys/isofs/cd9660/cd9660_vnops.c2
-rw-r--r--sys/kern/vfs_export.c132
-rw-r--r--sys/kern/vfs_subr.c132
-rw-r--r--sys/miscfs/kernfs/kernfs_vnops.c2
-rw-r--r--sys/msdosfs/msdosfs_vnops.c2
-rw-r--r--sys/ntfs/ntfs_vnops.c2
-rw-r--r--sys/sys/vnode.h2
-rw-r--r--sys/ufs/ufs/ufs_vnops.c2
13 files changed, 195 insertions, 91 deletions
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index b4e06fb..f34ebd4 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -155,7 +155,7 @@ cd9660_access(ap)
}
return (vaccess(vp->v_type, ip->inode.iso_mode, ip->inode.iso_uid,
- ip->inode.iso_gid, ap->a_mode, ap->a_cred));
+ ip->inode.iso_gid, ap->a_mode, ap->a_cred, NULL));
}
static int
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 86444ec..0c81ded 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -125,7 +125,7 @@ devfs_access(ap)
de = de->de_dir;
return (vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid,
- ap->a_mode, ap->a_cred));
+ ap->a_mode, ap->a_cred, NULL));
}
static int
diff --git a/sys/fs/hpfs/hpfs_vnops.c b/sys/fs/hpfs/hpfs_vnops.c
index 4f5a735..dcfd2cf 100644
--- a/sys/fs/hpfs/hpfs_vnops.c
+++ b/sys/fs/hpfs/hpfs_vnops.c
@@ -798,7 +798,7 @@ hpfs_access(ap)
}
return (vaccess(vp->v_type, hp->h_mode, hp->h_uid, hp->h_gid,
- ap->a_mode, ap->a_cred));
+ ap->a_mode, ap->a_cred, NULL));
}
/*
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index 09f99e3..f8426de 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -277,7 +277,7 @@ msdosfs_access(ap)
}
return (vaccess(vp->v_type, file_mode, pmp->pm_uid, pmp->pm_gid,
- ap->a_mode, ap->a_cred));
+ ap->a_mode, ap->a_cred, NULL));
}
static int
diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c
index 06dab1c..84b60ea 100644
--- a/sys/fs/ntfs/ntfs_vnops.c
+++ b/sys/fs/ntfs/ntfs_vnops.c
@@ -478,7 +478,7 @@ ntfs_access(ap)
}
return (vaccess(vp->v_type, ip->i_mp->ntm_mode, ip->i_mp->ntm_uid,
- ip->i_mp->ntm_gid, ap->a_mode, ap->a_cred));
+ ip->i_mp->ntm_gid, ap->a_mode, ap->a_cred, NULL));
}
/*
diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c
index b4e06fb..f34ebd4 100644
--- a/sys/isofs/cd9660/cd9660_vnops.c
+++ b/sys/isofs/cd9660/cd9660_vnops.c
@@ -155,7 +155,7 @@ cd9660_access(ap)
}
return (vaccess(vp->v_type, ip->inode.iso_mode, ip->inode.iso_uid,
- ip->inode.iso_gid, ap->a_mode, ap->a_cred));
+ ip->inode.iso_gid, ap->a_mode, ap->a_cred, NULL));
}
static int
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 02c84a8..8b11cc3 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -2986,54 +2986,106 @@ NDFREE(ndp, flags)
}
int
-vaccess(type, file_mode, uid, gid, acc_mode, cred)
+vaccess(type, file_mode, file_uid, file_gid, acc_mode, cred, privused)
enum vtype type;
mode_t file_mode;
- uid_t uid;
- gid_t gid;
+ uid_t file_uid;
+ gid_t file_gid;
mode_t acc_mode;
struct ucred *cred;
+ int *privused;
{
- mode_t mask;
+ mode_t dac_granted;
+#ifdef CAPABILITIES
+ mode_t cap_granted;
+#endif
/*
- * At this point, uid == 0 can do anything.
- * XXX: should use suser() ?
- * XXX: Should only check root-ness after other checks fail.
+ * Look for a normal, non-privileged way to access the file/directory
+ * as requested. If it exists, go with that.
*/
- if (cred->cr_uid == 0)
+
+ if (privused != NULL)
+ *privused = 0;
+
+ dac_granted = 0;
+
+ /* Check the owner. */
+ if (cred->cr_uid == file_uid) {
+ if (file_mode & S_IXUSR)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IRUSR)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWUSR)
+ dac_granted |= VWRITE;
+
+ if ((acc_mode & dac_granted) == acc_mode)
+ return (0);
+
+ goto privcheck;
+ }
+
+ /* Otherwise, check the groups (first match) */
+ if (groupmember(file_gid, cred)) {
+ if (file_mode & S_IXGRP)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IRGRP)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWGRP)
+ dac_granted |= VWRITE;
+
+ if ((acc_mode & dac_granted) == acc_mode)
+ return (0);
+
+ goto privcheck;
+ }
+
+ /* Otherwise, check everyone else. */
+ if (file_mode & S_IXOTH)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IROTH)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWOTH)
+ dac_granted |= VWRITE;
+ if ((acc_mode & dac_granted) == acc_mode)
+ return (0);
+
+privcheck:
+ if (!suser_xxx(cred, NULL, PRISON_ROOT)) {
+ /* XXX audit: privilege used */
+ if (privused != NULL)
+ *privused = 1;
return (0);
+ }
+
+#ifdef CAPABILITIES
+ /*
+ * Build a capability mask to determine if the set of capabilities
+ * satisfies the requirements when combined with the granted mask
+ * from above.
+ * For each capability, if the capability is required, bitwise
+ * or the request type onto the cap_granted mask.
+ */
+ cap_granted = 0;
+ if ((acc_mode & VEXEC) && ((dac_granted & VEXEC) == 0) &&
+ !cap_check_xxx(cred, p, CAP_DAC_EXECUTE, PRISON_ROOT))
+ cap_granted |= VEXEC;
+
+ if ((acc_mode & VREAD) && ((dac_granted & VREAD) == 0) &&
+ !cap_check_xxx(cred, p, CAP_DAC_READ_SEARCH, PRISON_ROOT))
+ cap_granted |= VREAD;
+
+ if ((acc_mode & VWRITE) && ((dac_granted & VWRITE) == 0) &&
+ !cap_check_xxx(cred, p, CAP_DAC_WRITE, PRISON_ROOT))
+ cap_granted |= VWRITE;
+
+ if ((acc_mode & (cap_granted | dac_granted)) == mode) {
+ /* XXX audit: privilege used */
+ if (privused != NULL)
+ *privused = 1;
+ return (0);
+ }
+#endif
- mask = 0;
-
- /* Otherwise, check the owner. */
- if (cred->cr_uid == uid) {
- if (acc_mode & VEXEC)
- mask |= S_IXUSR;
- if (acc_mode & VREAD)
- mask |= S_IRUSR;
- if (acc_mode & VWRITE)
- mask |= S_IWUSR;
- return ((file_mode & mask) == mask ? 0 : EACCES);
- }
-
- /* Otherwise, check for all groups. */
- if (groupmember(gid, cred)) {
- if (acc_mode & VEXEC)
- mask |= S_IXGRP;
- if (acc_mode & VREAD)
- mask |= S_IRGRP;
- if (acc_mode & VWRITE)
- mask |= S_IWGRP;
- return ((file_mode & mask) == mask ? 0 : EACCES);
- }
-
- /* Otherwise, check everyone else. */
- if (acc_mode & VEXEC)
- mask |= S_IXOTH;
- if (acc_mode & VREAD)
- mask |= S_IROTH;
- if (acc_mode & VWRITE)
- mask |= S_IWOTH;
- return ((file_mode & mask) == mask ? 0 : EACCES);
+ return (EACCES);
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 02c84a8..8b11cc3 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2986,54 +2986,106 @@ NDFREE(ndp, flags)
}
int
-vaccess(type, file_mode, uid, gid, acc_mode, cred)
+vaccess(type, file_mode, file_uid, file_gid, acc_mode, cred, privused)
enum vtype type;
mode_t file_mode;
- uid_t uid;
- gid_t gid;
+ uid_t file_uid;
+ gid_t file_gid;
mode_t acc_mode;
struct ucred *cred;
+ int *privused;
{
- mode_t mask;
+ mode_t dac_granted;
+#ifdef CAPABILITIES
+ mode_t cap_granted;
+#endif
/*
- * At this point, uid == 0 can do anything.
- * XXX: should use suser() ?
- * XXX: Should only check root-ness after other checks fail.
+ * Look for a normal, non-privileged way to access the file/directory
+ * as requested. If it exists, go with that.
*/
- if (cred->cr_uid == 0)
+
+ if (privused != NULL)
+ *privused = 0;
+
+ dac_granted = 0;
+
+ /* Check the owner. */
+ if (cred->cr_uid == file_uid) {
+ if (file_mode & S_IXUSR)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IRUSR)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWUSR)
+ dac_granted |= VWRITE;
+
+ if ((acc_mode & dac_granted) == acc_mode)
+ return (0);
+
+ goto privcheck;
+ }
+
+ /* Otherwise, check the groups (first match) */
+ if (groupmember(file_gid, cred)) {
+ if (file_mode & S_IXGRP)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IRGRP)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWGRP)
+ dac_granted |= VWRITE;
+
+ if ((acc_mode & dac_granted) == acc_mode)
+ return (0);
+
+ goto privcheck;
+ }
+
+ /* Otherwise, check everyone else. */
+ if (file_mode & S_IXOTH)
+ dac_granted |= VEXEC;
+ if (file_mode & S_IROTH)
+ dac_granted |= VREAD;
+ if (file_mode & S_IWOTH)
+ dac_granted |= VWRITE;
+ if ((acc_mode & dac_granted) == acc_mode)
+ return (0);
+
+privcheck:
+ if (!suser_xxx(cred, NULL, PRISON_ROOT)) {
+ /* XXX audit: privilege used */
+ if (privused != NULL)
+ *privused = 1;
return (0);
+ }
+
+#ifdef CAPABILITIES
+ /*
+ * Build a capability mask to determine if the set of capabilities
+ * satisfies the requirements when combined with the granted mask
+ * from above.
+ * For each capability, if the capability is required, bitwise
+ * or the request type onto the cap_granted mask.
+ */
+ cap_granted = 0;
+ if ((acc_mode & VEXEC) && ((dac_granted & VEXEC) == 0) &&
+ !cap_check_xxx(cred, p, CAP_DAC_EXECUTE, PRISON_ROOT))
+ cap_granted |= VEXEC;
+
+ if ((acc_mode & VREAD) && ((dac_granted & VREAD) == 0) &&
+ !cap_check_xxx(cred, p, CAP_DAC_READ_SEARCH, PRISON_ROOT))
+ cap_granted |= VREAD;
+
+ if ((acc_mode & VWRITE) && ((dac_granted & VWRITE) == 0) &&
+ !cap_check_xxx(cred, p, CAP_DAC_WRITE, PRISON_ROOT))
+ cap_granted |= VWRITE;
+
+ if ((acc_mode & (cap_granted | dac_granted)) == mode) {
+ /* XXX audit: privilege used */
+ if (privused != NULL)
+ *privused = 1;
+ return (0);
+ }
+#endif
- mask = 0;
-
- /* Otherwise, check the owner. */
- if (cred->cr_uid == uid) {
- if (acc_mode & VEXEC)
- mask |= S_IXUSR;
- if (acc_mode & VREAD)
- mask |= S_IRUSR;
- if (acc_mode & VWRITE)
- mask |= S_IWUSR;
- return ((file_mode & mask) == mask ? 0 : EACCES);
- }
-
- /* Otherwise, check for all groups. */
- if (groupmember(gid, cred)) {
- if (acc_mode & VEXEC)
- mask |= S_IXGRP;
- if (acc_mode & VREAD)
- mask |= S_IRGRP;
- if (acc_mode & VWRITE)
- mask |= S_IWGRP;
- return ((file_mode & mask) == mask ? 0 : EACCES);
- }
-
- /* Otherwise, check everyone else. */
- if (acc_mode & VEXEC)
- mask |= S_IXOTH;
- if (acc_mode & VREAD)
- mask |= S_IROTH;
- if (acc_mode & VWRITE)
- mask |= S_IWOTH;
- return ((file_mode & mask) == mask ? 0 : EACCES);
+ return (EACCES);
}
diff --git a/sys/miscfs/kernfs/kernfs_vnops.c b/sys/miscfs/kernfs/kernfs_vnops.c
index 283167a..72b8e78 100644
--- a/sys/miscfs/kernfs/kernfs_vnops.c
+++ b/sys/miscfs/kernfs/kernfs_vnops.c
@@ -313,7 +313,7 @@ kernfs_access(ap)
if ((amode & VWRITE) && (fmode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0)
return (EPERM);
- return (vaccess(vp->v_tag, fmode, 0, 0, ap->a_mode, ap->a_cred));
+ return (vaccess(vp->v_tag, fmode, 0, 0, ap->a_mode, ap->a_cred, NULL));
}
static int
diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c
index 09f99e3..f8426de 100644
--- a/sys/msdosfs/msdosfs_vnops.c
+++ b/sys/msdosfs/msdosfs_vnops.c
@@ -277,7 +277,7 @@ msdosfs_access(ap)
}
return (vaccess(vp->v_type, file_mode, pmp->pm_uid, pmp->pm_gid,
- ap->a_mode, ap->a_cred));
+ ap->a_mode, ap->a_cred, NULL));
}
static int
diff --git a/sys/ntfs/ntfs_vnops.c b/sys/ntfs/ntfs_vnops.c
index 06dab1c..84b60ea 100644
--- a/sys/ntfs/ntfs_vnops.c
+++ b/sys/ntfs/ntfs_vnops.c
@@ -478,7 +478,7 @@ ntfs_access(ap)
}
return (vaccess(vp->v_type, ip->i_mp->ntm_mode, ip->i_mp->ntm_uid,
- ip->i_mp->ntm_gid, ap->a_mode, ap->a_cred));
+ ip->i_mp->ntm_gid, ap->a_mode, ap->a_cred, NULL));
}
/*
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index a6f234d..de8c038 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -555,7 +555,7 @@ int spec_vnoperate __P((struct vop_generic_args *));
int speedup_syncer __P((void));
int textvp_fullpath __P((struct proc *p, char **retbuf, char **retfreebuf));
int vaccess __P((enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
- mode_t acc_mode, struct ucred *cred));
+ mode_t acc_mode, struct ucred *cred, int *privused));
void vattr_null __P((struct vattr *vap));
int vcount __P((struct vnode *vp));
void vdrop __P((struct vnode *));
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 298c133..c836f5b 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -332,7 +332,7 @@ ufs_access(ap)
return (EPERM);
return (vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
- ap->a_mode, ap->a_cred));
+ ap->a_mode, ap->a_cred, NULL));
}
/* ARGSUSED */
OpenPOWER on IntegriCloud