Browse Source

Merge remote-tracking branch 'origin/freebsd/current/master' into hardened/current/master

Conflicts:
	bin/pwait/pwait.c (unresolved)
hardened/current/master
Shawn Webb 8 months ago
parent
commit
26fc9a3de4
Signed by untrusted user: shawn.webb <shawn.webb@hardenedbsd.org> GPG Key ID: FF2E67A277F8E1FA
6 changed files with 156 additions and 43 deletions
  1. +4
    -2
      bin/pwait/pwait.1
  2. +65
    -27
      bin/pwait/pwait.c
  3. +80
    -0
      bin/pwait/tests/pwait_test.sh
  4. +1
    -14
      sys/kern/vfs_default.c
  5. +3
    -0
      sys/kern/vfs_subr.c
  6. +3
    -0
      tests/sys/kern/ptrace_test.c

+ 4
- 2
bin/pwait/pwait.1 View File

@@ -32,7 +32,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 7, 2017
.Dd January 26, 2020
.Dt PWAIT 1
.Os
.Sh NAME
@@ -41,7 +41,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl t Ar duration
.Op Fl v
.Op Fl ov
.Ar pid
\&...
.Sh DESCRIPTION
@@ -51,6 +51,8 @@ utility will wait until each of the given processes has terminated.
.Pp
The following option is available:
.Bl -tag -width indent
.It Fl o
Exit when any of the given processes has terminated.
.It Fl t Ar duration
If any process is still running after
.Ar duration ,


+ 65
- 27
bin/pwait/pwait.c View File

@@ -53,8 +53,7 @@ static void
usage(void)
{

fprintf(stderr, "usage: pwait [-t timeout] [-v] pid ...\n");
exit(EX_USAGE);
errx(EX_USAGE, "usage: pwait [-t timeout] [-ov] pid ...");
}

/*
@@ -64,26 +63,31 @@ int
main(int argc, char *argv[])
{
struct itimerval itv;
int kq;
struct kevent *e;
int tflag, verbose;
int opt, nleft, n, i, duplicate, status;
int oflag, tflag, verbose;
int i, kq, n, nleft, opt, status;
long pid;
char *s, *end;
char *end, *s;
double timeout;
pid_t me;

tflag = verbose = 0;
oflag = 0;
tflag = 0;
verbose = 0;
memset(&itv, 0, sizeof(itv));
while ((opt = getopt(argc, argv, "t:v")) != -1) {

while ((opt = getopt(argc, argv, "ot:v")) != -1) {
switch (opt) {
case 'o':
oflag = 1;
break;
case 't':
tflag = 1;
errno = 0;
timeout = strtod(optarg, &end);
if (end == optarg || errno == ERANGE ||
timeout < 0)
if (end == optarg || errno == ERANGE || timeout < 0) {
errx(EX_DATAERR, "timeout value");
}
switch(*end) {
case 0:
case 's':
@@ -97,8 +101,9 @@ main(int argc, char *argv[])
default:
errx(EX_DATAERR, "timeout unit");
}
if (timeout > 100000000L)
if (timeout > 100000000L) {
errx(EX_DATAERR, "timeout value");
}
itv.it_value.tv_sec = (time_t)timeout;
timeout -= (time_t)timeout;
itv.it_value.tv_usec =
@@ -116,29 +121,35 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;

if (argc == 0)
if (argc == 0) {
usage();
}

me = getpid();

kq = kqueue();
if (kq == -1)
err(1, "kqueue");
if (kq == -1) {
err(EX_OSERR, "kqueue");
}

e = malloc((argc + tflag) * sizeof(struct kevent));
if (e == NULL)
err(1, "malloc");
if (e == NULL) {
err(EX_OSERR, "malloc");
}
nleft = 0;
for (n = 0; n < argc; n++) {
s = argv[n];
if (!strncmp(s, "/proc/", 6)) /* Undocumented Solaris compat */
/* Undocumented Solaris compat */
if (!strncmp(s, "/proc/", 6)) {
s += 6;
}
errno = 0;
pid = strtol(s, &end, 10);
if (pid < 0 || *end != '\0' || errno != 0) {
warnx("%s: bad process id", s);
continue;
}
<<<<<<< HEAD
if (pid == me) {
warnx("%s: ignoring own process id", s);
continue;
@@ -154,45 +165,72 @@ main(int argc, char *argv[])
warn("%ld", pid);
else
nleft++;
=======
for (i = 0; i < nleft; i++) {
if (e[i].ident == (uintptr_t)pid) {
break;
}
}
if (i < nleft) {
/* Duplicate. */
continue;
}
EV_SET(e + nleft, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) {
warn("%ld", pid);
if (oflag) {
exit(EX_OK);
}
} else {
nleft++;
>>>>>>> origin/freebsd/current/master
}
}

if (tflag) {
if (nleft > 0 && tflag) {
/*
* Explicitly detect SIGALRM so that an exit status of 124
* can be returned rather than 142.
*/
EV_SET(e + nleft, SIGALRM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1)
if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) {
err(EX_OSERR, "kevent");
}
/* Ignore SIGALRM to not interrupt kevent(2). */
signal(SIGALRM, SIG_IGN);
if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
err(EX_OSERR, "setitimer");
}
}
while (nleft > 0) {
n = kevent(kq, NULL, 0, e, nleft + tflag, NULL);
if (n == -1)
err(1, "kevent");
if (n == -1) {
err(EX_OSERR, "kevent");
}
for (i = 0; i < n; i++) {
if (e[i].filter == EVFILT_SIGNAL) {
if (verbose)
if (verbose) {
printf("timeout\n");
return (124);
}
exit(124);
}
if (verbose) {
status = e[i].data;
if (WIFEXITED(status))
if (WIFEXITED(status)) {
printf("%ld: exited with status %d.\n",
(long)e[i].ident,
WEXITSTATUS(status));
else if (WIFSIGNALED(status))
} else if (WIFSIGNALED(status)) {
printf("%ld: killed by signal %d.\n",
(long)e[i].ident,
WTERMSIG(status));
else
} else {
printf("%ld: terminated.\n",
(long)e[i].ident);
}
}
if (oflag) {
exit(EX_OK);
}
--nleft;
}


+ 80
- 0
bin/pwait/tests/pwait_test.sh View File

@@ -232,6 +232,85 @@ timeout_many_cleanup()
wait $p1 $p5 $p10 >/dev/null 2>&1
}

atf_test_case or_flag
or_flag_head()
{
atf_set "descr" "Test OR flag"
}

or_flag_body()
{
sleep 2 &
p2=$!

sleep 4 &
p4=$!

sleep 6 &
p6=$!

atf_check \
-o inline:"$p2: exited with status 0.\n" \
-e empty \
-s exit:0 \
timeout --preserve-status 15 pwait -o -v $p2 $p4 $p6

atf_check \
-o empty \
-e inline:"pwait: $p2: No such process\n" \
-s exit:0 \
timeout --preserve-status 15 pwait -o $p2 $p4 $p6

atf_check \
-o empty \
-e empty \
-s exit:0 \
timeout --preserve-status 15 pwait -o $p4 $p6

atf_check \
-o empty \
-e inline:"pwait: $p4: No such process\n" \
-s exit:0 \
timeout --preserve-status 15 pwait -o $p4 $p6

atf_check \
-o inline:"$p6: exited with status 0.\n" \
-e empty \
-s exit:0 \
timeout --preserve-status 15 pwait -o -v $p6

atf_check \
-o empty \
-e inline:"pwait: $p6: No such process\n" \
-s exit:0 \
timeout --preserve-status 15 pwait -o $p6

atf_check \
-o empty \
-e inline:"kill: $p2: No such process\n" \
-s exit:1 \
kill -0 $p2

atf_check \
-o empty \
-e inline:"kill: $p4: No such process\n" \
-s exit:1 \
kill -0 $p4

atf_check \
-o empty \
-e inline:"kill: $p6: No such process\n" \
-s exit:1 \
kill -0 $p6

}

or_flag_cleanup()
{
kill $p2 $p4 $p6 >/dev/null 2>&1
wait $p2 $p4 $p6 >/dev/null 2>&1
}

atf_init_test_cases()
{
atf_add_test_case basic
@@ -239,4 +318,5 @@ atf_init_test_cases()
atf_add_test_case timeout_trigger_timeout
atf_add_test_case timeout_no_timeout
atf_add_test_case timeout_many
atf_add_test_case or_flag
}

+ 1
- 14
sys/kern/vfs_default.c View File

@@ -1450,20 +1450,7 @@ vop_sigdefer(struct vop_vector *vop, struct vop_generic_args *a)
vop_bypass_t *bp;
int prev_stops, rc;

for (; vop != NULL; vop = vop->vop_default) {
bp = bp_by_off(vop, a);
if (bp != NULL)
break;

/*
* Bypass is not really supported. It is done for
* fallback to unimplemented vops in the default
* vector.
*/
bp = vop->vop_bypass;
if (bp != NULL)
break;
}
bp = bp_by_off(vop, a);
MPASS(bp != NULL);

prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);


+ 3
- 0
sys/kern/vfs_subr.c View File

@@ -6368,6 +6368,9 @@ __mnt_vnode_first_lazy(struct vnode **mvp, struct mount *mp, mnt_lazy_cb_t *cb,
{
struct vnode *vp;

if (TAILQ_EMPTY(&mp->mnt_lazyvnodelist))
return (NULL);

*mvp = vn_alloc_marker(mp);
MNT_ILOCK(mp);
MNT_REF(mp);


+ 3
- 0
tests/sys/kern/ptrace_test.c View File

@@ -4189,6 +4189,9 @@ ATF_TC_BODY(ptrace__procdesc_reparent_wait_child, tc)
pid_t traced, debuger, wpid;
int pd, status;

if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
atf_tc_skip("https://bugs.freebsd.org/243605");

traced = pdfork(&pd, 0);
ATF_REQUIRE(traced >= 0);
if (traced == 0) {


Loading…
Cancel
Save