git: d2c233176f44 - main - sh: Add -o verify to use O_VERIFY when sourcing scripts

Wojciech Macek wma at FreeBSD.org
Thu Sep 23 08:43:28 UTC 2021


The branch main has been updated by wma:

URL: https://cgit.FreeBSD.org/src/commit/?id=d2c233176f44944ef3ed941a60010839340c06a7

commit d2c233176f44944ef3ed941a60010839340c06a7
Author:     Stephane Rochoy <stephane.rochoy at stormshield.eu>
AuthorDate: 2021-09-23 08:40:59 +0000
Commit:     Wojciech Macek <wma at FreeBSD.org>
CommitDate: 2021-09-23 08:43:09 +0000

    sh: Add -o verify to use O_VERIFY when sourcing scripts
    
    Add -o verify to sh to make it use O_VERIFY when
    sourcing scripts and reading profiles.
    
    Useful in conjunction with mac_veriexec to help protect at
    least some parts of the boot sequence, e.g., /etc/rc*.
    
    Differential revision:  https://reviews.freebsd.org/D30464
    Reviewed by:            jilles, sjg
    Obtained from:          Stormshield
---
 bin/sh/exec.c     |  2 +-
 bin/sh/histedit.c |  2 +-
 bin/sh/input.c    | 12 ++++++++++--
 bin/sh/input.h    |  2 +-
 bin/sh/main.c     | 12 ++++++++----
 bin/sh/main.h     |  2 +-
 bin/sh/options.c  |  2 +-
 bin/sh/options.h  |  4 +++-
 bin/sh/sh.1       |  5 +++++
 9 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index e3779b097e1d..43095a252a35 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -418,7 +418,7 @@ find_command(const char *name, struct cmdentry *entry, int act,
 		if (!S_ISREG(statb.st_mode))
 			continue;
 		if (opt) {		/* this is a %func directory */
-			readcmdfile(fullname);
+			readcmdfile(fullname, -1 /* verify */);
 			if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
 				error("%s not defined in %s", name, fullname);
 			stunalloc(fullname);
diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index 96511b87b451..3c113333f4c8 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -447,7 +447,7 @@ histcmd(int argc, char **argv __unused)
 		editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
 		sprintf(editcmd, "%s %s", editor, editfile);
 		evalstring(editcmd, 0);	/* XXX - should use no JC command */
-		readcmdfile(editfile);	/* XXX - should read back - quick tst */
+		readcmdfile(editfile, 0 /* verify */);	/* XXX - should read back - quick tst */
 		unlink(editfile);
 	}
 
diff --git a/bin/sh/input.c b/bin/sh/input.c
index a8d048fc4890..3933287524a4 100644
--- a/bin/sh/input.c
+++ b/bin/sh/input.c
@@ -352,17 +352,25 @@ popstring(void)
 /*
  * Set the input to take input from a file.  If push is set, push the
  * old input onto the stack first.
+ * About verify:
+ *   -1: Obey verifyflag
+ *    0: Do not verify
+ *    1: Do verify
  */
 
 void
-setinputfile(const char *fname, int push)
+setinputfile(const char *fname, int push, int verify)
 {
 	int e;
 	int fd;
 	int fd2;
+	int oflags = O_RDONLY | O_CLOEXEC;
+
+	if (verify == 1 || (verify == -1 && verifyflag))
+		oflags |= O_VERIFY;
 
 	INTOFF;
-	if ((fd = open(fname, O_RDONLY | O_CLOEXEC)) < 0) {
+	if ((fd = open(fname, oflags)) < 0) {
 		e = errno;
 		errorwithstatus(e == ENOENT || e == ENOTDIR ? 127 : 126,
 		    "cannot open %s: %s", fname, strerror(e));
diff --git a/bin/sh/input.h b/bin/sh/input.h
index 71046b9731c3..edb622b6ec2e 100644
--- a/bin/sh/input.h
+++ b/bin/sh/input.h
@@ -53,7 +53,7 @@ int preadbuffer(void);
 int preadateof(void);
 void pungetc(void);
 void pushstring(const char *, int, struct alias *);
-void setinputfile(const char *, int);
+void setinputfile(const char *, int, int);
 void setinputfd(int, int);
 void setinputstring(const char *, int);
 void popfile(void);
diff --git a/bin/sh/main.c b/bin/sh/main.c
index b0a5fac6fd4e..bc87440807b2 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -253,12 +253,16 @@ read_profile(const char *name)
 {
 	int fd;
 	const char *expandedname;
+	int oflags = O_RDONLY | O_CLOEXEC;
+
+	if (verifyflag)
+		oflags |= O_VERIFY;
 
 	expandedname = expandstr(name);
 	if (expandedname == NULL)
 		return;
 	INTOFF;
-	if ((fd = open(expandedname, O_RDONLY | O_CLOEXEC)) >= 0)
+	if ((fd = open(expandedname, oflags)) >= 0)
 		setinputfd(fd, 1);
 	INTON;
 	if (fd < 0)
@@ -274,9 +278,9 @@ read_profile(const char *name)
  */
 
 void
-readcmdfile(const char *name)
+readcmdfile(const char *name, int verify)
 {
-	setinputfile(name, 1);
+	setinputfile(name, 1, verify);
 	cmdloop(0);
 	popfile();
 }
@@ -331,7 +335,7 @@ dotcmd(int argc, char **argv)
 	filename = argc > 2 && strcmp(argv[1], "--") == 0 ? argv[2] : argv[1];
 
 	fullname = find_dot_file(filename);
-	setinputfile(fullname, 1);
+	setinputfile(fullname, 1, -1 /* verify */);
 	commandname = fullname;
 	cmdloop(0);
 	popfile();
diff --git a/bin/sh/main.h b/bin/sh/main.h
index ff0a1c61fa22..d12c7ab77fed 100644
--- a/bin/sh/main.h
+++ b/bin/sh/main.h
@@ -39,4 +39,4 @@ extern int rootpid;	/* pid of main shell */
 extern int rootshell;	/* true if we aren't a child of the main shell */
 extern struct jmploc main_handler;	/* top level exception handler */
 
-void readcmdfile(const char *);
+void readcmdfile(const char *, int);
diff --git a/bin/sh/options.c b/bin/sh/options.c
index 73d79ca9a74f..97171d32bff1 100644
--- a/bin/sh/options.c
+++ b/bin/sh/options.c
@@ -112,7 +112,7 @@ procargs(int argc, char **argv)
 	arg0 = argv[0];
 	if (sflag == 0 && minusc == NULL) {
 		scriptname = *argptr++;
-		setinputfile(scriptname, 0);
+		setinputfile(scriptname, 0, -1 /* verify */);
 		commandname = arg0 = scriptname;
 	}
 	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
diff --git a/bin/sh/options.h b/bin/sh/options.h
index 500d4ad5a903..7c9c4513aa33 100644
--- a/bin/sh/options.h
+++ b/bin/sh/options.h
@@ -68,9 +68,10 @@ struct shparam {
 #define	hflag optval[18]
 #define	nologflag optval[19]
 #define	pipefailflag optval[20]
+#define	verifyflag optval[21]
 
 #define NSHORTOPTS	19
-#define NOPTS		21
+#define NOPTS		22
 
 extern char optval[NOPTS];
 extern const char optletter[NSHORTOPTS];
@@ -99,6 +100,7 @@ static const unsigned char optname[] =
 	"\010trackall"
 	"\005nolog"
 	"\010pipefail"
+	"\006verify"
 ;
 #endif
 
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index ca3faeff13af..c49230133f9f 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -355,6 +355,11 @@ if a command such as
 in the pipeline terminates with status 0 without reading its
 input completely.
 This option only has a long name.
+.It Li verify
+Set
+.Dv O_VERIFY
+when sourcing files or loading profiles. See also
+.Xr mac_veriexec 4 .
 .El
 .Pp
 The


More information about the dev-commits-src-all mailing list