Thread: [Libsysio-commit] HEAD: libsysio/src access.c
Brought to you by:
lward
From: Lee W. <lw...@us...> - 2004-07-31 14:28:59
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30301 Modified Files: access.c Log Message: From Cray SPR 729654: access(path, -1) sets errno 13 instead of 22. We weren't checking to see if the passed mode was restricted only to the supported mask combinations. Fixed now. Fixed another as well. We didn't support F_OK. Do now. Index: access.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/access.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -w -b -B -p -r1.8 -r1.9 --- access.c 27 Jul 2004 15:00:43 -0000 1.8 +++ access.c 31 Jul 2004 14:28:51 -0000 1.9 @@ -64,6 +64,12 @@ SYSIO_INTERFACE_NAME(access)(const char SYSIO_INTERFACE_ENTER; err = 0; + /* + * Check amode. + */ + if ((amode & (R_OK|W_OK|X_OK)) != amode) + SYSIO_INTERFACE_RETURN(-1, -EINVAL); + n = getgroups(0, NULL); list = NULL; if (n) { @@ -82,6 +88,9 @@ SYSIO_INTERFACE_NAME(access)(const char err = -errno; goto out; } + if (!amode) + SYSIO_INTERFACE_RETURN(0, 0); + mask = 0; if (amode & R_OK) |
From: Lee W. <lw...@us...> - 2007-03-23 19:05:55
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv18240/src Modified Files: access.c Log Message: Bug in permission checking. It would allow the desired access if caller was owner, in group, or other and proper bit was set. Now, more in line with what is supposed to happen, it checks owner and applies mask. If the test fails, it returns failure. Then, it proceeds to groups checks, and fails there if caller is in one of the groups. Then, it proceeds to the "other" check. Index: access.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/access.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -w -b -B -p -r1.13 -r1.14 --- access.c 1 Jun 2006 21:28:57 -0000 1.13 +++ access.c 23 Mar 2007 19:05:50 -0000 1.14 @@ -74,6 +74,7 @@ _sysio_check_permission(struct pnode *pn struct intnl_stat *stat; gid_t *gids; int ngids; + int group_matched; /* * Check amode. @@ -95,38 +96,43 @@ _sysio_check_permission(struct pnode *pn ino = pno->p_base->pb_ino; assert(ino); - err = 0; /* assume success */ - + err = -EACCES; /* assume error */ + stat = &ino->i_stbuf; + do { /* * Owner? */ - stat = &ino->i_stbuf; - if (stat->st_uid == crp->creds_uid && - (stat->st_mode & mask) == mask) - goto out; + if (stat->st_uid == crp->creds_uid) { + if ((stat->st_mode & mask) == mask) + err = 0; + break; + } /* * Group? */ mask >>= 3; + group_matched = 0; gids = crp->creds_gids; ngids = crp->creds_ngids; while (ngids) { ngids--; - if (stat->st_gid == *gids++ && - (stat->st_mode & mask) == mask) - goto out; + if (stat->st_gid == *gids++) { + group_matched = 1; + if ((stat->st_mode & mask) == mask) + err = 0; } + } + if (group_matched) + break; /* * Other? */ mask >>= 3; if ((stat->st_mode & mask) == mask) - goto out; - - err = -EACCES; /* fail */ -out: + err = 0; + } while (0); if (err) return err; |
From: Lee W. <lw...@us...> - 2007-04-30 16:56:31
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv3499 Modified Files: access.c Log Message: Got rid of the warning about _sysio_getcreds not being used. We'll need the function later but I'm tired of it right now. Index: access.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/access.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -w -b -B -p -r1.15 -r1.16 --- access.c 30 Apr 2007 16:52:20 -0000 1.15 +++ access.c 30 Apr 2007 16:56:25 -0000 1.16 @@ -210,12 +210,14 @@ _sysio_ldcreds(uid_t uid, gid_t gid, str return 0; } +#if 0 static int _sysio_getcreds(struct creds *crp) { return _sysio_ldcreds(getuid(), getgid(), crp); } +#endif /* * Determine if a given access is permitted to a given file. |
From: Ruth K. <rk...@us...> - 2008-04-15 19:29:30
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9503 Modified Files: access.c Log Message: adjustment to _sysio_ldgroups return value Index: access.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/access.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -w -b -B -p -r1.17 -r1.18 --- access.c 2 Jul 2007 18:58:15 -0000 1.17 +++ access.c 15 Apr 2008 19:29:06 -0000 1.18 @@ -199,7 +199,11 @@ _sysio_ldgroups(gid_t gid0, gid_t **gids } break; } - return i; + /* + * increment count to include gidsp[0], we always + * have at least that group. + */ + return i + 1; } /* |
From: Lee W. <lw...@us...> - 2009-05-05 16:30:46
|
Update of /cvsroot/libsysio/libsysio/src In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv29952/src Modified Files: access.c Log Message: Modified to allow the package user to specify alternate routines for the acquisition of credentials and implementation of permission check policy. In order to arrange the acquisition of alternate credentials, the pointers to _sysio_get_credentials and _sysio_put_credentials should be overwritten. Your get_credentials routine should set the passed pointer to a credentials structure with the uid and gids set with the real values, if the formal called 'effective', is zero or the effective values if non-zero. Your put_credentials routine is called when the core no longer requires your credentials. If you do not need a release routine, you may set _sysio_put_credentials to NULL. In order to arrange the use of an alternate permission check the pointer to _sysio_check_permission should be overwritten. If any of these pointers are overwritten by the user, it must be done prior to calling _sysio_init and may not be reset thereafter. Index: access.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/access.c,v retrieving revision 1.19 retrieving revision 1.20 diff -u -w -b -B -p -r1.19 -r1.20 --- access.c 17 Jun 2008 17:18:57 -0000 1.19 +++ access.c 5 May 2009 16:30:18 -0000 1.20 @@ -41,6 +41,7 @@ * le...@sa... */ +#include <stddef.h> /* ptrdiff_t */ #include <stdlib.h> #include <errno.h> #include <assert.h> @@ -56,18 +57,32 @@ #include "inode.h" #include "sysio-symbols.h" -/* - * Use a persistent buffer for gids. No, not a cache. We just want to - * avoid calling malloc over, and over, and... - */ -static gid_t *gids = NULL; -static int gidslen = 0; +static int get_credentials(struct creds **crp, int effective); +static void put_credentials(struct creds *cr); +static int check_permission(struct pnode *pno, struct creds *cr, int amode); + +/* + * If the application will be managing credentials externally, these + * are the interface. Before calling this librariy's initialization + * routines, reset them to your own. + */ +int (*_sysio_get_credentials)(struct creds **, int) = + get_credentials; +void (*_sysio_put_credentials)(struct creds *) = + put_credentials; +int (*_sysio_check_permission)(struct pnode *, struct creds *, int) = + check_permission; + +static struct user_credentials { + struct creds creds; + unsigned refs; +} *_current_ucreds = NULL; /* * Check given access type on given inode. */ -int -_sysio_check_permission(struct pnode *pno, struct creds *crp, int amode) +static int +check_permission(struct pnode *pno, struct creds *crp, int amode) { mode_t mask; struct inode *ino; @@ -160,27 +175,18 @@ _sysio_check_permission(struct pnode *pn } /* - * Cache groups. + * (Re)fill credentials */ static int -_sysio_ldgroups(gid_t gid0, gid_t **gidsp, int *gidslenp) +ldgroups(gid_t gid0, gid_t **gidsp, int *gidslenp) { int n, i; void *p; n = *gidslenp; - if (n < 8) { - *gidsp = NULL; + if (n < 8) n = 8; - } for (;;) { - /* - * This is far more expensive than I would like. Each time - * called it has to go to some length to acquire the - * current uid and groups membership. We can't just cache - * the result, either. The caller could have altered something - * asynchronously. Wish we had easy access to this info. - */ if (n > *gidslenp) { p = realloc(*gidsp, (size_t )n * sizeof(gid_t)); if (!p) @@ -211,45 +217,133 @@ _sysio_ldgroups(gid_t gid0, gid_t **gids * Get current credentials. */ static int -_sysio_ldcreds(uid_t uid, gid_t gid, struct creds *crp) +ldcreds(uid_t uid, gid_t gid, struct creds *cr) { int n; - n = _sysio_ldgroups(gid, &gids, &gidslen); + n = ldgroups(gid, &cr->creds_gids, &cr->creds_ngids); if (n < 0) return n; - crp->creds_uid = uid; - crp->creds_gids = gids; - crp->creds_ngids = n; + cr->creds_ngids = n; + cr->creds_uid = uid; return 0; } -#if 0 static int -_sysio_getcreds(struct creds *crp) +get_credentials(struct creds **crp, int effective) { + int err; + uid_t uid; + gid_t gid; - return _sysio_ldcreds(getuid(), getgid(), crp); + /* + * This is not a particularly efficient implementation. We + * don't expect it to ever be used in a thread-safe environment + * though, so expect no problems because of it. + */ + err = 0; + mutex_lock(&_sysio_biglock); + do { + if (!_current_ucreds || _current_ucreds->refs) { + _current_ucreds = + malloc(sizeof(struct user_credentials)); + if (!_current_ucreds) { + err = -ENOMEM; + break; + } + _current_ucreds->creds.creds_uid = -1; + _current_ucreds->creds.creds_gids = NULL; + _current_ucreds->creds.creds_ngids = 0; + _current_ucreds->refs = 0; + } + if (effective) { + uid = geteuid(); + gid = getegid(); + } else { + uid = getuid(); + gid = getgid(); + } + err = + ldcreds(uid, + gid, + &_current_ucreds->creds); + if (err) + break; + _current_ucreds->refs++; + } while (0); + mutex_unlock(&_sysio_biglock); + if (err) + return err; + *crp = &_current_ucreds->creds; + return 0; +} + +static void +release_ucreds(struct user_credentials *ucr) +{ + + free(ucr->creds.creds_gids); + free(ucr); +} + +static void +put_credentials(struct creds *cr) +{ + struct user_credentials *ucr; + + mutex_lock(&_sysio_biglock); + do { + ucr = CONTAINER(user_credentials, creds, cr); + assert(ucr->refs); + if (--ucr->refs || ucr == _current_ucreds) { + ucr = NULL; + break; + } + } while (0); + mutex_unlock(&_sysio_biglock); + if (ucr) + release_ucreds(ucr); } -#endif /* - * Determine if a given access is permitted to a given file. + * Common permission check. */ int -_sysio_permitted(struct pnode *pno, int amode) +_sysio_p_generic_perms_check(struct pnode *pno, int amode, int effective) { - struct creds cr; int err; + struct creds *cr; - err = _sysio_ldcreds(geteuid(), getegid(), &cr); - if (err < 0) - return err; - err = _sysio_check_permission(pno, &cr, amode); + do { + if ((err = (*_sysio_get_credentials)(&cr, effective))) { + cr = NULL; + break; + } + err = (*_sysio_check_permission)(pno, cr, amode); + } while (0); + if (cr) + (*_sysio_put_credentials)(cr); return err; } +static int +permitted(struct pnode *pno, int amode, int effective) +{ + + return PNOP_PERMS_CHECK(pno, amode, effective); +} + +/* + * Determine if a given access is permitted to a given file. + */ +int +_sysio_permitted(struct pnode *pno, int amode) +{ + + return permitted(pno, amode, 0); +} + #ifdef ZERO_SUM_MEMORY /* * Clean up persistent resource on shutdown. @@ -258,10 +352,10 @@ void _sysio_access_shutdown() { - if (gids) - free(gids); - gids = NULL; - gidslen = 0; + if (_current_ucreds) { + release_ucreds(_current_ucreds); + _current_ucreds = NULL; + } } #endif @@ -271,22 +365,21 @@ SYSIO_INTERFACE_NAME(access)(const char struct intent intent; int err; struct pnode *pno; - struct creds cr; SYSIO_INTERFACE_DISPLAY_BLOCK; SYSIO_INTERFACE_ENTER(access, "%s%d", path, amode); + do { INTENT_INIT(&intent, INT_GETATTR, NULL, NULL); err = _sysio_namei(_sysio_cwd, path, 0, &intent, &pno); - if (err) - SYSIO_INTERFACE_RETURN(-1, err, access, "%d", 0); - err = _sysio_ldcreds(geteuid(), getegid(), &cr); - if (err < 0) - goto out; - err = - _sysio_check_permission(pno, &cr, amode); -out: + if (err) { + pno = NULL; + break; + } + err = permitted(pno, amode, 1); + } while (0); + if (pno) P_PUT(pno); SYSIO_INTERFACE_RETURN(err ? -1 : 0, err, access, "%d", 0); } |
From: Lee W. <lw...@us...> - 2009-08-03 19:48:29
|
Update of /cvsroot/libsysio/libsysio/src In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv29518/src Modified Files: access.c Log Message: Two changes: 1) Fixed bug in access; It was using effective IDs instead of real. 2) Created new _sysio_epermitted routine that allows caller to specify which IDs to use. The old routine _sysio_permitted still uses effective. Index: access.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/access.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -w -b -B -p -r1.20 -r1.21 --- access.c 5 May 2009 16:30:18 -0000 1.20 +++ access.c 3 Aug 2009 19:48:19 -0000 1.21 @@ -82,7 +82,7 @@ static struct user_credentials { * Check given access type on given inode. */ static int -check_permission(struct pnode *pno, struct creds *crp, int amode) +check_permission(struct pnode *pno, struct creds *cr, int amode) { mode_t mask; struct inode *ino; @@ -111,8 +111,9 @@ check_permission(struct pnode *pno, stru if (amode & X_OK) mask |= S_IXUSR; + assert(P_ISLOCKED(pno) && PB_ISLOCKED(pno->p_base)); ino = pno->p_base->pb_ino; - assert(ino); + assert(ino && I_ISLOCKED(ino)); err = -EACCES; /* assume error */ stat = &ino->i_stbuf; @@ -121,7 +122,7 @@ check_permission(struct pnode *pno, stru /* * Root? */ - if (_sysio_is_root(crp)) { + if (_sysio_is_root(cr)) { err = 0; break; } @@ -130,7 +131,7 @@ check_permission(struct pnode *pno, stru /* * Owner? */ - if (stat->st_uid == crp->creds_uid) { + if (stat->st_uid == cr->creds_uid) { if ((stat->st_mode & mask) == mask) err = 0; break; @@ -141,8 +142,8 @@ check_permission(struct pnode *pno, stru */ mask >>= 3; group_matched = 0; - gids = crp->creds_gids; - ngids = crp->creds_ngids; + gids = cr->creds_gids; + ngids = cr->creds_ngids; while (ngids) { ngids--; if (stat->st_gid == *gids++) { @@ -320,6 +321,9 @@ _sysio_p_generic_perms_check(struct pnod cr = NULL; break; } + assert(P_ISLOCKED(pno) && + PB_ISLOCKED(pno->p_base) && + pno->p_base->pb_ino && I_ISLOCKED(pno->p_base->pb_ino)); err = (*_sysio_check_permission)(pno, cr, amode); } while (0); if (cr) @@ -327,8 +331,8 @@ _sysio_p_generic_perms_check(struct pnod return err; } -static int -permitted(struct pnode *pno, int amode, int effective) +int +_sysio_epermitted(struct pnode *pno, int amode, int effective) { return PNOP_PERMS_CHECK(pno, amode, effective); @@ -341,7 +345,7 @@ int _sysio_permitted(struct pnode *pno, int amode) { - return permitted(pno, amode, 0); + return _sysio_epermitted(pno, amode, 1); } #ifdef ZERO_SUM_MEMORY @@ -377,7 +381,10 @@ SYSIO_INTERFACE_NAME(access)(const char pno = NULL; break; } - err = permitted(pno, amode, 1); + /* + * Check, using real IDs. + */ + err = _sysio_epermitted(pno, amode, 0); } while (0); if (pno) P_PUT(pno); |