From 54cfde1f94295bb9182d31c0d07aba8557f6010a Mon Sep 17 00:00:00 2001 From: Marcela Mašláňová Date: Jul 03 2007 14:05:53 +0000 Subject: Modified patches. --- diff --git a/at-3.1.10-dont_fork.patch b/at-3.1.10-dont_fork.patch index 51e0842..4d56bf2 100644 --- a/at-3.1.10-dont_fork.patch +++ b/at-3.1.10-dont_fork.patch @@ -1,33 +1,39 @@ ---- at-3.1.10/atd.c.dont_fork 2007-01-30 11:02:37.000000000 +0100 -+++ at-3.1.10/atd.c 2007-01-30 11:07:23.000000000 +0100 -@@ -1001,7 +1001,7 @@ - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; +--- at-3.1.10/atd.8.in.fork 2005-08-29 10:08:51.000000000 +0200 ++++ at-3.1.10/atd.8.in 2007-07-03 14:04:05.000000000 +0200 +@@ -1,5 +1,5 @@ + .Id $Id$ +-.TH ATD 8 "Mar 1997" local "Linux Programmer's Manual" ++.TH ATD 3 "Jun 2007" at-3.1.10 "Linux Programmer's Manual" + .SH NAME + atd \- run jobs queued for later execution + .SH SYNOPSIS +@@ -10,6 +10,7 @@ + .IR batch_interval ] + .RB [ -d ] + .RB [ -s ] ++.RB [ -n ] + .SH DESCRIPTION + .B atd + runs jobs queued by +@@ -46,6 +47,9 @@ + is installed as + .B @prefix@/sbin/atrun + for backward compatibility. ++.TP 8 ++.B -n ++Don't fork option. + .SH WARNING + .B atd + won't work if its spool directory is mounted via NFS even if +--- at-3.1.10/daemon.h.fork 2005-08-05 05:16:01.000000000 +0200 ++++ at-3.1.10/daemon.h 2007-07-03 14:02:22.000000000 +0200 +@@ -14,3 +14,4 @@ + perr (const char *fmt, ...); -- while ((c = getopt(argc, argv, "sdl:b:")) != EOF) { -+ while ((c = getopt(argc, argv, "sdl:b:n:")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) -@@ -1014,10 +1014,15 @@ - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; -+ - case 'd': - daemon_debug++; -+ /* go through another option*/ -+ -+ case 'n': -+ daemon_nofork++; - break; -- -+ - case 's': - run_as_daemon = 0; - break; ---- at-3.1.10/daemon.c.dont_fork 2005-08-05 05:16:01.000000000 +0200 -+++ at-3.1.10/daemon.c 2007-01-30 11:06:19.000000000 +0100 + extern int daemon_debug; ++extern int daemon_nofork; +--- at-3.1.10/daemon.c.fork 2005-08-05 05:16:01.000000000 +0200 ++++ at-3.1.10/daemon.c 2007-07-03 14:01:51.000000000 +0200 @@ -50,7 +50,8 @@ static const char *svnid = "$Id$"; @@ -58,30 +64,3 @@ PRIV_START ---- at-3.1.10/daemon.h.dont_fork 2005-08-05 05:16:01.000000000 +0200 -+++ at-3.1.10/daemon.h 2007-01-30 11:07:54.000000000 +0100 -@@ -14,3 +14,4 @@ - perr (const char *fmt, ...); - - extern int daemon_debug; -+extern int daemon_nofork; ---- at-3.1.8/atd.8.in.dontfork 2002-01-18 08:41:03.000000000 +0100 -+++ at-3.1.8/atd.8.in 2007-01-30 10:51:51.000000000 +0100 -@@ -10,6 +10,7 @@ - .IR batch_interval ] - .RB [ -d ] - .RB [ -s ] -+.RB [ -n ] - .SH DESCRIPTION - .B atd - runs jobs queued by -@@ -46,6 +47,9 @@ - is installed as - .B @prefix@/sbin/atrun - for backward compatibility. -+.TP 8 -+.B -n -+Don't fork option. - .SH WARNING - .B atd - won't work if its spool directory is mounted via NFS even if diff --git a/at-3.1.10-makefile.patch b/at-3.1.10-makefile.patch index 5fe5f1b..53379c8 100644 --- a/at-3.1.10-makefile.patch +++ b/at-3.1.10-makefile.patch @@ -1,23 +1,36 @@ ---- at-3.1.10/Makefile.in.makefile 2006-09-12 08:33:38.000000000 +0200 -+++ at-3.1.10/Makefile.in 2006-09-12 08:44:52.000000000 +0200 -@@ -69,13 +69,13 @@ +--- at-3.1.10/Makefile.in.old 2005-08-29 10:08:28.000000000 +0200 ++++ at-3.1.10/Makefile.in 2007-07-02 15:38:48.000000000 +0200 +@@ -51,7 +51,7 @@ + privs.h + + OTHERS = parsetime.l parsetime.y +- ++TEST_VERBOSE = 0 + DOCS = Problems Copyright README ChangeLog timespec + + MISC = COPYING Makefile.in configure acconfig.h install-sh \ +@@ -67,13 +67,13 @@ all: at atd atrun at: $(ATOBJECTS) -- $(CC) $(CFLAGS) -o at -pie $(ATOBJECTS) $(LIBS) $(LEXLIB) -+ $(CC) $(CFLAGS) -o at -pie $(ATOBJECTS) $(LIBS) $(LEXLIB) $(PAMLIB) +- $(CC) $(CFLAGS) -o at $(ATOBJECTS) $(LIBS) $(LEXLIB) ++ $(CC) $(CFLAGS) -o at -pie $(ATOBJECTS) $(LIBS) $(LEXLIB) rm -f $(CLONES) $(LN_S) -f at atq $(LN_S) -f at atrm atd: $(RUNOBJECTS) -- $(CC) $(CFLAGS) -o atd -pie $(RUNOBJECTS) $(LIBS) $(PAMLIB) -+ $(CC) $(CFLAGS) -o atd -pie $(RUNOBJECTS) $(LIBS) $(SELINUXLIB) $(PAMLIB) +- $(CC) $(CFLAGS) -o atd $(RUNOBJECTS) $(LIBS) $(PAMLIB) ++ $(CC) $(CFLAGS) -o atd -pie $(RUNOBJECTS) $(LIBS) $(PAMLIB) y.tab.c y.tab.h: parsetime.y $(YACC) -d parsetime.y -@@ -90,35 +90,38 @@ - $(CC) -c $(CFLAGS) -fpie $(DEFS) $*.c +@@ -85,38 +85,42 @@ + configure + + .c.o: +- $(CC) -c $(CFLAGS) $(DEFS) $*.c ++ $(CC) -c $(CFLAGS) -fpie $(DEFS) $*.c install: all - $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(etcdir) @@ -33,18 +46,18 @@ + $(INSTALL) -m 755 -d $(IROOT)$(docdir) + $(INSTALL) -m 755 -d $(IROOT)$(atdocdir) + $(INSTALL) -m 755 -d $(IROOT)$(ATJOB_DIR) -+ $(INSTALL) -m 755 -d $(IROOT)$(etcdir)/pam.d -+ $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT) $(ATSPOOL_DIR) -+ chmod 700 $(IROOT)$(ATSPOOL_DIR) $(IROOT)$(ATJOB_DIR) ++ $(INSTALL) -m 755 -d $(IROOT)$(etcdir)/pam.d ++ $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT)$(ATSPOOL_DIR) ++ chmod 700 $(IROOT)$(ATJOB_DIR) $(IROOT)$(ATSPOOL_DIR) ++ chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(ATJOB_DIR) $(IROOT)$(ATSPOOL_DIR) touch $(IROOT)$(LFILE) chmod 600 $(IROOT)$(LFILE) -- chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(LFILE) + chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(LFILE) - test -f $(IROOT)$(etcdir)/at.allow || test -f $(IROOT)$(etcdir)/at.deny || $(INSTALL) -o root -g $(DAEMON_GROUPNAME) -m 640 at.deny $(IROOT)$(etcdir)/ - $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 6755 -s at $(IROOT)$(bindir) -+ chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(ATJOB_DIR) $(IROOT)$(ATSPOOL_DIR) -+ test -f $(IROOT)$(etcdir)/at.allow || test -f $(IROOT)$(etcdir)/at.deny || $(INSTALL) -m 600 at.deny $(IROOT)$(etcdir)/ ++ test -f $(IROOT)$(etcdir)/at.allow || test -f $(IROOT)$(etcdir)/at.deny || $(INSTALL) -m 600 at.deny $(IROOT)$(etcdir)/ + $(INSTALL) -o $(INSTALL_ROOT_USER) -g $(DAEMON_GROUPNAME) pam_atd $(IROOT)$(etcdir)/pam.d/atd -+ $(INSTALL) -m 4755 -s at $(IROOT)$(bindir) ++ $(INSTALL) -m 4755 at $(IROOT)$(bindir) $(LN_S) -f at $(IROOT)$(bindir)/atq $(LN_S) -f at $(IROOT)$(bindir)/atrm - $(INSTALL) -g root -o root -m 755 batch $(IROOT)$(bindir) @@ -55,10 +68,10 @@ - $(INSTALL) -g root -o root -m 755 atrun $(IROOT)$(sbindir) - $(INSTALL) -g root -o root -m 644 at.1 $(IROOT)$(man1dir)/ + $(INSTALL) -m 755 batch $(IROOT)$(bindir) -+ $(INSTALL) -m 755 -d $(IROOT)$(man1dir) -+ $(INSTALL) -m 755 -d $(IROOT)$(man5dir) -+ $(INSTALL) -m 755 -d $(IROOT)$(man8dir) -+ $(INSTALL) -m 755 -s atd $(IROOT)$(sbindir) ++ $(INSTALL) -d -m 755 $(IROOT)$(man1dir) ++ $(INSTALL) -d -m 755 $(IROOT)$(man5dir) ++ $(INSTALL) -d -m 755 $(IROOT)$(man8dir) ++ $(INSTALL) -m 755 atd $(IROOT)$(sbindir) + $(INSTALL) -m 755 atrun $(IROOT)$(sbindir) + $(INSTALL) -m 644 at.1 $(IROOT)$(man1dir)/ cd $(IROOT)$(man1dir) && $(LN_S) -f at.1 atq.1 && $(LN_S) -f at.1 batch.1 && $(LN_S) -f at.1 atrm.1 @@ -69,10 +82,21 @@ + $(INSTALL) -m 644 tmpman $(IROOT)$(man8dir)/atrun.8 rm -f tmpman - $(INSTALL) -g root -o root -m 644 at_allow.5 $(IROOT)$(man5dir)/ -+ $(INSTALL) -m 644 at_allow.5 $(IROOT)$(man5dir)/ - cd $(IROOT)$(man5dir) && $(LN_S) -f at_allow.5 at_deny.5 +- cd $(IROOT)$(man5dir) && $(LN_S) -f at_allow.5 at_deny.5 - $(INSTALL) -g root -o root -m 644 $(DOCS) $(IROOT)$(atdocdir) ++ $(INSTALL) -m 644 at_allow.5 $(IROOT)$(man5dir)/ ++ cd $(IROOT)$(man5dir) && $(LN_S) -f at_allow.5 at_deny.5 + $(INSTALL) -m 644 $(DOCS) $(IROOT)$(atdocdir) rm -f $(IROOT)$(mandir)/cat1/at.1* $(IROOT)$(mandir)/cat1/batch.1* \ $(IROOT)$(mandir)/cat1/atq.1* rm -f $(IROOT)$(mandir)/cat1/atd.8* +@@ -150,6 +154,9 @@ + parsetest: lex.yy.c y.tab.c + $(CC) -o parsetest $(CFLAGS) $(DEFS) -DTEST_PARSER -DNEED_YYWRAP lex.yy.c y.tab.c + ++test: parsetest ++ PERL_DL_NONLAZY=1 perl -e 'use Test::Harness qw(&runtests $$verbose); $$verbose=$(TEST_VERBOSE); runtests @ARGV;' test.pl ++ + .depend: $(CSRCS) + gcc $(CFLAGS) $(DEFS) -MM $(CSRCS) > .depend + diff --git a/at-3.1.10-pam.patch b/at-3.1.10-pam.patch index 3d3bc5f..9cc8b26 100644 --- a/at-3.1.10-pam.patch +++ b/at-3.1.10-pam.patch @@ -1,9 +1,40 @@ ---- at-3.1.10/atd.c.pam 2006-09-12 15:01:55.000000000 +0200 -+++ at-3.1.10/atd.c 2006-09-12 15:26:49.000000000 +0200 -@@ -73,6 +73,42 @@ - #ifdef HAVE_UNISTD_H - #include +--- at-3.1.10/perm.c.pam 2005-08-05 05:16:01.000000000 +0200 ++++ at-3.1.10/perm.c 2007-07-03 13:29:24.000000000 +0200 +@@ -51,6 +51,14 @@ + #define PRIV_END while(0) #endif + ++#ifdef WITH_PAM ++#include ++static pam_handle_t *pamh = NULL; ++static const struct pam_conv conv = { ++ NULL ++}; ++#endif ++ + /* Structures and unions */ + + +@@ -109,18 +117,54 @@ + int + check_permission() + { +- uid_t uid = geteuid(); ++ uid_t euid = geteuid(), uid=getuid(), egid=getegid(), gid=getgid(); + struct passwd *pentry; + int allow = 0, deny = 1; +- +- if (uid == 0) ++ int retcode = 0; ++ if (euid == 0) + return 1; + +- if ((pentry = getpwuid(uid)) == NULL) { ++ if ((pentry = getpwuid(euid)) == NULL) { + perror("Cannot access user database"); + exit(EXIT_FAILURE); + } + +#ifdef WITH_PAM +/* + * We must check if the atd daemon userid will be allowed to gain the job owner user's @@ -14,12 +45,11 @@ + +# define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \ + fprintf(stderr,"PAM authentication failure: %s\n",pam_strerror(pamh, retcode)); \ -+ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT ); -+ pam_close_session(pamh,PAM_SILENT); \ ++ pam_close_session(pamh,PAM_SILENT); \ + pam_end(pamh, retcode); \ -+ setregid(gid,egid); \ -+ setreuid(uid,euid); \ -+ return(0); \ ++ setregid(gid,egid); \ ++ setreuid(uid,euid); \ ++ return(0); \ + } + retcode = pam_start("atd", pentry->pw_name, &conv, &pamh); + PAM_FAIL_CHECK; @@ -32,6 +62,7 @@ + retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); + PAM_FAIL_CHECK; + ++ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT ); + pam_close_session(pamh,PAM_SILENT); + pam_end(pamh, PAM_ABORT); + @@ -40,10 +71,62 @@ + +#endif + + allow = user_in_file(ETCDIR "/at.allow", pentry->pw_name); + if (allow==0 || allow==1) + return allow; +--- at-3.1.10/config.h.in.pam 2005-08-05 05:16:02.000000000 +0200 ++++ at-3.1.10/config.h.in 2007-07-03 13:29:24.000000000 +0200 +@@ -181,3 +181,10 @@ + + #undef HAVE_ATTRIBUTE_NORETURN + #undef HAVE_PAM ++ ++/* Define if you are building with_pam */ ++#undef WITH_PAM ++ ++/* Define if you are building with_selinux */ ++#undef WITH_SELINUX ++ +--- at-3.1.10/configure.in.pam 2005-08-05 05:16:02.000000000 +0200 ++++ at-3.1.10/configure.in 2007-07-03 13:29:24.000000000 +0200 +@@ -316,4 +316,19 @@ + ) + AC_SUBST(DAEMON_GROUPNAME) ++AC_ARG_WITH(selinux, ++[ --with-selinux Define to run with selinux], ++AC_DEFINE(WITH_SELINUX), ++) ++AC_CHECK_LIB(selinux, is_selinux_enabled, SELINUXLIB=-lselinux) ++AC_SUBST(SELINUXLIB) ++AC_SUBST(WITH_SELINUX) ++ ++AC_ARG_WITH(pam, ++[ --with-pam Define to enable pam support ], ++AC_DEFINE(WITH_PAM), ++) ++AC_CHECK_LIB(pam, pam_start, PAMLIB='-lpam -lpam_misc') ++AC_SUBST(PAMLIB) ++ + AC_OUTPUT(Makefile atrun atd.8 atrun.8 at.1 batch) +--- at-3.1.10/atd.c.pam 2007-07-03 13:29:24.000000000 +0200 ++++ at-3.1.10/atd.c 2007-07-03 13:52:38.000000000 +0200 +@@ -74,6 +74,14 @@ + #include + #endif + ++#ifdef WITH_SELINUX ++#include ++#include ++int selinux_enabled=0; ++#include ++#include ++#endif ++ /* Local headers */ -@@ -83,6 +119,10 @@ + #include "privs.h" +@@ -83,6 +91,10 @@ #include "getloadavg.h" #endif @@ -54,7 +137,15 @@ /* Macros */ #define BATCH_INTERVAL_DEFAULT 60 -@@ -196,6 +236,19 @@ +@@ -121,6 +133,7 @@ + #define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \ + fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \ + syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \ ++ pam_close_session(pamh, PAM_SILENT); \ + pam_end(pamh, retcode); exit(1); \ + } + #define PAM_END { retcode = pam_close_session(pamh,0); \ +@@ -196,6 +209,19 @@ #define fork myfork #endif @@ -72,33 +163,50 @@ +#endif + static void - run_file(char *filename, uid_t uid, gid_t gid) + run_file(const char *filename, uid_t uid, gid_t gid) { -@@ -420,6 +473,8 @@ +@@ -378,18 +404,22 @@ + fstat(fd_out, &buf); + size = buf.st_size; + +-#ifdef HAVE_PAM +- PRIV_START ++//add for fedora, removed HAVE_PAM ++#ifdef WITH_PAM + retcode = pam_start("atd", pentry->pw_name, &conv, &pamh); + PAM_FAIL_CHECK; ++ retcode = pam_set_item(pamh, PAM_TTY, "atd"); ++ PAM_FAIL_CHECK; + retcode = pam_acct_mgmt(pamh, PAM_SILENT); + PAM_FAIL_CHECK; + retcode = pam_open_session(pamh, PAM_SILENT); PAM_FAIL_CHECK; retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); PAM_FAIL_CHECK; +- PRIV_END + closelog(); + openlog("atd", LOG_PID, LOG_ATD); - PRIV_END #endif ++//end -@@ -434,6 +489,14 @@ + close(STDIN_FILENO); + close(STDOUT_FILENO); +@@ -402,6 +432,14 @@ else if (pid == 0) { char *nul = NULL; char **nenvp = &nul; + char **pam_envp=0L; -+ -+ PRIV_START -+ #ifdef WITH_PAM -+ pam_envp = pam_getenvlist(pamh); -+ if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) -+ nenvp = pam_envp; -+ #endif ++ ++ PRIV_START ++#ifdef WITH_PAM ++ pam_envp = pam_getenvlist(pamh); ++ if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) ++ nenvp = pam_envp; ++#endif /* Set up things for the child; we want standard input from the * input file, and standard output and error sent to our output file. -@@ -455,8 +518,6 @@ +@@ -423,8 +461,6 @@ if (chdir(ATJOB_DIR) < 0) perr("Cannot chdir to " ATJOB_DIR); @@ -107,87 +215,84 @@ nice((tolower((int) queue) - 'a' + 1) * 2); if (initgroups(pentry->pw_name, pentry->pw_gid)) -@@ -472,10 +533,93 @@ - perr("Cannot reset signal handler to default"); +@@ -441,10 +477,90 @@ chdir("/"); + +#ifdef WITH_SELINUX + if (selinux_enabled>0) { -+ security_context_t user_context=NULL; -+ security_context_t file_context=NULL; -+ int retval=0; -+ struct av_decision avd; -+ char *seuser=NULL; -+ char *level=NULL; -+ -+ if (getseuserbyname(pentry->pw_name, &seuser, &level) == 0) { -+ retval=get_default_context_with_level(seuser, level, NULL, &user_context); -+ free(seuser); -+ free(level); -+ if (retval) { -+ if (security_getenforce()==1) { -+ perr("execle: couldn't get security context for user %s\n", pentry->pw_name); -+ } else { -+ syslog(LOG_ERR, "execle: couldn't get security context for user %s\n", pentry->pw_name); -+ goto out; -+ } -+ } -+ } -+ -+ /* -+ * 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. -+ */ -+ if (fgetfilecon(STDIN_FILENO, &file_context) < 0) -+ perr("fgetfilecon FAILED %s", filename); -+ -+ retval = security_compute_av(user_context, -+ file_context, -+ SECCLASS_FILE, -+ FILE__ENTRYPOINT, -+ &avd); -+ freecon(file_context); -+ if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT)) { -+ if (security_getenforce()==1) { -+ perr("Not allowed to set exec context to %s for user %s\n", user_context,pentry->pw_name); -+ } else { -+ syslog(LOG_ERR, "Not allowed to set exec context to %s for user %s\n", user_context,pentry->pw_name); -+ goto out; -+ } -+ } -+ -+ if (setexeccon(user_context) < 0) { -+ if (security_getenforce()==1) { ++ security_context_t user_context=NULL; ++ security_context_t file_context=NULL; ++ int retval=0; ++ struct av_decision avd; ++ char *seuser=NULL; ++ char *level=NULL; + -+ perr("Could not set exec context to %s for user %s\n", user_context,pentry->pw_name); -+ } else { -+ syslog(LOG_ERR, "Could not set exec context to %s for user %s\n", user_context,pentry->pw_name); -+ } -+ } -+ out: -+ freecon(user_context); -+ } ++ if (getseuserbyname(pentry->pw_name, &seuser, &level) == 0) { ++ retval=get_default_context_with_level(seuser, level, NULL, &user_context); ++ free(seuser); ++ free(level); ++ if (retval) { ++ if (security_getenforce()==1) { ++ perr("execle: couldn't get security context for user %s\n", pentry->pw_name); ++ } else { ++ syslog(LOG_ERR, "execle: couldn't get security context for user %s\n", pentry->pw_name); ++ goto out; ++ } ++ } ++ } ++ ++ /* ++ * 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. ++ */ ++ if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { ++ if (security_getenforce() > 0) { ++ perr("fgetfilecon FAILED %s", filename); ++ } else { ++ syslog(LOG_ERR, "fgetfilecon FAILED %s", filename); ++ goto out; ++ } ++ } ++ retval = security_compute_av(user_context, ++ file_context, ++ SECCLASS_FILE, ++ FILE__ENTRYPOINT, ++ &avd); ++ freecon(file_context); ++ if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT)) { ++ if (security_getenforce()==1) ++ perr("Not allowed to set exec context to %s for user %s\n", user_context,pentry->pw_name); ++ } ++ ++ if (setexeccon(user_context) < 0) { ++ if (security_getenforce()==1) { ++ perr("Could not set exec context to %s for user %s\n", user_context,pentry->pw_name); ++ } else { ++ syslog(LOG_ERR, "Could not set exec context to %s for user %s\n", user_context,pentry->pw_name); ++ } ++ } ++ freecon(user_context); ++ } +#endif -+ + - if (execle("/bin/sh", "sh", (char *) NULL, nenvp) != 0) -+ perr("Exec failed for /bin/sh"); - +- ++//add for fedora +#ifdef WITH_SELINUX -+ if (selinux_enabled>0) { -+ if (setexeccon(NULL) < 0) -+ if (security_getenforce()==1) -+ perr("Could not resset exec context for user %s\n", pentry->pw_name); -+ } -+ } -+#endif ++ if (selinux_enabled>0) ++ if (setexeccon(NULL) < 0) ++ if (security_getenforce()==1) ++ perr("Could not resset exec context for user %s\n", pentry->pw_name); + -+#ifdef WITH_PAM ++#endif ++//end ++//add for fedora ++#ifdef WITH_PAM + if ( ( nenvp != &nul ) && (pam_envp != 0L) && (*pam_envp != 0L)) + { + for( nenvp = pam_envp; *nenvp != 0L; nenvp++) @@ -197,13 +302,32 @@ + pam_envp=0L; + } +#endif -+ PRIV_END ++//end } /* We're the parent. Let's wait. -@@ -507,14 +651,43 @@ - unlink(filename); - } + */ +@@ -456,7 +572,7 @@ + return with an ECHILD error. + */ + waitpid(pid, (int *) NULL, 0); +- ++/* remove because WITH_PAM + #ifdef HAVE_PAM + PRIV_START + pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); +@@ -464,7 +580,7 @@ + pam_end(pamh, retcode); + PRIV_END + #endif +- ++*/ + /* Send mail. Unlink the output file after opening it, so it + * doesn't hang around after the run. + */ +@@ -472,6 +588,13 @@ + if (open(filename, O_RDONLY) != STDIN_FILENO) + perr("Open of jobfile failed"); +#ifdef WITH_PAM + pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT ); @@ -212,17 +336,17 @@ + closelog(); + openlog("atd", LOG_PID, LOG_ATD); +#endif -+ + unlink(filename); + /* The job is now finished. We can delete its input file. - */ - chdir(ATJOB_DIR); +@@ -480,8 +603,30 @@ unlink(newname); + free(newname); +#ifdef ATD_MAIL_PROGRAM if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { -- -- PRIV_START + int mail_pid = -1; ++//add for fedora +#ifdef WITH_PAM + retcode = pam_start("atd", pentry->pw_name, &conv, &pamh); + PAM_FAIL_CHECK; @@ -238,16 +362,15 @@ + closelog(); + openlog("atd", LOG_PID, LOG_ATD); +#endif -+ -+ mail_pid = fork(); -+ -+ if ( mail_pid == 0 ) -+ { -+ PRIV_START ++//end ++ mail_pid = fork(); + ++ if ( mail_pid == 0 ) ++ { + PRIV_START if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot delete saved userids"); -@@ -527,16 +700,81 @@ +@@ -495,16 +640,80 @@ chdir ("/"); @@ -258,85 +381,83 @@ - perr("No mail command specified."); +#ifdef WITH_SELINUX + if (selinux_enabled>0) { -+ security_context_t user_context=NULL; -+ security_context_t file_context=NULL; -+ int retval=0; -+ struct av_decision avd; -+ -+ if (get_default_context(pentry->pw_name, NULL, &user_context)) -+ perr("execle: couldn't get security context for user %s\n", pentry->pw_name); -+ /* -+ * 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. -+ */ -+ if (fgetfilecon(STDIN_FILENO, &file_context) < 0) -+ perr("fgetfilecon FAILED %s", filename); -+ -+ retval = security_compute_av(user_context, -+ file_context, -+ SECCLASS_FILE, -+ FILE__ENTRYPOINT, -+ &avd); -+ freecon(file_context); -+ if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT)) { -+ if (security_getenforce()==1) { -+ perr("Not allowed to set exec context to %s for user %s\n", user_context,pentry->pw_name); -+ } else { -+ syslog(LOG_ERR, "Not allowed to set exec context to %s for user %s\n", user_context,pentry->pw_name); -+ goto out; -+ } -+ } -+ -+ if (setexeccon(user_context) < 0) { -+ if (security_getenforce()==1) { -+ perr("Could not set exec context to %s for user %s\n", user_context,pentry->pw_name); -+ } else { -+ syslog(LOG_ERR, "Could not set exec context to %s for user %s\n", user_context,pentry->pw_name); -+ } -+ } -+ freecon(user_context); -+ } ++ security_context_t user_context=NULL; ++ security_context_t file_context=NULL; ++ int retval=0; ++ struct av_decision avd; ++ ++ if (get_default_context(pentry->pw_name, NULL, &user_context)) ++ perr("execle: couldn't get security context for user %s\n", pentry->pw_name); ++ /* ++ * 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. ++ */ ++ if (fgetfilecon(STDIN_FILENO, &file_context) < 0) ++ perr("fgetfilecon FAILED %s", filename); ++ ++ retval = security_compute_av(user_context, ++ file_context, ++ SECCLASS_FILE, ++ FILE__ENTRYPOINT, ++ &avd); ++ freecon(file_context); ++ if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT)) { ++ if (security_getenforce()==1) { ++ perr("Not allowed to set exec context to %s for user %s\n", user_context,pentry->pw_name); ++ } else { ++ syslog(LOG_ERR, "Not allowed to set exec context to %s for user %s\n", user_context,pentry->pw_name); ++ goto out; ++ } ++ } ++ ++ if (setexeccon(user_context) < 0) { ++ if (security_getenforce()==1) { ++ perr("Could not set exec context to %s for user %s\n", user_context,pentry->pw_name); ++ } else { ++ syslog(LOG_ERR, "Could not set exec context to %s for user %s\n", user_context,pentry->pw_name); ++ } ++ } ++ out: ++ freecon(user_context); ++ } +#endif -+ -+ execl(ATD_MAIL_PROGRAM, ATD_MAIL_NAME, mailname, (char *) NULL); -+ perr("Exec failed for mail command"); -+ exit(-1); ++ execl(ATD_MAIL_PROGRAM, ATD_MAIL_NAME, mailname, (char *) NULL); ++ perr("Exec faile for mail command"); ++ exit(-1); ++ +#ifdef WITH_SELINUX -+ if (selinux_enabled>0) { -+ if (setexeccon(NULL) < 0) -+ if (security_getenforce()==1) -+ perr("Could not resset exec context for user %s\n", pentry->pw_name); -+ } -+ } ++ if (selinux_enabled>0) ++ if (setexeccon(NULL) < 0) ++ if (security_getenforce()==1) ++ perr("Could not resset exec context for user %s\n", pentry->pw_name); #endif - perr("Exec failed for mail command"); -- PRIV_END -+ PRIV_END -+ } else -+ if ( mail_pid == -1 ) { -+ perr("fork of mailer failed"); -+ } else { -+ /* Parent */ -+ waitpid(mail_pid, (int *) NULL, 0); -+ + PRIV_END ++ } ++ else if ( mail_pid == -1 ) { ++ perr("fork of mailer failed"); ++ } ++ else { ++ /* Parent */ ++ waitpid(mail_pid, (int *) NULL, 0); ++ } +#ifdef WITH_PAM -+ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT ); -+ pam_close_session(pamh, PAM_SILENT); -+ pam_end(pamh, PAM_ABORT); -+ closelog(); -+ openlog("atd", LOG_PID, LOG_ATD); ++ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT ); ++ pam_close_session(pamh, PAM_SILENT); ++ pam_end(pamh, PAM_ABORT); ++ closelog(); ++ openlog("atd", LOG_PID, LOG_ATD); +#endif -+ } } +#endif exit(EXIT_SUCCESS); } -@@ -736,6 +974,10 @@ +@@ -702,6 +911,10 @@ struct passwd *pwe; struct group *ge; @@ -347,7 +468,7 @@ /* We don't need root privileges all the time; running under uid and gid * daemon is fine. */ -@@ -752,11 +994,7 @@ +@@ -718,18 +931,13 @@ RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) @@ -356,110 +477,74 @@ -#endif - - openlog("atd", LOG_PID, LOG_CRON); +- + openlog("atd", LOG_PID, LOG_ATD); - opterr = 0; errno = 0; ---- at-3.1.10/perm.c.pam 2005-08-05 05:16:01.000000000 +0200 -+++ at-3.1.10/perm.c 2006-09-12 15:06:30.000000000 +0200 -@@ -51,6 +51,14 @@ - #define PRIV_END while(0) - #endif + run_as_daemon = 1; + batch_interval = BATCH_INTERVAL_DEFAULT; -+#ifdef WITH_PAM -+#include -+static pam_handle_t *pamh = NULL; -+static const struct pam_conv conv = { -+ NULL -+}; -+#endif -+ - /* Structures and unions */ +- while ((c = getopt(argc, argv, "sdl:b:")) != EOF) { ++ while ((c = getopt(argc, argv, "sdl:b:n:")) != EOF) { + switch (c) { + case 'l': + if (sscanf(optarg, "%lf", &load_avg) != 1) +@@ -742,10 +950,15 @@ + if (sscanf(optarg, "%ud", &batch_interval) != 1) + pabort("garbled option -b"); + break; ++ + case 'd': + daemon_debug++; ++ /* go through another option*/ ++ ++ case 'n': ++ daemon_nofork++; + break; +- ++ + case 's': + run_as_daemon = 0; + break; +--- at-3.1.10/Makefile.in.pam 2007-07-03 13:29:24.000000000 +0200 ++++ at-3.1.10/Makefile.in 2007-07-03 13:29:24.000000000 +0200 +@@ -41,6 +41,7 @@ + LIBOBJS = @LIBOBJS@ + INSTALL = @INSTALL@ + PAMLIB = @PAMLIB@ ++SELINUXLIB = @SELINUXLIB@ + CLONES = atq atrm + ATOBJECTS = at.o panic.o perm.o y.tab.o lex.yy.o +@@ -67,13 +68,13 @@ + all: at atd atrun -@@ -109,18 +117,58 @@ - int - check_permission() - { -- uid_t uid = geteuid(); -+ uid_t euid = geteuid(), uid=getuid(), egid=getegid(), gid=getgid(); - struct passwd *pentry; - int allow = 0, deny = 1; + at: $(ATOBJECTS) +- $(CC) $(CFLAGS) -o at -pie $(ATOBJECTS) $(LIBS) $(LEXLIB) ++ $(CC) $(CFLAGS) -o at -pie $(ATOBJECTS) $(LIBS) $(LEXLIB) $(PAMLIB) + rm -f $(CLONES) + $(LN_S) -f at atq + $(LN_S) -f at atrm -- if (uid == 0) -+ int retcode=0; -+ -+ if (euid == 0) - return 1; + atd: $(RUNOBJECTS) +- $(CC) $(CFLAGS) -o atd -pie $(RUNOBJECTS) $(LIBS) $(PAMLIB) ++ $(CC) $(CFLAGS) -o atd -pie $(RUNOBJECTS) $(LIBS) $(SELINUXLIB) $(PAMLIB) -- if ((pentry = getpwuid(uid)) == NULL) { -+ if ((pentry = getpwuid(euid)) == NULL) { - perror("Cannot access user database"); - exit(EXIT_FAILURE); - } - -+#ifdef WITH_PAM -+/* -+ * We must check if the atd daemon userid will be allowed to gain the job owner user's -+ * credentials with PAM . If not, the user has been denied at(1) usage, eg. with pam_access. -+ */ -+ setreuid(daemon_uid, daemon_uid); -+ setregid(daemon_gid, daemon_gid); -+ -+# define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \ -+ fprintf(stderr,"PAM authentication failure: %s\n",pam_strerror(pamh, retcode)); \ -+ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT ); -+ pam_close_session(pamh,PAM_SILENT); \ -+ pam_end(pamh, retcode); \ -+ setregid(gid,egid); \ -+ setreuid(uid,euid); \ -+ return(0); \ -+ } -+ retcode = pam_start("atd", pentry->pw_name, &conv, &pamh); -+ PAM_FAIL_CHECK; -+ retcode = pam_set_item(pamh, PAM_TTY, "atd"); -+ PAM_FAIL_CHECK; -+ retcode = pam_acct_mgmt(pamh, PAM_SILENT); -+ PAM_FAIL_CHECK; -+ retcode = pam_open_session(pamh, PAM_SILENT); -+ PAM_FAIL_CHECK; -+ retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); -+ PAM_FAIL_CHECK; -+ -+ pam_close_session(pamh,PAM_SILENT); -+ pam_end(pamh, PAM_ABORT); -+ -+ setregid(gid,egid); -+ setreuid(uid,euid); -+ -+#endif -+ -+ -+ - allow = user_in_file(ETCDIR "/at.allow", pentry->pw_name); - if (allow==0 || allow==1) - return allow; ---- at-3.1.10/config.h.in.__ 2006-09-07 18:47:06.000000000 +0200 -+++ at-3.1.10/config.h.in 2006-09-07 18:48:12.000000000 +0200 -@@ -181,3 +181,9 @@ - - #undef HAVE_ATTRIBUTE_NORETURN - #undef HAVE_PAM -+ -+/* Define if you are building with_selinux */ -+#undef WITH_SELINUX -+ -+/* Define if you are building with_pam */ -+#undef WITH_PAM ---- at-3.1.10/configure.in._ 2005-08-05 05:16:02.000000000 +0200 -+++ at-3.1.10/configure.in 2006-09-07 16:21:19.000000000 +0200 -@@ -88,6 +88,9 @@ - if test "$ac_cv_path_SENDMAIL" != "" ; then - AC_DEFINE_UNQUOTED(SENDMAIL,"$ac_cv_path_SENDMAIL") - MAIL_CMD="$ac_cv_path_SENDMAIL" -+#AC_PATH_PROG(GETOPT, getopt, , $PATH:/bin:/usr/bin:/usr/local/bin ) -+#if test "$ac_cv_path_GETOPT" != "" ; then -+#AC_DEFINE_UNQUOTED(GETOPT,"$ac_cv_path_GETOPT") - fi - - AC_SUBST(MAIL_CMD) + y.tab.c y.tab.h: parsetime.y + $(YACC) -d parsetime.y +--- at-3.1.10/pam_atd.pam 2007-07-03 13:29:24.000000000 +0200 ++++ at-3.1.10/pam_atd 2007-07-03 13:29:24.000000000 +0200 +@@ -0,0 +1,13 @@ ++# The PAM configuration file for the at daemon ++# ++# ++auth sufficient pam_rootok.so ++auth include system-auth ++auth required pam_env.so ++account include system-auth ++session required pam_loginuid.so ++session include system-auth ++# Sets up user limits, please uncomment and read /etc/security/limits.conf ++# to enable this functionality. ++# session required pam_limits.so ++# diff --git a/at-3.1.10-perm.patch b/at-3.1.10-perm.patch index 57ea7cf..27cd5a4 100644 --- a/at-3.1.10-perm.patch +++ b/at-3.1.10-perm.patch @@ -1,29 +1,12 @@ ---- at-3.1.10/at.c.perm 2006-11-14 12:26:27.000000000 +0100 -+++ at-3.1.10/at.c 2006-11-14 12:28:15.000000000 +0100 -@@ -144,17 +144,12 @@ - */ - if (fcreated) { - /* -- PRIV_START -- - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - setregid(real_gid, effective_gid); - unlink(atfile); - setregid(effective_gid, real_gid); -- /* -- PRIV_END -- */ - } - exit(EXIT_FAILURE); - } -@@ -314,18 +309,18 @@ +--- at-3.1.10/at.c.perm 2007-07-02 15:40:35.000000000 +0200 ++++ at-3.1.10/at.c 2007-07-02 16:19:54.000000000 +0200 +@@ -314,10 +314,11 @@ * bit. Yes, this is a kluge. */ cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); - seteuid(real_uid); -+ seteuid(effective_uid); ++ //seteuid(real_uid); ++ seteuid(effective_uid); if ((fd = open(atfile, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, S_IRUSR)) == -1) perr("Cannot create atjob file %.500s", atfile); - seteuid(effective_uid); @@ -31,53 +14,3 @@ if ((fd2 = dup(fd)) < 0) perr("Error in dup() of job file"); - -- /* -+ - if (fchown(fd2, real_uid, real_gid) != 0) - perr("Cannot give away file"); -- */ -+ - - PRIV_END - -@@ -656,6 +651,7 @@ - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ -+// PRIV_START - setregid(real_gid, effective_gid); - - if (queue == '=') { -@@ -668,17 +664,17 @@ - - setregid(effective_gid, real_gid); - done = 1; -- -+// PRIV_END - break; - - case CAT: - { - FILE *fp; - int ch; -- -+ // PRIV_START - setregid(real_gid, effective_gid); - fp = fopen(dirent->d_name, "r"); -- -+ // PRIV_END - if (fp) { - while ((ch = getc(fp)) != EOF) { - putchar(ch); ---- at-3.1.10/Makefile.in.perm 2006-11-14 12:26:27.000000000 +0100 -+++ at-3.1.10/Makefile.in 2006-11-14 12:26:27.000000000 +0100 -@@ -97,7 +97,7 @@ - $(INSTALL) -m 755 -d $(IROOT)$(atdocdir) - $(INSTALL) -m 755 -d $(IROOT)$(ATJOB_DIR) - $(INSTALL) -m 755 -d $(IROOT)$(etcdir)/pam.d -- $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT) $(ATSPOOL_DIR) -+ $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT)$(ATSPOOL_DIR) - chmod 700 $(IROOT)$(ATSPOOL_DIR) $(IROOT)$(ATJOB_DIR) - touch $(IROOT)$(LFILE) - chmod 600 $(IROOT)$(LFILE) diff --git a/at-3.1.8-t_option.patch b/at-3.1.8-t_option.patch index 0bd4e8e..22f7ac5 100644 --- a/at-3.1.8-t_option.patch +++ b/at-3.1.8-t_option.patch @@ -1,41 +1,18 @@ ---- at-3.1.10/at.1.in.t_opti 2006-09-12 12:48:04.000000000 +0200 -+++ at-3.1.10/at.1.in 2006-09-12 12:45:40.000000000 +0200 -@@ -12,6 +12,16 @@ - .RB [ -mldbv ] - .B TIME - .br -+.B at -+.RB [ -V ] -+.RB [ -q -+.IR queue ] -+.RB [ -f -+.IR file ] -+.RB [ -mldbv ] -+.RB -t -+.IR time_arg -+.br - .B "at -c" - .I job - .RI [ job... ] -@@ -227,6 +237,15 @@ - .B - \-c - cats the jobs listed on the command line to standard output. -+.TP -+.BI \-t " time_arg" -+Submit the job to be run at the time specified by the -+.BI time_arg -+option argument, which must have the same format as specified for the -+.BR touch(1) -+utility's -+.B -t -+time option argument ([[CC]YY]MMDDhhmm). - .SH FILES - .I @ATJBD@ - .br ---- at-3.1.10/at.c.t_ 2006-09-12 10:15:56.000000000 +0200 -+++ at-3.1.10/at.c 2006-09-12 10:30:17.000000000 +0200 -@@ -750,6 +750,101 @@ +--- at-3.1.10/at.c.t_option 2007-06-28 14:43:51.000000000 +0200 ++++ at-3.1.10/at.c 2007-06-28 14:54:04.000000000 +0200 +@@ -396,8 +396,9 @@ + unsigned int i; + for (i = 0; i < sizeof(no_export) / sizeof(no_export[0]); i++) { + export = export +- && (strncmp(*atenv, no_export[i], +- (size_t) (eqp - *atenv)) != 0); ++ && ( (((size_t) (eqp - *atenv)) != strlen(no_export[i])) ++ ||(strncmp(*atenv, no_export[i],(size_t) (eqp - *atenv)) != 0) ++ ); + } + eqp++; + } +@@ -752,6 +753,102 @@ return p; } @@ -126,8 +103,9 @@ + + if( tm.tm_mday ) + { -+ tm.tm_isdst = tm_now.tm_isdst; -+ return mktime(&tm); ++ tm.tm_isdst = -1; ++ t = mktime(&tm); ++ return t; + } else + return 0L; +} @@ -137,3 +115,136 @@ int main(int argc, char **argv) { +@@ -761,9 +858,9 @@ + char *pgm; + + int program = AT; /* our default program */ +- char *options = "q:f:MmvldhVc"; /* default options for at */ ++ char *options = "q:f:MmvldhVct:"; /* default options for at */ + int disp_version = 0; +- time_t timer; ++ time_t timer=0L; + struct passwd *pwe; + struct group *ge; + +@@ -866,7 +963,9 @@ + program = CAT; + options = ""; + break; +- ++ case 't': ++ timer = t_option(optarg); ++ break; + default: + usage(); + break; +@@ -955,10 +1054,12 @@ + else + queue = DEFAULT_BATCH_QUEUE; + +- if (argc > optind) +- timer = parsetime(argc, argv); +- else +- timer = time(NULL); ++ if( timer == 0L ) { ++ if (argc > optind) ++ timer = parsetime(argc, argv); ++ else ++ timer = time(NULL); ++ } + + if (atverify) { + struct tm *tm = localtime(&timer); +--- at-3.1.10/at.1.in.t_option 2007-06-28 14:43:51.000000000 +0200 ++++ at-3.1.10/at.1.in 2007-06-28 14:43:51.000000000 +0200 +@@ -12,6 +12,16 @@ + .RB [ -mldbv ] + .B TIME + .br ++.B at ++.RB [ -V ] ++.RB [ -q ++.IR queue ] ++.RB [ -f ++.IR file ] ++.RB [ -mldbv ] ++.RB -t ++.IR time_arg ++.br + .B "at -c" + .I job + .RI [ job... ] +@@ -32,8 +42,7 @@ + and + .B batch + read commands from standard input or a specified file which are to +-be executed at a later time, using +-.BR /bin/sh . ++be executed at a later time. + .TP 8 + .BR at + executes commands at a specified time. +@@ -227,6 +236,63 @@ + .B + \-c + cats the jobs listed on the command line to standard output. ++.TP ++.BI \-t " time_arg" ++Submit the job to be run at the time specified by the ++.BI time_arg ++option argument, which must have the same format as specified for the ++.BR touch(1) ++utility's ++.B \-t ++time option argument ([[CC]YY]MMDDhhmm). ++.SH ENVIRONMENT ++.P ++.TP 8 ++.B SHELL ++The value of the SHELL environment variable at the time of ++.B at ++invocation will determine which shell is used to execute the ++.B at ++job commands. If SHELL is unset when ++.B at ++is invoked, the user's login shell will be used; otherwise, ++if SHELL is set when ++.B at ++is invoked, it must contain the path of a shell interpreter ++executable that will be used to run the commands at the specified time. ++.P ++.B at ++will record the values of ++environment variables present at time of ++.B at ++invocation. When the commands are run at the specified time, ++.B at ++will restore these variables to their recorded values . ++These variables are excluded from this processing and are never ++set by ++.B at ++when the commands are run : ++.br ++.BI TERM, ++.BI DISPLAY, ++.BI SHELLOPTS, ++.BI _, ++.BI PPID, ++.BI BASH_VERSINFO, ++.BI EUID, ++.BI UID, ++.BI GROUPS. ++.br ++If the user submitting the ++.B at ++job is not the super-user, variables that alter the behaviour of the ++loader ++.BR ld.so(8), ++such as ++.B LD_LIBRARY_PATH ++, cannot be recorded and restored by ++.B at . ++.P + .SH FILES + .I @ATJBD@ + .br diff --git a/at.spec b/at.spec index 90e2259..40a2a3c 100644 --- a/at.spec +++ b/at.spec @@ -68,10 +68,9 @@ cp %{SOURCE1} . #%patch8 -p1 -b .instinet #unlink unsucessful jobs, removed -> atd crash %patch9 -p1 -b .shell %patch11 -p1 -b .t_option -%patch12 -p1 -b .usage %patch14 -p1 -b .pam %patch15 -p1 -b .dont_fork -#%patch21 -p1 -b .perm +%patch21 -p1 -b .perm %build # patch10 touches configure.in