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
This commit is contained in:
Stephane Rochoy 2021-09-23 10:40:59 +02:00 committed by Wojciech Macek
parent 90f6610b19
commit d2c233176f
9 changed files with 31 additions and 12 deletions

View file

@ -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);

View file

@ -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);
}

View file

@ -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));

View file

@ -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);

View file

@ -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();

View file

@ -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);

View file

@ -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... */

View file

@ -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

View file

@ -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