From 3cf17d30fac99853c5324167d35ba4db667cd819 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Fri, 17 Mar 1995 18:54:45 +0000 Subject: Back out changes to protid and associated permission checking functions. --- libdiskfs/diskfs.h | 134 +++++++++++++---------------------------------------- 1 file changed, 33 insertions(+), 101 deletions(-) (limited to 'libdiskfs') diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h index 5735bee0..1d24661d 100644 --- a/libdiskfs/diskfs.h +++ b/libdiskfs/diskfs.h @@ -20,24 +20,15 @@ #include -/* Identifies a given user; these are chained for the implementation - of the layering semantics of io_restrict_auth. */ -struct userid -{ - int refcnt; - uid_t *uids, *gids; - int nuids, ngids; - struct userid *next; -}; - /* Each user port referring to a file points to one of these (with the aid of the ports library. */ struct protid { struct port_info pi; /* libports info block */ - /* Identifies chain of user ids. */ - struct userid *id; + /* User identification */ + uid_t *uids, *gids; + int nuids, ngids; /* Object this refers to */ struct peropen *po; @@ -134,7 +125,10 @@ extern volatile struct mapped_time_value *diskfs_mtime; extern int diskfs_bootflags; extern char *diskfs_bootflagarg; -/* True iff we should do every operation synchronously. */ +/* True iff we should do every operation synchronously. It + is the format-specific code's responsibility to keep allocation + information permanently in sync if this is set; the rest will + be done by format independent code. */ extern int diskfs_synchronous; extern spin_lock_t diskfs_node_refcnt_lock; @@ -627,142 +621,80 @@ diskfs_nrele_light (struct node *np) spin_unlock (&diskfs_node_refcnt_lock); } -/* Return nonzero iff the user identified by ID has uid UID. */ +/* Return nonzero iff the user identified by CRED has uid UID. */ extern inline int -diskfs_idhasuid (uid_t uid, struct userid *id) +diskfs_isuid (uid_t uid, struct protid *cred) { int i; - - for (i = 0; i < id->nuids; i++) - if (id->uids[i] == uid) + for (i = 0; i < cred->nuids; i++) + if (cred->uids[i] == uid) return 1; return 0; } -/* Return nonzero iff the user identified by ID has gid GRP. */ +/* Return nonzero iff the user identified by CRED has group GRP. */ extern inline int -diskfs_idhasgid (uid_t grp, struct userid *id) +diskfs_groupmember (uid_t grp, struct protid *cred) { int i; - - for (i = 0; i < id->ngids; i++) - if (id->gids[i] == grp) + for (i = 0; i < cred->ngids; i++) + if (cred->gids[i] == grp) return 1; return 0; } -/* Check to see if the user identified by ID is permitted to do +/* Check to see if the user identified by CRED is permitted to do owner-only operations on node NP; if so, return 0; if not, return EPERM. */ extern inline error_t -_diskfs_idisowner (struct node *np, struct userid *id) +diskfs_isowner (struct node *np, struct protid *cred) { /* Permitted if the user is the owner, superuser, or if the user is in the group of the file and has the group ID as their user ID. (This last is colloquially known as `group leader'.) */ - if (diskfs_idhasuid (np->dn_stat.st_uid, id) || diskfs_idhasuid (0, id) - || (diskfs_idhasgid (np->dn_stat.st_gid, id) - && diskfs_idhasuid (np->dn_stat.st_gid, id))) + if (diskfs_isuid (np->dn_stat.st_uid, cred) || diskfs_isuid (0, cred) + || (diskfs_groupmember (np->dn_stat.st_gid, cred) + && diskfs_isuid (np->dn_stat.st_gid, cred))) return 0; else return EPERM; } -/* Check to see is the user identified by ID is permitted to do +/* Check to see is the user identified by CRED is permitted to do operation OP on node NP. Op is one of S_IREAD, S_IWRITE, or S_IEXEC. Return 0 if the operation is permitted and EACCES if not. */ extern inline error_t -_diskfs_idaccess (struct node *np, int op, struct userid *id) +diskfs_access (struct node *np, int op, struct protid *cred) { int gotit; - - if (diskfs_idhasuid (0, id)) + if (diskfs_isuid (0, cred)) gotit = 1; - else if (id->nuids == 0 && (np->dn_stat.st_mode & S_IUSEUNK)) + else if (cred->nuids == 0 && (np->dn_stat.st_mode & S_IUSEUNK)) gotit = np->dn_stat.st_mode & (op << S_IUNKSHIFT); - else if (!_diskfs_idisowner (np, id)) + else if (!diskfs_isowner (np, cred)) gotit = np->dn_stat.st_mode & op; - else if (diskfs_idhasgid (np->dn_stat.st_gid, id)) + else if (diskfs_groupmember (np->dn_stat.st_gid, cred)) gotit = np->dn_stat.st_mode & (op >> 3); else gotit = np->dn_stat.st_mode & (op >> 6); - - /* I learned this kind of thing from APL. Cool, huh? */ - return (!gotit) * EACCES; + return gotit ? 0 : EACCES; } -/* Check to see if the user identified by ID is allowed to modify +/* Check to see if the user identified by CRED is allowed to modify directory DP with respect to existing file NP. This is the same as diskfs_access (dp, S_IWRITE, cred), except when the directory has the sticky bit set. (If there is no existing file NP, then 0 can be passed.) */ extern inline error_t -_diskfs_idcheckdirmod (struct node *dp, struct node *np, - struct userid *id) +diskfs_checkdirmod (struct node *dp, struct node *np, + struct protid *cred) { /* The user must be able to write the directory, but if the directory is sticky, then the user must also be either the owner of the directory or the file. */ - return (_diskfs_idaccess (dp, S_IWRITE, id) - && (!(dp->dn_stat.st_mode & S_ISVTX) || !np - || diskfs_idhasuid (0, id) || _diskfs_idisowner (dp, id) - || _diskfs_idisowner (np, id))); -} - -/* Return if the calling user CRED should be permitted to do an owner - only operation on NP. If so, return 0; if not, return EPERM. */ -extern inline error_t -diskfs_isowner (struct node *np, struct protid *cred) -{ - struct userid *id; - error_t err; - - assert (cred->id); - for (id = cred->id; id; id = id->next) - { - err = _diskfs_idisowner (np, id); - if (err) - return err; - } - return 0; -} - -/* Check to see if the calling user identified by CRED is permitted to - do operation OP on node NP. OP is one of S_IREAD, S_IWRITE, or S_IEXEC. - Return 0 if the operation is permitted and EACCES if not. */ -extern inline error_t -diskfs_access (struct node *np, int op, struct protid *cred) -{ - struct userid *id; - error_t err; - - assert (cred->id); - for (id = cred->id; id; id = id->next) - { - err = _diskfs_idaccess (np, op, id); - if (err) - return err; - } - return 0; -} - -/* Check to see if the calling user identified by CRED is allowed to - modify directory DY with respect to existing file NP. Return zero - if permitted and an appropriate error if not. */ -extern inline error_t -diskfs_checkdirmod (struct node *dp, struct node *np, struct protid *cred) -{ - struct userid *id; - error_t err; - - assert (cred->id); - for (id = cred->id; id; id = id->next) - { - err = _diskfs_idcheckdirmod (dp, np, id); - if (err) - return err; - } - return 0; + return (diskfs_access (dp, S_IWRITE, cred) + && (!(dp->dn_stat.st_mode & S_ISVTX) || !np || diskfs_isuid (0,cred) + || diskfs_isowner (dp, cred) || diskfs_isowner (np, cred))); } /* Reading and writing of files. this is called by other filesystem -- cgit v1.2.3