aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 b4e06fb5d9ad..f34ebd44634e 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 86444ec10e7b..0c81ded86a3a 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 4f5a7354c665..dcfd2cf5bf8a 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 09f99e39d87f..f8426def67da 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 06dab1c50c27..84b60ea824a9 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 b4e06fb5d9ad..f34ebd44634e 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 02c84a887442..8b11cc3eca79 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 02c84a887442..8b11cc3eca79 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 283167abc5fa..72b8e7804d0a 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 09f99e39d87f..f8426def67da 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 06dab1c50c27..84b60ea824a9 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 a6f234d80bc0..de8c03876a66 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 298c1339ce4a..c836f5babde4 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 */