changeset 13372:dd80b2e7fda4

864 at(1) should not popen /usr/bin/pwd Reviewed by: Garrett D'Amore <garrett@nexenta.com> Reviewed by: Albert Lee <trisk@nexenta.com> Approved by: Gordon Ross <gwr@nexenta.com>
author Gary Mills <mills@cc.umanitoba.ca>
date Sun, 15 May 2011 13:49:21 -0500
parents ac51c74a855d
children d8a063b9ccba
files usr/src/cmd/cron/at.c
diffstat 1 files changed, 19 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/cron/at.c	Tue May 10 14:20:12 2011 -0400
+++ b/usr/src/cmd/cron/at.c	Sun May 15 13:49:21 2011 -0500
@@ -20,6 +20,8 @@
  */
 
 /*
+ * Copyright (c) 2011 Gary Mills
+ *
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -71,6 +73,7 @@
 #define	WARNSHELL	"commands will be executed using %s\n"
 #define	CANTCD		"can't change directory to the at directory"
 #define	CANTCHOWN	"can't change the owner of your job to you"
+#define	CANTCHUID	"can't change user identifier"
 #define	CANTCREATE	"can't create a job for you"
 #define	INVALIDUSER	"you are not a valid user (no entry in /etc/passwd)"
 #define	NOOPENDIR	"can't open the at directory"
@@ -85,10 +88,6 @@
 
 #define	FORMAT		"%a %b %e %H:%M:%S %Y"
 
-/* Macros used in format for fscanf */
-#define	AQ(x)		#x
-#define	BUFFMT(p)		AQ(p)
-
 static int leap(int);
 static int atoi_for2(char *);
 static int check_queue(char *, int);
@@ -554,7 +553,6 @@
 {
 	int c;
 	FILE *pfp;
-	FILE *xfp;
 	char *shell;
 	char	dirbuf[PATH_MAX + 1];
 	char	line[LINE_MAX];
@@ -562,9 +560,7 @@
 	mode_t um;
 	char *val;
 	extern char **environ;
-	int pfd[2];
-	pid_t pid;
-	uid_t realusr;
+	uid_t realusr, effeusr;
 	int ttyinput;
 	int ulimit_flag = 0;
 	struct rlimit rlp;
@@ -664,40 +660,25 @@
 			goto out;
 		case 'd':
 			/*
-			 * fork off a child with submitter's permissions,
-			 * otherwise, when IFS=/, /usr/bin/pwd would be parsed
-			 * by the shell as file "bin".  The shell would
-			 * then search according to the submitter's PATH
-			 * and run the file bin with root permission
+			 * Must obtain current working directory as the user
 			 */
 
-			(void) fflush(stdout);
-			dirbuf[0] = NULL;
-			if (pipe(pfd) != 0)
-				atabort("pipe open failed");
-			realusr = getuid(); /* get realusr before the fork */
-			if ((pid = fork()) == (pid_t)-1)
-				atabort("fork failed");
-			if (pid == 0) {			/* child process */
-				(void) close(pfd[0]);
-				/* remove setuid for pwd */
-				(void) setuid(realusr);
-				if ((xfp = popen("/usr/bin/pwd", "r"))
-				    != NULL) {
-					fscanf(xfp, "%" BUFFMT(PATH_MAX) "s",
-					    dirbuf);
-					(void) pclose(xfp);
-					xfp = fdopen(pfd[1], "w");
-					fprintf(xfp, "%s", dirbuf);
-					(void) fclose(xfp);
-				}
-				_exit(0);
+			dirbuf[0] = '\0';
+			realusr = getuid();
+			effeusr = geteuid();
+			/* change euid for getcwd */
+			if (seteuid(realusr) < 0) {
+				atabort(CANTCHUID);
 			}
-			(void) close(pfd[1]);		/* parent process */
-			xfp = fdopen(pfd[0], "r");
-			fscanf(xfp, "%" BUFFMT(PATH_MAX) "s", dirbuf);
+			if (getcwd(dirbuf, sizeof (dirbuf)) == NULL) {
+				atabort(
+				    "can't obtain current working directory");
+			}
+			/* change back afterwards */
+			if (seteuid(effeusr) < 0) {
+				atabort(CANTCHUID);
+			}
 			printf("%s", dirbuf);
-			(void) fclose(xfp);
 			break;
 		case 'm':
 			printf("%o", um);