summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_export.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_export.c')
-rw-r--r--sys/kern/vfs_export.c132
1 files changed, 92 insertions, 40 deletions
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);
}
OpenPOWER on IntegriCloud