Explorar o código

[173687] deadlock caused by error log rotation and logging
Modified to change the owner to the "localuser" if the error log file is not
owned by the user.

Noriko Hosoi %!s(int64=20) %!d(string=hai) anos
pai
achega
1ec891b346

+ 18 - 0
ldap/servers/slapd/log.c

@@ -48,6 +48,7 @@
 
 #include "log.h"
 #include "fe.h"
+#include <pwd.h> /* getpwnam */
 
 #if defined( XP_WIN32 )
 #include <fcntl.h>
@@ -3225,6 +3226,17 @@ log__open_errorlogfile(int logfile_state, int locked)
 	char			tbuf[TBUFSIZE];
 	struct logfileinfo	*logp;
 	char			buffer[BUFSIZ];
+	struct passwd	*pw = NULL;
+
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+	if ( slapdFrontendConfig->localuser != NULL )  {
+		if ( (pw = getpwnam( slapdFrontendConfig->localuser )) == NULL )
+			return LOG_UNABLE_TO_OPENFILE;
+	}
+	else {
+		return LOG_UNABLE_TO_OPENFILE;
+	}
 
 	if (!locked) LOG_ERROR_LOCK_WRITE( );
 
@@ -3287,6 +3299,12 @@ log__open_errorlogfile(int logfile_state, int locked)
 		return LOG_UNABLE_TO_OPENFILE;
 	}
 
+	/* make sure the logfile is owned by the localuser.  If one of the
+	 * alternate ns-slapd modes, such as db2bak, tries to log an error
+	 * at startup, it will create the logfile as root! 
+	 */
+	slapd_chown_if_not_owner(loginfo.log_error_file, pw->pw_uid, -1);
+
 	loginfo.log_error_fdes = fp;
 	if (logfile_state == LOGFILE_REOPENED) {
 		/* we have all the information */

+ 3 - 29
ldap/servers/slapd/main.c

@@ -207,32 +207,6 @@ extern void collation_init();
 
 #ifndef WIN32
 
-/* Changes the ownership of the given file/directory iff not
-   already the owner
-   Returns 0 upon success or non-zero otherwise, usually -1 if
-   some system error occurred
-*/
-static int
-chown_if_not_owner(const char *filename, uid_t uid, gid_t gid)
-{
-	struct stat statbuf;
-	int result = 1;
-	if (!filename)
-		return result;
-
-	memset(&statbuf, '\0', sizeof(statbuf));
-	if (!(result = stat(filename, &statbuf)))
-	{
-		if (((uid != -1) && (uid != statbuf.st_uid)) ||
-			((gid != -1) && (gid != statbuf.st_gid)))
-		{
-			result = chown(filename, uid, gid);
-		}
-	}
-
-	return result;
-}
-
 /* 
    Four cases:
     - change ownership of all files in directory (strip_fn=PR_FALSE)
@@ -258,7 +232,7 @@ chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn)
     if((ptr=strrchr(log,'/'))==NULL)
     {
       LDAPDebug(LDAP_DEBUG_ANY, "Caution changing ownership of ./%s \n",name,0,0);
-      chown_if_not_owner(log, pw->pw_uid, -1 ); 
+      slapd_chown_if_not_owner(log, pw->pw_uid, -1 ); 
       rc=1;
     } else if(log==ptr) {
       LDAPDebug(LDAP_DEBUG_ANY, "Caution changing ownership of / directory and its contents to %s\n",pw->pw_name,0,0);
@@ -273,7 +247,7 @@ chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn)
     while( (entry = PR_ReadDir(dir , PR_SKIP_BOTH )) !=NULL ) 
     {
 	PR_snprintf(file,MAXPATHLEN+1,"%s/%s",log,entry->name);
-	chown_if_not_owner( file, pw->pw_uid, -1 ); 
+	slapd_chown_if_not_owner( file, pw->pw_uid, -1 ); 
     }
     PR_CloseDir( dir );
   }
@@ -302,7 +276,7 @@ fix_ownership()
 	}
 
 	/* The instance directory needs to be owned by the local user */
-	chown_if_not_owner( slapdFrontendConfig->instancedir, pw->pw_uid, -1 );
+	slapd_chown_if_not_owner( slapdFrontendConfig->instancedir, pw->pw_uid, -1 );
 	PR_snprintf(dirname,sizeof(dirname),"%s/config",slapdFrontendConfig->instancedir);
 	chown_dir_files(dirname, pw, PR_FALSE); /* config directory */
 	chown_dir_files(slapdFrontendConfig->accesslog, pw, PR_TRUE); /* do access log directory */

+ 1 - 0
ldap/servers/slapd/proto-slap.h

@@ -588,6 +588,7 @@ void g_set_accesslog_level(int val);
  */
 void slapd_nasty(char* str, int c, int err);
 int strarray2str( char **a, char *buf, size_t buflen, int include_quotes );
+int slapd_slapd_chown_if_not_owner(const char *filename, uid_t uid, gid_t gid);
 
 /*
  * modify.c

+ 27 - 0
ldap/servers/slapd/util.c

@@ -631,3 +631,30 @@ strarray2str( char **a, char *buf, size_t buflen, int include_quotes )
 	return( rc );
 }
 /*****************************************************************************/
+
+/* Changes the ownership of the given file/directory if not
+   already the owner
+   Returns 0 upon success or non-zero otherwise, usually -1 if
+   some system error occurred
+*/
+int
+slapd_chown_if_not_owner(const char *filename, uid_t uid, gid_t gid)
+{
+        struct stat statbuf;
+        int result = 1;
+        if (!filename)
+                return result;
+
+        memset(&statbuf, '\0', sizeof(statbuf));
+        if (!(result = stat(filename, &statbuf)))
+        {
+                if (((uid != -1) && (uid != statbuf.st_uid)) ||
+                        ((gid != -1) && (gid != statbuf.st_gid)))
+                {
+                        result = chown(filename, uid, gid);
+                }
+        }
+
+        return result;
+}
+