From: <li...@us...> - 2008-09-18 01:02:58
|
Revision: 8 http://npfs.svn.sourceforge.net/npfs/?rev=8&view=rev Author: lionkov Date: 2008-09-18 01:03:08 +0000 (Thu, 18 Sep 2008) Log Message: ----------- Multiple races in the unix user function. Modified Paths: -------------- npfs/trunk/fs/ufs.c npfs/trunk/include/npfs.h npfs/trunk/libnpfs/Makefile npfs/trunk/libnpfs/conn.c npfs/trunk/libnpfs/error.c npfs/trunk/libnpfs/fcall.c npfs/trunk/libnpfs/fidpool.c npfs/trunk/libnpfs/mount-Linux.c npfs/trunk/libnpfs/mount-none.c npfs/trunk/libnpfs/npfsimpl.h npfs/trunk/libnpfs/user.c npfs/trunk/libnpfs/uxusers.c Modified: npfs/trunk/fs/ufs.c =================================================================== --- npfs/trunk/fs/ufs.c 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/fs/ufs.c 2008-09-18 01:03:08 UTC (rev 8) @@ -62,6 +62,12 @@ int debuglevel; int sameuser; +pthread_mutex_t culock = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cucond = PTHREAD_COND_INITIALIZER; +Npuser *cuser; +int curef; +int maxref; + char *Estatfailed = "stat failed"; char *Ebadfid = "fid unknown or out of range"; char *Enoextension = "empty extension while creating special file"; @@ -441,10 +447,15 @@ } static inline void -npfs_change_user(Npuser *user) +npfs_set_user(Npuser *user) { - if (!sameuser) - np_change_user(user); + if (sameuser) + return; + + if (geteuid() == user->uid) + return; + + np_change_user(user); } static Npfcall* @@ -459,12 +470,12 @@ user = NULL; ret = NULL; + npfs_set_user(nfid->user); if (nafid != NULL) { np_werror(Enoauth, EIO); goto done; } - npfs_change_user(nfid->user); fid = npfs_fidalloc(); fid->omode = -1; if (aname->len==0 || *aname->str!='/') @@ -510,7 +521,7 @@ char *path; f = fid->aux; - npfs_change_user(fid->user); + npfs_set_user(fid->user); n = fidstat(f); if (n < 0) create_rerror(n); @@ -543,7 +554,7 @@ Npqid qid; f = fid->aux; - npfs_change_user(fid->user); + npfs_set_user(fid->user); if ((err = fidstat(f)) < 0) create_rerror(err); @@ -814,7 +825,7 @@ f = fid->aux; ret = np_alloc_rread(count); - npfs_change_user(fid->user); + npfs_set_user(fid->user); if (f->dir) n = npfs_read_dir(fid, ret->data, offset, count, fid->conn->dotu); else { @@ -845,7 +856,7 @@ Fid *f; f = fid->aux; - npfs_change_user(fid->user); + npfs_set_user(fid->user); if (use_aio) { n = npfs_aio_write(fid, data, offset, count, req); @@ -881,7 +892,7 @@ ret = NULL; f = fid->aux; - npfs_change_user(fid->user); + npfs_set_user(fid->user); if (remove(f->path) < 0) { create_rerror(errno); goto out; @@ -904,7 +915,7 @@ Npwstat wstat; f = fid->aux; - npfs_change_user(fid->user); + npfs_set_user(fid->user); err = fidstat(f); if (err < 0) create_rerror(err); @@ -934,7 +945,7 @@ ret = NULL; f = fid->aux; up = fid->conn->srv->upool; - npfs_change_user(fid->user); + npfs_set_user(fid->user); err = fidstat(f); if (err < 0) { create_rerror(err); @@ -1046,7 +1057,7 @@ rc = NULL; if (count<0 && !flush) { - if (areq->req->tcall->id == Tread) + if (areq->req->tcall->type == Tread) free(areq->rread); if (strerror_r(count, buf, sizeof(buf))) @@ -1054,7 +1065,7 @@ rc = np_create_rerror(buf, count, areq->req->conn->dotu); } else { - if (areq->req->tcall->id == Tread) { + if (areq->req->tcall->type == Tread) { rc = areq->rread; np_set_rread_count(rc, count); } else { Modified: npfs/trunk/include/npfs.h =================================================================== --- npfs/trunk/include/npfs.h 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/include/npfs.h 2008-09-18 01:03:08 UTC (rev 8) @@ -34,6 +34,7 @@ typedef struct Npwstat Npwstat; typedef struct Npfcall Npfcall; typedef struct Npfid Npfid; +typedef struct Npfidpool Npfidpool; typedef struct Npbuf Npbuf; typedef struct Nptrans Nptrans; typedef struct Npconn Npconn; @@ -231,6 +232,7 @@ }; struct Npfid { + pthread_mutex_t lock; Npconn* conn; u32 fid; int refcount; @@ -241,6 +243,7 @@ void* aux; Npfid* next; /* list of fids within a bucket */ + Npfid* prev; }; struct Npbuf { @@ -258,8 +261,15 @@ void (*destroy)(void *); }; +struct Npfidpool { + pthread_mutex_t lock; + int size; + Npfid** htable; +}; + struct Npconn { pthread_mutex_t lock; + pthread_mutex_t wlock; int refcount; int resetting; @@ -271,7 +281,7 @@ int shutdown; Npsrv* srv; Nptrans* trans; - Npfid** fidpool; + Npfidpool* fidpool; int freercnum; Npfcall* freerclist; void* aux; @@ -491,11 +501,11 @@ void np_conn_respond(Npreq *req); void np_respond(Npreq *, Npfcall *); -Npfid **np_fidpool_create(void); -void np_fidpool_destroy(Npfid **); +Npfidpool *np_fidpool_create(void); +void np_fidpool_destroy(Npfidpool *); Npfid *np_fid_find(Npconn *, u32); Npfid *np_fid_create(Npconn *, u32, void *); -int np_fid_destroy(Npfid *); +void np_fid_destroy(Npfid *); void np_fid_incref(Npfid *); void np_fid_decref(Npfid *); Modified: npfs/trunk/libnpfs/Makefile =================================================================== --- npfs/trunk/libnpfs/Makefile 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/Makefile 2008-09-18 01:03:08 UTC (rev 8) @@ -16,7 +16,6 @@ file.o\ fmt.o\ np.o\ - pipesrv.o\ pvusers.o\ socksrv.o\ srv.o\ @@ -24,6 +23,10 @@ user.o\ uxusers.o\ +ifeq ($(SYSNAME), Linux) + LIBFILES += pipesrv.o +endif + libnpfs.a: $(LIBFILES) ar rc libnpfs.a $(LIBFILES) ranlib libnpfs.a Modified: npfs/trunk/libnpfs/conn.c =================================================================== --- npfs/trunk/libnpfs/conn.c 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/conn.c 2008-09-18 01:03:08 UTC (rev 8) @@ -32,7 +32,7 @@ extern int printfcall(FILE *f, Npfcall *fc, int dotu); static Npfcall *np_conn_new_incall(Npconn *conn); -static void np_conn_free_incall(Npconn *, Npfcall *); +static void np_conn_free_incall(Npconn *, Npfcall *, int); static void *np_conn_read_proc(void *); Npconn* @@ -46,6 +46,7 @@ //fprintf(stderr, "np_conn_create %p\n", conn); pthread_mutex_init(&conn->lock, NULL); + pthread_mutex_init(&conn->wlock, NULL); pthread_cond_init(&conn->resetcond, NULL); pthread_cond_init(&conn->resetdonecond, NULL); conn->refcount = 0; @@ -169,7 +170,7 @@ pthread_mutex_lock(&conn->lock); trans = conn->trans; conn->trans = NULL; - np_conn_free_incall(conn, fc); + np_conn_free_incall(conn, fc, 0); pthread_mutex_unlock(&conn->lock); np_srv_remove_conn(conn->srv, conn); @@ -315,7 +316,7 @@ void np_conn_respond(Npreq *req) { - int n; + int n, send; Npconn *conn; Nptrans *trans; Npfcall *rc; @@ -323,25 +324,36 @@ trans = NULL; conn = req->conn; rc = req->rcall; + if (!rc) + goto done; + pthread_mutex_lock(&conn->lock); - if (conn->trans && !conn->resetting && rc) { + send = conn->trans && !conn->resetting; + pthread_mutex_unlock(&conn->lock); + + if (send) { + pthread_mutex_lock(&conn->wlock); if (conn->srv->debuglevel) { fprintf(stderr, ">>> (%p) ", conn); np_printfcall(stderr, rc, conn->dotu); fprintf(stderr, "\n"); } n = np_trans_write(conn->trans, rc->pkt, rc->size); + pthread_mutex_unlock(&conn->wlock); + if (n <= 0) { + pthread_mutex_lock(&conn->lock); trans = conn->trans; conn->trans = NULL; + pthread_mutex_unlock(&conn->lock); } } - np_conn_free_incall(req->conn, req->tcall); +done: + np_conn_free_incall(req->conn, req->tcall, 1); free(req->rcall); req->tcall = NULL; req->rcall = NULL; - pthread_mutex_unlock(&conn->lock); if (conn->resetting) { pthread_mutex_lock(&conn->srv->lock); @@ -384,19 +396,23 @@ } static void -np_conn_free_incall(Npconn* conn, Npfcall *rc) +np_conn_free_incall(Npconn* conn, Npfcall *rc, int lock) { if (!rc) return; -// pthread_mutex_lock(&conn->lock); + if (lock) + pthread_mutex_lock(&conn->lock); + if (conn->freercnum < 64) { rc->next = conn->freerclist; conn->freerclist = rc; rc = NULL; } -// pthread_mutex_unlock(&conn->lock); + if (lock) + pthread_mutex_unlock(&conn->lock); + if (rc) free(rc); } Modified: npfs/trunk/libnpfs/error.c =================================================================== --- npfs/trunk/libnpfs/error.c 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/error.c 2008-09-18 01:03:08 UTC (rev 8) @@ -92,6 +92,9 @@ va_list ap; Nperror *err; + if (ecode == 5) + printf("EIO...\n"); + pthread_once(&error_once, np_init_error_key); err = pthread_getspecific(error_key); if (!err) { @@ -152,10 +155,10 @@ void np_suerror(char *s, int ecode) { - char err[256], *str; + char err[256]; char buf[512]; - str = strerror_r(ecode, err, sizeof(err)); - snprintf(buf, sizeof(buf), "%s: %s", s, str); + strerror_r(ecode, err, sizeof(err)); + snprintf(buf, sizeof(buf), "%s: %s", s, err); np_werror(buf, ecode); } Modified: npfs/trunk/libnpfs/fcall.c =================================================================== --- npfs/trunk/libnpfs/fcall.c 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/fcall.c 2008-09-18 01:03:08 UTC (rev 8) @@ -307,6 +307,7 @@ } if (tc->fid != tc->newfid) { +// printf("newfid conn %p fid %d\n", conn, tc->newfid); newfid = np_fid_find(conn, tc->newfid); if (newfid) { np_werror(Einuse, EIO); Modified: npfs/trunk/libnpfs/fidpool.c =================================================================== --- npfs/trunk/libnpfs/fidpool.c 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/fidpool.c 2008-09-18 01:03:08 UTC (rev 8) @@ -28,27 +28,36 @@ #include "npfs.h" #include "npfsimpl.h" -Npfid** +Npfidpool * np_fidpool_create(void) { - Npfid **ret; + Npfidpool *fp; - return calloc(FID_HTABLE_SIZE, sizeof(*ret)); + fp = np_malloc(sizeof(*fp) + FID_HTABLE_SIZE * sizeof(Npfid *)); + if (!fp) + return NULL; + + pthread_mutex_init(&fp->lock, NULL); + fp->size = FID_HTABLE_SIZE; + fp->htable = (Npfid **)((char *) fp + sizeof(*fp)); + memset(fp->htable, 0, fp->size * sizeof(Npfid *)); + + return fp; } void -np_fidpool_destroy(Npfid **pool) +np_fidpool_destroy(Npfidpool *pool) { int i; Npfid *f, *ff; Npsrv *srv; - for(i = 0; i < FID_HTABLE_SIZE; i++) { - f = pool[i]; + for(i = 0; i < pool->size; i++) { + f = pool->htable[i]; while (f != NULL) { ff = f->next; srv = f->conn->srv; - if (f->type&Qtauth && srv->auth->clunk) + if (f->type&Qtauth && srv->auth && srv->auth->clunk) (*srv->auth->clunk)(f); else if (!(f->type&Qtauth) && srv->fiddestroy) (*srv->fiddestroy)(f); @@ -60,103 +69,130 @@ free(pool); } -Npfid* -np_fid_find(Npconn *conn, u32 fid) +Npfid * +np_fid_lookup(Npfidpool *fp, u32 fid, int hash) { - int hash; - Npfid **htable, *f, **prevp; + Npfid **htable, *f; - hash = fid % FID_HTABLE_SIZE; - htable = conn->fidpool; - pthread_mutex_lock(&conn->lock); - prevp = &htable[hash]; - f = *prevp; - while (f != NULL) { + htable = fp->htable; + for(f = htable[hash]; f != NULL; f = f->next) { if (f->fid == fid) { - *prevp = f->next; - f->next = htable[hash]; - htable[hash] = f; + if (f != htable[hash]) { + if (f->next) + f->next->prev = f->prev; + + f->prev->next = f->next; + f->prev = NULL; + f->next = htable[hash]; + htable[hash]->prev = f; + htable[hash] = f; + } + break; } + } - prevp = &f->next; - f = *prevp; - } - pthread_mutex_unlock(&conn->lock); return f; } Npfid* +np_fid_find(Npconn *conn, u32 fid) +{ + int hash; + Npfidpool *fp; + Npfid *ret; + + fp = conn->fidpool; + pthread_mutex_lock(&fp->lock); + hash = fid % fp->size; + ret = np_fid_lookup(fp, fid, hash); + pthread_mutex_unlock(&fp->lock); + + return ret; +} + +Npfid* np_fid_create(Npconn *conn, u32 fid, void *aux) { int hash; + Npfidpool *fp; Npfid **htable, *f; + fp = conn->fidpool; + pthread_mutex_lock(&fp->lock); + htable = fp->htable; hash = fid % FID_HTABLE_SIZE; - htable = conn->fidpool; - f = np_fid_find(conn, fid); - if (f) - return NULL; + f = np_fid_lookup(fp, fid, hash); + if (!f) { + f = np_malloc(sizeof(*f)); + if (!f) { + pthread_mutex_unlock(&fp->lock); + return NULL; + } - f = malloc(sizeof(*f)); - if (!f) - return NULL; + pthread_mutex_init(&f->lock, NULL); + f->fid = fid; + f->conn = conn; + f->refcount = 0; + f->omode = ~0; + f->type = 0; + f->diroffset = 0; + f->user = NULL; + f->aux = aux; - f->fid = fid; - f->conn = conn; - f->refcount = 0; - f->omode = ~0; - f->type = 0; - f->diroffset = 0; - f->user = NULL; - f->aux = aux; + f->next = htable[hash]; + f->prev = NULL; + if (htable[hash]) + htable[hash]->prev = f; - pthread_mutex_lock(&conn->lock); - f->next = htable[hash]; - htable[hash] = f; - pthread_mutex_unlock(&conn->lock); + htable[hash] = f; + } + pthread_mutex_unlock(&fp->lock); + return f; } -int +void np_fid_destroy(Npfid *fid) { int hash; Npconn *conn; Npsrv *srv; - Npfid **htable, *f, **prevp; + Npfidpool *fp; + Npfid **htable; conn = fid->conn; - hash = fid->fid % FID_HTABLE_SIZE; - htable = conn->fidpool; - if(!htable) - return 0; + srv = conn->srv; + fp = conn->fidpool; + if (!fp) + return; - pthread_mutex_lock(&conn->lock); - prevp = &htable[hash]; - f = *prevp; - while (f != NULL) { - if (f->fid == fid->fid) { - *prevp = f->next; - srv = f->conn->srv; - if (f->type & Qtauth && srv->auth->clunk) - (*srv->auth->clunk)(f); - else if (!(f->type&Qtauth) && srv->fiddestroy) - (*srv->fiddestroy)(f); +// printf("destroy conn %p fid %d\n", conn, fid->fid); + pthread_mutex_lock(&fp->lock); + hash = fid->fid % fp->size; + htable = fp->htable; + if (fid->prev) + fid->prev->next = fid->next; + else + htable[hash] = fid->next; - if (f->user) - np_user_decref(f->user); + if (fid->next) + fid->next->prev = fid->prev; - free(f); - break; - } + pthread_mutex_unlock(&fp->lock); - prevp = &f->next; - f = *prevp; - } - pthread_mutex_unlock(&conn->lock); - return f != NULL; + if (fid->type & Qtauth && srv->auth && srv->auth->clunk) + (*srv->auth->clunk)(fid); + else if (!(fid->type&Qtauth) && srv->fiddestroy) + (*srv->fiddestroy)(fid); + + if (fid->user) + np_user_decref(fid->user); + + free(fid); + + return; } void @@ -165,17 +201,23 @@ if (!fid) return; + pthread_mutex_lock(&fid->lock); fid->refcount++; + pthread_mutex_unlock(&fid->lock); } void np_fid_decref(Npfid *fid) { + int n; + if (!fid) return; - fid->refcount--; + pthread_mutex_lock(&fid->lock); + n = --fid->refcount; + pthread_mutex_unlock(&fid->lock); - if (!fid->refcount) + if (!n) np_fid_destroy(fid); } Modified: npfs/trunk/libnpfs/mount-Linux.c =================================================================== --- npfs/trunk/libnpfs/mount-Linux.c 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/mount-Linux.c 2008-09-18 01:03:08 UTC (rev 8) @@ -1,6 +1,19 @@ #include <sys/mount.h> +#include <sys/syscall.h> int np_mount(char *mntpt, int mntflags, char *opts) { return mount("none", mntpt, "9p", mntflags, opts); } + +int +sreuid(int a, int b) +{ + return syscall(SYS_setreuid, a, b); +} + +int +sregid(int a, int b) +{ + return syscall(SYS_setregid, a, b); +} Modified: npfs/trunk/libnpfs/mount-none.c =================================================================== --- npfs/trunk/libnpfs/mount-none.c 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/mount-none.c 2008-09-18 01:03:08 UTC (rev 8) @@ -1,3 +1,5 @@ +#include <unistd.h> + int np_mount(char *mntpt, int mntflags, char *opts) { return -1; @@ -2 +4,13 @@ } + +int +sreuid(int a, int b) +{ + return setreuid(a, b); +} + +int +sregid(int a, int b) +{ + return setregid(a, b); +} Modified: npfs/trunk/libnpfs/npfsimpl.h =================================================================== --- npfs/trunk/libnpfs/npfsimpl.h 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/npfsimpl.h 2008-09-18 01:03:08 UTC (rev 8) @@ -52,3 +52,5 @@ void np_req_unref(Npreq*); void np_req_free(Npreq *req); void np_srv_process_fcall(Npconn *conn, Npfcall *tc); +int sreuid(int a, int b); +int sregid(int a, int b); Modified: npfs/trunk/libnpfs/user.c =================================================================== --- npfs/trunk/libnpfs/user.c 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/user.c 2008-09-18 01:03:08 UTC (rev 8) @@ -32,8 +32,6 @@ #include "npfs.h" #include "npfsimpl.h" -static Npuser *currentUser; - void np_user_incref(Npuser *u) { @@ -108,10 +106,7 @@ int i; gid_t *gids; - if (currentUser == u) - return 0; - - if (setreuid(0, 0) < 0) + if (sreuid(0, 0) < 0) goto error; gids = np_malloc(u->ngroups * sizeof(gid_t)); @@ -123,16 +118,13 @@ if (u->ngroups > 0) { setgroups(u->ngroups, gids); - if (setregid(-1, u->dfltgroup->gid) < 0) + if (sregid(-1, u->dfltgroup->gid) < 0) goto error; } - if (setreuid(-1, u->uid) < 0) + if (sreuid(-1, u->uid) < 0) goto error; - np_user_incref(u); - np_user_decref(currentUser); - currentUser = u; return 0; error: @@ -143,5 +135,5 @@ Npuser * np_current_user(void) { - return currentUser; + return NULL; } Modified: npfs/trunk/libnpfs/uxusers.c =================================================================== --- npfs/trunk/libnpfs/uxusers.c 2008-07-17 17:20:51 UTC (rev 7) +++ npfs/trunk/libnpfs/uxusers.c 2008-09-18 01:03:08 UTC (rev 8) @@ -67,6 +67,8 @@ pthread_mutex_t lock; } groupcache = { 0 }; +pthread_mutex_t grentlock = PTHREAD_MUTEX_INITIALIZER; + static void initusercache(void) { @@ -95,7 +97,7 @@ static Npuser * np_unix_uname2user(Npuserpool *up, char *uname) { - int i, n; + int i, n, found; struct passwd pw, *pwp; int bufsize; char *buf; @@ -105,55 +107,63 @@ if (!usercache.init) initusercache(); + found = 0; for(i = 0; i<usercache.hsize; i++) for(u = usercache.htable[i]; u != NULL; u = u->next) - if (strcmp(uname, u->uname) == 0) + if (strcmp(uname, u->uname) == 0) { + found = 1; break; - pthread_mutex_unlock(&usercache.lock); + } - if (u) + if (found) { + pthread_mutex_unlock(&usercache.lock); + pthread_mutex_lock(&u->lock); + found = u->uname != NULL; + pthread_mutex_unlock(&u->lock); + + if (!found) + return NULL; + goto done; + } + u = np_malloc(sizeof(*u) + 256); + pthread_mutex_init(&u->lock, NULL); + u->uname = NULL; + + n = u->uid % usercache.hsize; + u->next = usercache.htable[n]; + usercache.htable[n] = u; + + pthread_mutex_lock(&u->lock); + pthread_mutex_unlock(&usercache.lock); + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); if (bufsize < 256) bufsize = 256; buf = np_malloc(bufsize); - if (!buf) - return NULL; - i = getpwnam_r(uname, &pw, buf, bufsize, &pwp); if (i) { np_uerror(i); free(buf); + pthread_mutex_unlock(&u->lock); return NULL; } - u = np_malloc(sizeof(*u) + strlen(pw.pw_name) + 1); - if (!u) { - free(buf); - return NULL; - } - - pthread_mutex_init(&u->lock, NULL); u->refcount = 1; u->upool = up; u->uid = pw.pw_uid; u->uname = (char *)u + sizeof(*u); - strcpy(u->uname, pw.pw_name); + strncpy(u->uname, pw.pw_name, 256); u->dfltgroup = (*up->gid2group)(up, pw.pw_gid); u->ngroups = 0; u->groups = NULL; np_init_user_groups(u); free(buf); + pthread_mutex_unlock(&u->lock); - pthread_mutex_lock(&usercache.lock); - n = u->uid % usercache.hsize; - u->next = usercache.htable[n]; - usercache.htable[n] = u; - pthread_mutex_unlock(&usercache.lock); - done: np_user_incref(u); return u; @@ -162,7 +172,7 @@ static Npuser * np_unix_uid2user(Npuserpool *up, u32 uid) { - int n, i; + int n, i, found; Npuser *u; struct passwd pw, *pwp; int bufsize; @@ -172,54 +182,62 @@ if (!usercache.init) initusercache(); + found = 0; n = uid % usercache.hsize; for(u = usercache.htable[n]; u != NULL; u = u->next) - if (u->uid == uid) + if (u->uid == uid) { + found = 1; break; - pthread_mutex_unlock(&usercache.lock); + } - if (u) + if (found) { + pthread_mutex_unlock(&usercache.lock); + pthread_mutex_lock(&u->lock); + found = u->uname != NULL; + pthread_mutex_unlock(&u->lock); + + if (!found) + return NULL; + goto done; + } + u = np_malloc(sizeof(*u) + 256); + pthread_mutex_init(&u->lock, NULL); + u->uname = NULL; + + u->next = usercache.htable[n]; + usercache.htable[n] = u; + + pthread_mutex_lock(&u->lock); + pthread_mutex_unlock(&usercache.lock); + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); if (bufsize < 256) bufsize = 256; buf = np_malloc(bufsize); - if (!buf) - return NULL; - i = getpwuid_r(uid, &pw, buf, bufsize, &pwp); if (i) { np_uerror(i); free(buf); + pthread_mutex_unlock(&u->lock); return NULL; } - u = np_malloc(sizeof(*u) + strlen(pw.pw_name) + 1); - if (!u) { - free(buf); - return NULL; - } - - pthread_mutex_init(&u->lock, NULL); u->refcount = 1; u->upool = up; u->uid = uid; u->uname = (char *)u + sizeof(*u); - strcpy(u->uname, pw.pw_name); + strncpy(u->uname, pw.pw_name, 256); u->dfltgroup = up->gid2group(up, pw.pw_gid); u->ngroups = 0; u->groups = NULL; np_init_user_groups(u); free(buf); + pthread_mutex_unlock(&u->lock); - pthread_mutex_lock(&usercache.lock); - u->next = usercache.htable[n]; - usercache.htable[n] = u; - pthread_mutex_unlock(&usercache.lock); - done: np_user_incref(u); return u; @@ -228,7 +246,7 @@ static Npgroup * np_unix_gname2group(Npuserpool *up, char *gname) { - int i, n, bufsize; + int i, bufsize, found; Npgroup *g; struct group grp, *pgrp; char *buf; @@ -237,48 +255,52 @@ if (!groupcache.init) initgroupcache(); + found = 0; for(i = 0; i < groupcache.hsize; i++) for(g = groupcache.htable[i]; g != NULL; g = g->next) - if (strcmp(g->gname, gname) == 0) + if (strcmp(g->gname, gname) == 0) { + found = 1; break; - pthread_mutex_unlock(&groupcache.lock); + } - if (g) + if (found) { + pthread_mutex_unlock(&groupcache.lock); + pthread_mutex_lock(&g->lock); + found = g->gname != NULL; + pthread_mutex_unlock(&g->lock); + + if (!found) + return NULL; + goto done; + } + g = np_malloc(sizeof(*g) + 256); + pthread_mutex_init(&g->lock, NULL); + g->gname = NULL; + pthread_mutex_lock(&g->lock); + pthread_mutex_unlock(&groupcache.lock); + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); if (bufsize < 256) bufsize = 256; buf = np_malloc(bufsize); - if (!buf) - return NULL; - i = getgrnam_r(gname, &grp, buf, bufsize, &pgrp); if (i) { np_uerror(i); free(buf); + pthread_mutex_unlock(&g->lock); return NULL; } - g = np_malloc(sizeof(*g) + strlen(grp.gr_name) + 1); - if (!g) { - free(buf); - return NULL; - } - g->refcount = 1; g->upool = up; g->gid = grp.gr_gid; g->gname = (char *)g + sizeof(*g); - strcpy(g->gname, grp.gr_name); + strncpy(g->gname, grp.gr_name, 256); - pthread_mutex_lock(&groupcache.lock); - n = g->gid % groupcache.hsize; - g->next = groupcache.htable[n]; - groupcache.htable[n] = g; - pthread_mutex_unlock(&groupcache.lock); - + pthread_mutex_unlock(&g->lock); free(buf); done: @@ -289,7 +311,7 @@ static Npgroup * np_unix_gid2group(Npuserpool *up, u32 gid) { - int n, err; + int n, err, found; Npgroup *g; struct group grp, *pgrp; int bufsize; @@ -300,47 +322,50 @@ initgroupcache(); n = gid % groupcache.hsize; + found = 0; for(g = groupcache.htable[n]; g != NULL; g = g->next) - if (g->gid == gid) + if (g->gid == gid) { + found = 1; break; - pthread_mutex_unlock(&groupcache.lock); + } + if (found) { + pthread_mutex_unlock(&groupcache.lock); + pthread_mutex_lock(&g->lock); + found = g->gname != NULL; + pthread_mutex_unlock(&g->lock); - if (g) + if (!found) + return NULL; + goto done; + } + g = np_malloc(sizeof(*g) + 256); + pthread_mutex_init(&g->lock, NULL); + g->gname = NULL; + pthread_mutex_lock(&g->lock); + pthread_mutex_unlock(&groupcache.lock); + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); if (bufsize < 256) bufsize = 256; buf = np_malloc(bufsize); - if (!buf) - return NULL; - err = getgrgid_r(gid, &grp, buf, bufsize, &pgrp); if (err) { np_uerror(err); free(buf); + pthread_mutex_unlock(&g->lock); return NULL; } - g = np_malloc(sizeof(*g) + strlen(grp.gr_name) + 1); - if (!g) { - free(buf); - return NULL; - } - - pthread_mutex_init(&g->lock, NULL); g->refcount = 1; g->upool = up; g->gid = grp.gr_gid; g->gname = (char *)g + sizeof(*g); - strcpy(g->gname, grp.gr_name); + strncpy(g->gname, grp.gr_name, 256); - pthread_mutex_lock(&groupcache.lock); - g->next = groupcache.htable[n]; - groupcache.htable[n] = g; - pthread_mutex_unlock(&groupcache.lock); - + pthread_mutex_unlock(&g->lock); free(buf); done: @@ -353,15 +378,19 @@ { int i; - if (!u->groups && np_init_user_groups(u)<0) + pthread_mutex_lock(&u->lock); + if (!u->groups && np_init_user_groups(u) < 0) { + pthread_mutex_unlock(&u->lock); return -1; + } for(i = 0; i < u->ngroups; i++) { if (g == u->groups[i]) - return 1; + break; } + pthread_mutex_unlock(&u->lock); - return 0; + return i < u->ngroups; } static void @@ -386,6 +415,7 @@ free(u->groups); u->ngroups = 0; + pthread_mutex_lock(&grentlock); setgrent(); if(u->dfltgroup) { @@ -404,6 +434,7 @@ } endgrent(); + pthread_mutex_unlock(&grentlock); grps = np_malloc(sizeof(*grps) * n); if (!grps) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |