From d2c233176f44944ef3ed941a60010839340c06a7 Mon Sep 17 00:00:00 2001 From: Stephane Rochoy Date: Thu, 23 Sep 2021 10:40:59 +0200 Subject: 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 -- cgit v1.2.3