rpms/vixie-cron/devel vixie-cron-4.1-_53_bz199294_selinux_mls.patch, NONE, 1.1 vixie-cron-4.1-_54_bz198019_database_changes.patch, NONE, 1.1 vixie-cron.spec, 1.71, 1.72

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Fri Jul 21 02:01:27 UTC 2006


Author: jvdias

Update of /cvs/dist/rpms/vixie-cron/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv2981

Modified Files:
	vixie-cron.spec 
Added Files:
	vixie-cron-4.1-_53_bz199294_selinux_mls.patch 
	vixie-cron-4.1-_54_bz198019_database_changes.patch 
Log Message:
fix bugs 198019, 199294

vixie-cron-4.1-_53_bz199294_selinux_mls.patch:
 crontab.1  |    8 ++
 crontab.5  |   13 +++
 crontab.c  |   52 ++++++++++----
 funcs.h    |    4 -
 security.c |  219 ++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 5 files changed, 242 insertions(+), 54 deletions(-)

--- NEW FILE vixie-cron-4.1-_53_bz199294_selinux_mls.patch ---
--- vixie-cron-4.1/crontab.c.selinux_mls	2006-07-20 20:10:27.000000000 -0400
+++ vixie-cron-4.1/crontab.c	2006-07-20 20:10:27.000000000 -0400
@@ -43,10 +43,19 @@
 
 #if DEBUGGING
 static char	*Options[] = { "???", "list", "delete", "edit", "replace" };
+#   ifdef WITH_SELINUX
+static char	*getoptargs = "u:lerisx:";
+#   else
 static char	*getoptargs = "u:lerix:";
+#   endif
 #else
+#   ifdef WITH_SELINUX
+static char	*getoptargs = "u:leris";
+#   else
 static char	*getoptargs = "u:leri";
+#   endif
 #endif
+static char     *selinux_context = 0;
 
 static	PID_T		Pid;
 static	char		User[MAX_UNAME], RealUser[MAX_UNAME];
@@ -75,6 +84,9 @@
 	fprintf(stderr, "\t-l\t(list user's crontab)\n");
 	fprintf(stderr, "\t-r\t(delete user's crontab)\n");
 	fprintf(stderr, "\t-i\t(prompt before deleting user's crontab)\n");
+#ifdef WITH_SELINUX
+	fprintf(stderr, "\t-s\t(selinux context)\n");
+#endif
 	exit(ERROR_EXIT);
 }
 
@@ -198,6 +210,16 @@
 		case 'i':
        		        PromptOnDelete = 1;
 			break;
+#ifdef WITH_SELINUX
+	        case 's':
+		        if ( getprevcon( (security_context_t*)&(selinux_context) ) ) 
+			{
+				fprintf(stderr,
+					"Cannot obtain SELinux process context\n");
+				exit(ERROR_EXIT);
+			}
+			break;
+#endif 
 		default:
 			usage("unrecognized option");
 		}
@@ -317,7 +339,7 @@
 edit_cmd(void) {
 	char n[MAX_FNAME], q[MAX_TEMPSTR], *editor;
 	FILE *f;
-	int ch='\0', t, x;
+	int ch='\0', t;
 	struct stat statbuf;
 	struct utimbuf utimebuf;
 	WAIT_T waiter;
@@ -379,26 +401,22 @@
 	}
 
 	Set_LineNum(1)
-
-	/* ignore the top NHEADER_LINES comment lines since we put them there.
+	/* 
+	 * NHEADER_LINES processing removed for clarity
+	 * (NHEADER_LINES == 0 in all Red Hat crontabs)
 	 */
-	x = 0;
-	while ((x < NHEADER_LINES) && (EOF != (ch = get_char(f)))) {
-		if ('#' != ch) {
-			putc(ch, NewCrontab);
-			break;
-		}
-		while (EOF != (ch = get_char(f)))
-			if (ch == '\n')
-				break;
-		++x;
-	}
-
+	
 	/* copy the rest of the crontab (if any) to the temp file.
 	 */
 	if (EOF != ch)
 		while (EOF != (ch = get_char(f)))
 			putc(ch, NewCrontab);
+
+#ifdef WITH_SELINUX
+	if ( selinux_context )
+		fprintf(NewCrontab,"SELINUX_ROLE_TYPE=%s\n", selinux_context);
+#endif
+
 	fclose(f);
 	if (fflush(NewCrontab) < OK) {
 		perror(Filename);
@@ -610,6 +628,10 @@
 	 *fprintf(tmp, "# (%s installed on %-24.24s)\n", Filename, ctime(&now));
 	 *fprintf(tmp, "# (Cron version %s -- %s)\n", CRON_VERSION, rcsid);
 	 */
+#ifdef WITH_SELINUX
+	if ( selinux_context )
+		fprintf(tmp,"SELINUX_ROLE_TYPE=%s\n", selinux_context);
+#endif
 
 	/* copy the crontab to the tmp
 	 */
--- vixie-cron-4.1/funcs.h.selinux_mls	2006-07-20 20:10:27.000000000 -0400
+++ vixie-cron-4.1/funcs.h	2006-07-20 20:10:27.000000000 -0400
@@ -88,7 +88,9 @@
 
 int cron_change_user( struct passwd *pw );
 
-int cron_change_selinux_context( user *u );
+int cron_get_job_context( user *u, void *scontextp, void *file_contextp, char **envp );
+
+int cron_change_selinux_context( user *, void *scontext, void *file_context );
 
 int get_security_context(const char *name, 
 			 int crontab_fd, 
--- vixie-cron-4.1/crontab.1.selinux_mls	2006-07-20 20:10:26.000000000 -0400
+++ vixie-cron-4.1/crontab.1	2006-07-20 20:10:27.000000000 -0400
@@ -32,6 +32,7 @@
 .RB [ -u
 .IR user ]
 .RB [ -l " | " -r " | " -e ] [ -i ]
+.RB [ -s ]
 .SH DESCRIPTION
 .I Crontab
 is the program used to install, deinstall or list the tables
@@ -89,6 +90,13 @@
 .I -i
 option modifies the -r option to prompt the user for a 'y/Y' response
 before actually removing the crontab.
+.PP
+The
+.I -s
+option will append the current SELinux security context string as an
+SELINUX_ROLE_TYPE setting to the crontab file before editing / replacement
+occurs - see the documentation of SELINUX_ROLE_TYPE in 
+.IR crontab(5) .
 .SH "SEE ALSO"
 crontab(5), cron(8)
 .SH FILES
--- vixie-cron-4.1/crontab.5.selinux_mls	2006-07-20 20:10:27.000000000 -0400
+++ vixie-cron-4.1/crontab.5	2006-07-20 20:10:27.000000000 -0400
@@ -87,6 +87,19 @@
 setting the CONTENT_TYPE and CONTENT_TRANSFER_ENCODING variables in crontabs,
 to the correct values of the mail headers of those names.  
 .PP
+The SELINUX_ROLE_TYPE environment variable provides support for multiple per-job 
+SELinux security contexts in the same crontab.
+By default, cron jobs execute with the default SELinux security context of the 
+user that created the crontab file.
+When using multiple security levels and roles, this may not be sufficient, because
+the same user may be running in a different role or at a different security level.
+You can set SELINUX_ROLE_TYPE to the SELinux security context string specifying
+the SELinux security context in which you want the job to run, and crond will set 
+the execution context of the or jobs to which the setting applies to the specified 
+context.
+See also the 
+.IR crontab(1) -s option.
+.PP
 The format of a cron command is very much the V7 standard, with a number of
 upward-compatible extensions.  Each line has five time and date fields,
 followed by a user name if this is the system crontab file,
--- vixie-cron-4.1/security.c.selinux_mls	2006-07-20 20:10:27.000000000 -0400
+++ vixie-cron-4.1/security.c	2006-07-20 20:29:32.000000000 -0400
@@ -49,23 +49,49 @@
 	      );
 	return -1;
     }
-    
+
+    *jobenv = build_env( e->envp );
+
+#ifdef WITH_SELINUX
+
+    /* we must get the crontab context BEFORE changing user, else
+     * we'll not be permitted to read the cron spool directory :-)
+     */
+
+    security_context_t scontext=0, file_context=0; 
+
+    if ( cron_get_job_context(u, &scontext, &file_context, *jobenv) < OK )
+    {
+	syslog(LOG_ERR, "CRON (%s) ERROR: failed to get selinux context: %s", 
+	       e->pwd->pw_name, strerror(errno)
+	      );
+	return -1;
+    }
+
+#endif
+
     if ( cron_change_user( e->pwd ) != 0 )
     {
 	syslog(LOG_INFO, "CRON (%s) ERROR: failed to open PAM security session: %s", 
 	       e->pwd->pw_name, strerror(errno)
 	      );
 	return -1;
-    }
-	
-    if ( cron_change_selinux_context( u ) != 0 )
+    }	
+
+    if ( cron_change_selinux_context( u, scontext, file_context ) != 0 )
     {
         syslog(LOG_INFO,"CRON (%s) ERROR: failed to change SELinux context", 
 	       e->pwd->pw_name);
+#if WITH_SELINUX
+	if ( file_context )
+		freecon(file_context);
+#endif
 	return -1;
     }
-
-    *jobenv = build_env( e->envp );
+#if WITH_SELINUX
+    if ( file_context )
+	freecon(file_context);
+#endif
 
     log_close();
     openlog(ProgramName, LOG_PID, LOG_CRON);
@@ -167,23 +193,145 @@
     return 0;
 }
 
-int cron_change_selinux_context( user *u )
+static int 
+cron_authorize_context
+( 
+	security_context_t scontext,
+	security_context_t file_context
+)	
 {
 #ifdef WITH_SELINUX
-    if ((is_selinux_enabled() >0) && (u->scontext != 0L)) {
-	if (setexeccon(u->scontext) < 0) {
-	    if (security_getenforce() > 0) {
-		syslog(LOG_INFO,
-		       "CRON (%s) ERROR:"
-		       "Could not set exec context to %s for user\n", 
-		       u->name, u->scontext
-		      );
+	struct av_decision avd;
+	int retval;
+	/*
+	 * Since crontab files are not directly executed,
+	 * crond must ensure that the crontab file has
+	 * a context that is appropriate for the context of
+	 * the user cron job.  It performs an entrypoint
+	 * permission check for this purpose.
+	 */
+	retval = security_compute_av(scontext,
+				     file_context,
+				     SECCLASS_FILE,
+				     FILE__ENTRYPOINT,
+				     &avd);
+
+	if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT))
+		return 0;
+#endif
+	return 1;
+}
+
+int cron_get_job_context( user *u, void *scontextp, void *file_contextp, char **jobenv )
+{
+#if WITH_SELINUX
+	char *sroletype;
+
+	if ( is_selinux_enabled() <= 0 )
+		return 0;
+	if ( (file_contextp == 0) || (scontextp == 0L) )
 		return -1;
-	    }
+
+	*((security_context_t*)scontextp) = u->scontext;
+	*((void **)file_contextp) = 0L;
+
+	if ( (sroletype = env_get("SELINUX_ROLE_TYPE",jobenv)) != 0L )
+	{
+	        *((security_context_t*)scontextp) = (security_context_t) sroletype;
+		
+		char crontab[MAX_FNAME];
+		if ( strcmp(u->name,"*system*") == 0 )
+			strncpy(crontab, u->tabname, MAX_FNAME);
+		else
+			snprintf(crontab, MAX_FNAME, "%s/%s", CRONDIR, u->tabname);
+
+		if ( getfilecon( crontab, file_contextp ) == -1 )
+		{		
+			if ( security_getenforce() > 0 ) 
+			{
+				log_it(u->name, 
+				       getpid(), "getfilecon FAILED for SELINUX_ROLE_TYPE", 
+				       sroletype
+				      );
+				return -1;
+			} else
+			if ( access( crontab, F_OK ) )
+				log_it(u->name,
+				       getpid(), 
+				       "getfilecon FAILED but SELinux in permissive mode, continuing "
+				       "- SELINUX_ROLE_TYPE=", sroletype
+				       );
+		}		       
 	}
-    }
 #endif
-    return 0;
+	return 0;
+}
+
+int cron_change_selinux_context( user *u, void *scontext, void *file_context )
+{
+#ifdef WITH_SELINUX
+	if ( is_selinux_enabled() <= 0 )
+		return 0;
+
+	if ( scontext == 0L )
+	{
+		if (security_getenforce() > 0) 
+		{
+			log_it( u->name, getpid(), 
+				"NULL security context for user", 
+				""
+			      );
+			return -1;
+		}else
+		{
+			log_it( u->name, getpid(), 
+				"NULL security context for user, "
+				"but SELinux in permissive mode, continuing",
+				""
+				);
+			return 0;
+		}
+	}
+	
+	if ( file_context )
+	{		
+		if ( ! cron_authorize_context( scontext, file_context ) )
+		{
+			if ( security_getenforce() > 0 ) 
+			{
+				syslog(LOG_ERR,
+				       "CRON (%s) ERROR:"
+				       "Unauthorized exec context to SELINUX_ROLE_TYPE %s for user", 
+				       u->name, (char*)scontext
+				      );
+				return -1;
+			} else
+			{
+				syslog(LOG_INFO,
+				       "CRON (%s) WARNING:"
+				       "Unauthorized exec context to SELINUX_ROLE_TYPE %s for user,"
+				       " but SELinux in permissive mode, continuing", 
+				       u->name, (char*)scontext
+				      );
+			}
+		}
+	} 
+
+	if ( setexeccon(scontext) < 0 ) 
+	{
+		if (security_getenforce() > 0) 
+		{
+			syslog(LOG_ERR,
+			       "CRON (%s) ERROR:"
+			       "Could not set exec context to %s for user", 
+			       u->name, (char*)scontext
+			      );
+
+			return -1;
+		}
+	}
+#endif
+	return 0;
 }
 
 int get_security_context( const char *name, 
@@ -192,8 +340,7 @@
 			  const char *tabname) {
 #ifdef WITH_SELINUX
 	security_context_t scontext=NULL;
-	security_context_t  file_context=NULL;
-	struct av_decision avd;
+	security_context_t file_context=NULL;
 	int retval=0;
 	char *seuser=NULL;
 	char *level=NULL;
@@ -233,28 +380,24 @@
 		}
 	}
     
-	/*
-	 * Since crontab files are not directly executed,
-	 * crond must ensure that the crontab file has
-	 * a context that is appropriate for the context of
-	 * the user cron job.  It performs an entrypoint
-	 * permission check for this purpose.
-	 */
-	retval = security_compute_av(scontext,
-				     file_context,
-				     SECCLASS_FILE,
-				     FILE__ENTRYPOINT,
-				     &avd);
-	freecon(file_context);
-	if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT)) {
+	if ( ! cron_authorize_context( scontext, file_context ) )
+	{
+		freecon(scontext);
+		freecon(file_context);
 		if (security_getenforce() > 0) {
-			log_it(name, getpid(), "ENTRYPOINT FAILED", tabname);
-			freecon(scontext);
+			log_it(name, getpid(), "Unauthorized SELinux context", tabname);
 			return -1;
-		} else {
-			log_it(name, getpid(), "ENTRYPOINT FAILED but SELinux in permissive mode, continuing", tabname);
+		} else
+		{
+			log_it(name, getpid(), 
+			       "Unauthorized SELinux context, but SELinux in permissive mode, continuing",
+			       tabname
+			      );
+			return  0;
 		}
 	}
+	freecon(file_context);
+
 	*rcontext=scontext;
 #endif
 	return 0;

vixie-cron-4.1-_54_bz198019_database_changes.patch:
 database.c |  129 ++++++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 86 insertions(+), 43 deletions(-)

--- NEW FILE vixie-cron-4.1-_54_bz198019_database_changes.patch ---
--- vixie-cron-4.1/database.c.bz198019	2006-07-20 21:42:01.000000000 -0400
+++ vixie-cron-4.1/database.c	2006-07-20 21:46:51.000000000 -0400
@@ -34,6 +34,12 @@
 					const char *, struct stat *,
 					cron_db *, cron_db *);
 
+static int not_a_crontab( DIR_T *dp ); 
+/* return 1 if we should skip this file */
+
+static void max_mtime( char *dir_name, struct stat *max_st ); 
+/* record max mtime of any file under dir_name in max_st */
+
 void
 load_database(cron_db *old_db) {
 	struct stat statbuf, syscron_stat, crond_stat;
@@ -52,12 +58,20 @@
 		log_it("CRON", getpid(), "STAT FAILED", SPOOL_DIR);
 		(void) exit(ERROR_EXIT);
 	}
+	
+	/* As pointed out in Red Hat bugzilla 198019, with modern Linux it
+	 * is possible to modify a file without modifying the mtime of the
+         * containing directory. Hence, we must check the mtime of each file:
+         */
+	max_mtime(SPOOL_DIR, &statbuf);
 
 	if (stat(RH_CROND_DIR, &crond_stat) < OK) {
 		log_it("CRON", getpid(), "STAT FAILED", RH_CROND_DIR);
 		(void) exit(ERROR_EXIT);
 	}
 
+	max_mtime(RH_CROND_DIR, &crond_stat);
+
 	/* track system crontab file
 	 */
 	if (stat(SYSCRONTAB, &syscron_stat) < OK)
@@ -97,40 +111,12 @@
 	}
 
 	while (NULL != (dp = readdir(dir))) {
-		char	fname[MAXNAMLEN+1],
-			tabname[MAXNAMLEN+1];
-		size_t len;
-
-		/* avoid file names beginning with ".".  this is good
-		 * because we would otherwise waste two guaranteed calls
-		 * to getpwnam() for . and .., and there shouldn't be 
-		 * hidden files in here anyway
-		 */
-		if (dp->d_name[0] == '.')
-			continue;
-
-		/* ignore files starting with # and ending with ~ */
-		if (dp->d_name[0] == '#')
-			continue;
-		
-		len = strlen(dp->d_name);
-
-		if (len >= sizeof fname)
-			continue;	/* XXX log? */
-
-		if ((len > 0) && (dp->d_name[len - 1] == '~'))
-			continue;
+		char   tabname[MAXNAMLEN+1];
 
-		(void) strcpy(fname, dp->d_name);
-		
-		if ((len > 8) && (strncmp(fname + len - 8, ".rpmsave", 8) == 0))
-			continue;
-		if ((len > 8) && (strncmp(fname + len - 8, ".rpmorig", 8) == 0))
-			continue;
-		if ((len > 7) && (strncmp(fname + len - 7, ".rpmnew", 7) == 0))
+		if ( not_a_crontab( dp ) )
 			continue;
 
-		if (!glue_strings(tabname, sizeof tabname, RH_CROND_DIR, fname, '/'))
+		if (!glue_strings(tabname, sizeof tabname, RH_CROND_DIR, dp->d_name, '/'))
 			continue;	/* XXX log? */
 
 		process_crontab("root", NULL, tabname,
@@ -142,6 +128,7 @@
 	 * efficiency.  however, we need to close it in every fork, and
 	 * we fork a lot more often than the mtime of the dir changes.
 	 */
+
 	if (!(dir = opendir(SPOOL_DIR))) {
 		log_it("CRON", getpid(), "OPENDIR FAILED", SPOOL_DIR);
 		(void) exit(ERROR_EXIT);
@@ -150,20 +137,12 @@
 	while (NULL != (dp = readdir(dir))) {
 		char fname[MAXNAMLEN+1], tabname[MAXNAMLEN+1];
 
-		/* avoid file names beginning with ".".  this is good
-		 * because we would otherwise waste two guaranteed calls
-		 * to getpwnam() for . and .., and also because user names
-		 * starting with a period are just too nasty to consider.
-		 */
-		if (dp->d_name[0] == '.')
+		if ( not_a_crontab( dp ) )
 			continue;
 
-		if (strlen(dp->d_name) >= sizeof fname)
-			continue;	/* XXX log? */
-		(void) strcpy(fname, dp->d_name);
-		
-		if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR,
-				  fname, '/'))
+		strncpy(fname, dp->d_name, MAXNAMLEN);
+
+		if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, fname, '/'))
 			continue;	/* XXX log? */
 
 		process_crontab(fname, fname, tabname,
@@ -322,3 +301,67 @@
 		close(crontab_fd);
 	}
 }
+
+static int not_a_crontab( DIR_T *dp )
+{
+	int len;
+
+	/* avoid file names beginning with ".".  this is good
+	 * because we would otherwise waste two guaranteed calls
+	 * to getpwnam() for . and .., and there shouldn't be 
+	 * hidden files in here anyway
+	 */
+	if (dp->d_name[0] == '.')
+		return(1);
+
+	/* ignore files starting with # and ending with ~ */
+	if (dp->d_name[0] == '#')
+		return(1);
+
+	len = strlen(dp->d_name);
+
+	if (len >= MAXNAMLEN)
+		return(1);	/* XXX log? */
+
+	if ((len > 0) && (dp->d_name[len - 1] == '~'))
+		return(1);
+
+	if ((len > 8) && (strncmp(dp->d_name + len - 8, ".rpmsave", 8) == 0))
+		return(1);
+	if ((len > 8) && (strncmp(dp->d_name + len - 8, ".rpmorig", 8) == 0))
+		return(1);
+	if ((len > 7) && (strncmp(dp->d_name + len - 7, ".rpmnew", 7) == 0))
+		return(1);
+
+	return(0);
+}
+
+static void max_mtime( char *dir_name, struct stat *max_st )
+{
+	DIR * dir;
+	DIR_T *dp;
+	struct stat st;
+
+	if (!(dir = opendir(dir_name))) {
+		log_it("CRON", getpid(), "OPENDIR FAILED", dir_name);
+		(void) exit(ERROR_EXIT);
+	}
+
+	while (NULL != (dp = readdir(dir))) 
+	{
+		char tabname[MAXNAMLEN+1];
+
+		if ( not_a_crontab ( dp ) )
+			continue;
+
+		if (!glue_strings(tabname, sizeof tabname, SPOOL_DIR, dp->d_name, '/'))
+			continue;	/* XXX log? */
+
+		if ( stat( tabname, &st ) < OK )
+			continue;       /* XXX log? */
+		
+		if ( st.st_mtime > max_st->st_mtime )
+			max_st->st_mtime = st.st_mtime;		
+	}
+	closedir(dir);
+}


Index: vixie-cron.spec
===================================================================
RCS file: /cvs/dist/rpms/vixie-cron/devel/vixie-cron.spec,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -r1.71 -r1.72
--- vixie-cron.spec	15 Jul 2006 00:27:50 -0000	1.71
+++ vixie-cron.spec	21 Jul 2006 02:01:22 -0000	1.72
@@ -10,7 +10,7 @@
 Summary: The Vixie cron daemon for executing specified programs at set times.
 Name: vixie-cron
 Version: 4.1
-Release: 56.FC6
+Release: 58%{?dist}
 Epoch:   4
 License: distributable
 Group:   System Environment/Base
@@ -70,6 +70,8 @@
 Patch50: vixie-cron-4.1-_50-bz178931.patch
 Patch51: vixie-cron-4.1-_51-bz180145-mail_i18n.patch
 Patch52: vixie-cron-4.1-_52-bz181439.patch
+Patch53: vixie-cron-4.1-_53_bz199294_selinux_mls.patch
+Patch54: vixie-cron-4.1-_54_bz198019_database_changes.patch
 Buildroot: %{_tmppath}/%{name}-%{version}-root
 Requires: syslog, bash >= 2.0
 Conflicts: sysklogd < 1.4.1
@@ -158,6 +160,8 @@
 %patch50 -p1 -b .bz178931
 %patch51 -p1 -b .mail_i18n
 %patch52 -p1 -b .bz181439
+%patch53 -p1 -b .selinux_mls
+%patch54 -p1 -b .bz198019
 
 %build
 make RPM_OPT_FLAGS="$RPM_OPT_FLAGS -g -DLINT -Dlint -Werror" \
@@ -225,6 +229,11 @@
 %config(noreplace) /etc/sysconfig/crond
 
 %changelog
+* Thu Jul 20 2006 Jason Vas Dias <jvdias at redhat.com> - 4:4.1-58
+- fix bug 199294: support for LSPP multiple per-job SELinux contexts
+- fix bug 198019: make database.c correct if crontab mtime changes 
+                  while spool dir mtime does not.
+
 * Fri Jul 14 2006 Jason Vas Dias <jvdias at redhat.com> - 4:4.1-56.FC6
 - fix bug 198893 - change permissions of cron spool directories to 0700
 




More information about the fedora-cvs-commits mailing list