From 0dfc30cf87ab3b5746701034150e3a6400857148 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 17 Mar 2001 03:36:38 +0000 Subject: lib/system.c (Finally) fixed all insure errors in password caching code. We can't stop libc routines from calling getpwXXX functions, so caching a pointer to them is impossible. This new code now makes two copies of the returned struct passwd struct - one used as a cache, one returned to allow the caller to modify. When doing a lookup we compare against the cached copy. Code is now easier to understand also. smbd/posix_acls.c: If we move the head of the linked list, remember to pass a reference to that pointer..... Jeremy. (This used to be commit af364b93d92f70aa52195c46d3cc516830752609) --- source3/lib/system.c | 109 ++++++++++++++++++++++------------------------ source3/smbd/posix_acls.c | 23 ++++++++-- 2 files changed, 73 insertions(+), 59 deletions(-) diff --git a/source3/lib/system.c b/source3/lib/system.c index 5557aa8735..526113dcf7 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -580,49 +580,61 @@ int sys_setgroups(int setlen, gid_t *gidset) Helper function for getpwnam/getpwuid wrappers. ****************************************************************************/ +struct saved_pw { + fstring pw_name; + fstring pw_passwd; + struct passwd pass; +}; + +static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */ +static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */ + +static int num_lookups; /* Counter so we don't always use cache. */ +#ifndef PW_RET_CACHE_MAX_LOOKUPS +#define PW_RET_CACHE_MAX_LOOKUPS 100 +#endif + static struct passwd *setup_pwret(struct passwd *pass) { - static fstring pw_name; - static fstring pw_passwd; - static struct passwd pw_ret; - - if (pass == NULL) + if (pass == NULL) { + /* Clear the caches. */ + memset(&pw_cache, '\0', sizeof(struct saved_pw)); + memset(&pw_mod, '\0', sizeof(struct saved_pw)); + num_lookups = 0; return NULL; + } /* this gets the uid, gid and null pointers */ - memcpy((char *)&pw_ret, pass, sizeof(struct passwd)); - if (pass->pw_name) - { - pw_ret.pw_name = pw_name; - fstrcpy(pw_ret.pw_name, pass->pw_name); - } + memcpy((char *)&pw_mod.pass, pass, sizeof(struct passwd)); + fstrcpy(pw_mod.pw_name, pass->pw_name); + pw_mod.pass.pw_name = pw_mod.pw_name; + fstrcpy(pw_mod.pw_passwd, pass->pw_passwd); + pw_mod.pass.pw_passwd = pw_mod.pw_passwd; - if (pass->pw_passwd) - { - pw_ret.pw_passwd = pw_passwd; - fstrcpy(pw_ret.pw_passwd, pass->pw_passwd); - } - return &pw_ret; -} + if (pass != &pw_cache.pass) { -/* static pointer to be used for caching the last - getpw[nam|uid]() call. Patch by "Richard Bollinger" - */ + /* If it's a cache miss we must also refill the cache. */ -/* - * This next static pointer is used to cache the results - * from the real getpwXX calls. It is never returned to - * the caller, only the output from calling setup_pwret with - * this is returned. JRA. - */ + memcpy((char *)&pw_cache.pass, pass, sizeof(struct passwd)); + fstrcpy(pw_cache.pw_name, pass->pw_name); + pw_cache.pass.pw_name = pw_cache.pw_name; + fstrcpy(pw_cache.pw_passwd, pass->pw_passwd); + pw_cache.pass.pw_passwd = pw_cache.pw_passwd; -static struct passwd *sv_pw_ret; /* implicitly initialized to NULL */ -static int num_lookups; /* Counter so we don't always use cache. */ -#ifndef PW_RET_CACHE_MAX_LOOKUPS -#define PW_RET_CACHE_MAX_LOOKUPS 100 -#endif + num_lookups = 1; + + } else { + + /* Cache hit. */ + + num_lookups++; + num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS); + } + + return &pw_mod.pass; +} /************************************************************************** Wrappers for setpwent(), getpwent() and endpwent() @@ -630,19 +642,18 @@ static int num_lookups; /* Counter so we don't always use cache. */ void sys_setpwent(void) { - sv_pw_ret = NULL; + setup_pwret(NULL); /* Clear cache. */ setpwent(); } struct passwd *sys_getpwent(void) { - sv_pw_ret = getpwent(); - return setup_pwret(sv_pw_ret); + return setup_pwret(getpwent()); } void sys_endpwent(void) { - sv_pw_ret = NULL; + setup_pwret(NULL); /* Clear cache. */ endpwent(); } @@ -656,22 +667,15 @@ struct passwd *sys_getpwnam(const char *name) return NULL; /* check for a cache hit first */ - if (num_lookups && sv_pw_ret && !strcmp(name, sv_pw_ret->pw_name)) - { + if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) { DEBUG(2,("getpwnam(%s) avoided - using cached results\n",name)); - num_lookups++; - num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS); - return setup_pwret(sv_pw_ret); + return setup_pwret(&pw_cache.pass); } /* no cache hit--use old lookup instead */ DEBUG(2,("getpwnam(%s) called\n",name)); - num_lookups = 1; - - sv_pw_ret = getpwnam(name); - - return setup_pwret(sv_pw_ret); + return setup_pwret(getpwnam(name)); } /************************************************************************** @@ -680,21 +684,14 @@ struct passwd *sys_getpwnam(const char *name) struct passwd *sys_getpwuid(uid_t uid) { - if (num_lookups && sv_pw_ret && (uid == sv_pw_ret->pw_uid)) - { + if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) { DEBUG(2,("getpwuid(%d) avoided - using cached results\n",uid)); - num_lookups++; - num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS); - return setup_pwret(sv_pw_ret); + return setup_pwret(&pw_cache.pass); } DEBUG(2,("getpwuid(%d) called\n",uid)); - num_lookups = 1; - - sv_pw_ret = getpwuid(uid); - - return setup_pwret(sv_pw_ret); + return setup_pwret(getpwuid(uid)); } /************************************************************************** diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index f73f122f43..e358e0238c 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -930,9 +930,10 @@ static void free_canon_ace_list( canon_ace *list_head ) entries, last entry = other. ********************************************************************************/ -static void arrange_posix_perms( char *filename, canon_ace *list_head) +static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) { extern DOM_SID global_sid_World; + canon_ace *list_head = *pp_list_head; canon_ace *owner_ace = NULL; canon_ace *other_ace = NULL; canon_ace *ace = NULL; @@ -1011,6 +1012,10 @@ static void arrange_posix_perms( char *filename, canon_ace *list_head) owner_ace->attr = DENY_ACE; owner_ace->perms = 0; } + + /* We have probably changed the head of the list. */ + + *pp_list_head = list_head; } /****************************************************************************** @@ -1080,7 +1085,7 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu DLIST_ADD(list_head, group_ace); DLIST_ADD(list_head, owner_ace); - arrange_posix_perms(fsp->fsp_name,list_head ); + arrange_posix_perms(fsp->fsp_name,&list_head ); return list_head; @@ -1219,6 +1224,8 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ * acl_mask. */ + DEBUG(10,("canonicalize_acl: ace entries before arrange :\n")); + for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { next_ace = ace->next; @@ -1229,9 +1236,13 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ if (ace->perms == 0) { DLIST_PROMOTE(list_head, ace); } + + if( DEBUGLVL( 10 ) ) { + print_canon_ace(ace, ace_count); + } } - arrange_posix_perms(fsp->fsp_name,list_head ); + arrange_posix_perms(fsp->fsp_name,&list_head ); if( DEBUGLVL( 10 ) ) { char *acl_text = sys_acl_to_text( posix_acl, NULL); @@ -1239,6 +1250,12 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ dbgtext("canonicalize_acl: processed acl %s\n", acl_text == NULL ? "NULL" : acl_text ); if (acl_text) sys_acl_free_text(acl_text); + + dbgtext("canonicalize_acl: ace entries after arrange :\n"); + + for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { + print_canon_ace(ace, ace_count); + } } return list_head; -- cgit