aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/kyua/utils/fs/directory.cpp18
-rw-r--r--crypto/krb5/src/lib/crypto/builtin/aes/aestab.h17
-rw-r--r--include/dirent.h3
-rw-r--r--lib/libarchive/config_freebsd.h1
-rw-r--r--lib/libc/gen/readdir.c2
-rw-r--r--libexec/rc/rc.subr4
-rw-r--r--libexec/rc/tests/rc_subr_test.sh29
-rw-r--r--sys/kern/vfs_inotify.c71
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_hostres/hostres_swinstalled_tbl.c2
9 files changed, 101 insertions, 46 deletions
diff --git a/contrib/kyua/utils/fs/directory.cpp b/contrib/kyua/utils/fs/directory.cpp
index f82fe88f86dc..b73741aa544d 100644
--- a/contrib/kyua/utils/fs/directory.cpp
+++ b/contrib/kyua/utils/fs/directory.cpp
@@ -127,16 +127,9 @@ struct utils::fs::detail::directory_iterator::impl : utils::noncopyable {
/// not. A null pointer means an invalid iterator.
::DIR* _dirp;
- /// Raw representation of the system directory entry.
- ///
- /// We need to keep this at the class level so that we can use the
- /// readdir_r(3) function.
- ::dirent _dirent;
-
/// Custom representation of the directory entry.
///
- /// This is separate from _dirent because this is the type we return to the
- /// user. We must keep this as a pointer so that we can support the common
+ /// We must keep this as a pointer so that we can support the common
/// operators (* and ->) over iterators.
std::unique_ptr< directory_entry > _entry;
@@ -192,22 +185,23 @@ struct utils::fs::detail::directory_iterator::impl : utils::noncopyable {
/// It is possible to use this function on a new directory_entry object to
/// initialize the first entry.
///
- /// \throw system_error If the call to readdir_r fails.
+ /// \throw system_error If the call to readdir fails.
void
next(void)
{
::dirent* result;
- if (::readdir_r(_dirp, &_dirent, &result) == -1) {
+ errno = 0;
+ if ((result = ::readdir(_dirp)) == NULL && errno != 0) {
const int original_errno = errno;
- throw fs::system_error(F("readdir_r(%s) failed") % _path,
+ throw fs::system_error(F("readdir(%s) failed") % _path,
original_errno);
}
if (result == NULL) {
_entry.reset();
close();
} else {
- _entry.reset(new directory_entry(_dirent.d_name));
+ _entry.reset(new directory_entry(result->d_name));
}
}
};
diff --git a/crypto/krb5/src/lib/crypto/builtin/aes/aestab.h b/crypto/krb5/src/lib/crypto/builtin/aes/aestab.h
index 8fe32d1800d6..87d7097ba0ec 100644
--- a/crypto/krb5/src/lib/crypto/builtin/aes/aestab.h
+++ b/crypto/krb5/src/lib/crypto/builtin/aes/aestab.h
@@ -86,10 +86,11 @@ extern "C" {
# define EXTERN extern
#endif
+/* Renamed from ALIGN in MIT source to avoid a conflict with machine/param.h */
#if defined(_MSC_VER) && defined(TABLE_ALIGN)
-#define ALIGN __declspec(align(TABLE_ALIGN))
+#define AES_ALIGN __declspec(align(TABLE_ALIGN))
#else
-#define ALIGN
+#define AES_ALIGN
#endif
#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 )
@@ -99,13 +100,13 @@ extern "C" {
#endif
#if defined(DO_TABLES) && defined(STATIC_TABLES)
-#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e)
-#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) }
-EXTERN ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH] = rc_data(w0);
+#define d_1(t,n,b,e) EXTERN AES_ALIGN CONST XP_DIR t n[256] = b(e)
+#define d_4(t,n,b,e,f,g,h) EXTERN AES_ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) }
+EXTERN AES_ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH] = rc_data(w0);
#else
-#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256]
-#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256]
-EXTERN ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH];
+#define d_1(t,n,b,e) EXTERN AES_ALIGN CONST XP_DIR t n[256]
+#define d_4(t,n,b,e,f,g,h) EXTERN AES_ALIGN CONST XP_DIR t n[4][256]
+EXTERN AES_ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH];
#endif
#if defined( SBX_SET )
diff --git a/include/dirent.h b/include/dirent.h
index dff0e8675722..7fcdceb10b23 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -116,7 +116,8 @@ DIR *fdopendir(int);
struct dirent *
readdir(DIR *);
#if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE >= 500
-int readdir_r(DIR *, struct dirent *, struct dirent **);
+int readdir_r(DIR *, struct dirent *, struct dirent **)
+ __deprecated1("Does not take variable {NAME_MAX} into account");
#endif
void rewinddir(DIR *);
#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 700
diff --git a/lib/libarchive/config_freebsd.h b/lib/libarchive/config_freebsd.h
index a3a0216169bf..1601adddd0de 100644
--- a/lib/libarchive/config_freebsd.h
+++ b/lib/libarchive/config_freebsd.h
@@ -165,7 +165,6 @@
#define HAVE_POSIX_SPAWNP 1
#define HAVE_PTHREAD_H 1
#define HAVE_PWD_H 1
-#define HAVE_READDIR_R 1
#define HAVE_READLINK 1
#define HAVE_READLINKAT 1
#ifndef __linux__
diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c
index b70102954df1..94d2b2e8d877 100644
--- a/lib/libc/gen/readdir.c
+++ b/lib/libc/gen/readdir.c
@@ -134,3 +134,5 @@ __readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
}
__strong_reference(__readdir_r, readdir_r);
+__warn_references(readdir_r,
+ "warning: this program uses readdir_r(), which is unsafe.");
diff --git a/libexec/rc/rc.subr b/libexec/rc/rc.subr
index a2e2e98a5087..06b1bd51384c 100644
--- a/libexec/rc/rc.subr
+++ b/libexec/rc/rc.subr
@@ -800,7 +800,7 @@ wait_for_pids()
fi
_prefix=
while true; do
- _nlist="";
+ _nlist=""
for _j in $_list; do
if kill -0 $_j 2>/dev/null; then
_nlist="${_nlist}${_nlist:+ }$_j"
@@ -813,7 +813,7 @@ wait_for_pids()
_list=$_nlist
echo -n ${_prefix:-"Waiting for PIDS: "}$_list
_prefix=", "
- pwait $_list 2>/dev/null
+ pwait -o $_list 2>/dev/null
done
if [ -n "$_prefix" ]; then
echo "."
diff --git a/libexec/rc/tests/rc_subr_test.sh b/libexec/rc/tests/rc_subr_test.sh
index 9931389e7a02..fe6d3b8264c9 100644
--- a/libexec/rc/tests/rc_subr_test.sh
+++ b/libexec/rc/tests/rc_subr_test.sh
@@ -1,7 +1,8 @@
+#-
+# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright 2022 Mateusz Piotrowski <0mp@FreeBSD.org>
-#
-# SPDX-License-Identifier: BSD-2-Clause
+# Copyright (c) 2025 Klara, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -104,8 +105,32 @@ oomprotect_yes_body()
/bin/sh "$__script" "$__name" "$__pidfile" onestop
}
+atf_test_case wait_for_pids_progress
+wait_for_pids_progress_head()
+{
+ atf_set "descr" "Verify that wait_for_pids prints progress updates"
+}
+wait_for_pids_progress_body()
+{
+ cat >>script <<'EOF'
+. /etc/rc.subr
+sleep 15 &
+a=$!
+sleep 10 &
+b=$!
+sleep 5 &
+c=$!
+wait_for_pids $a $b $c
+EOF
+ re="^Waiting for PIDS: [0-9]+ [0-9]+ [0-9]+"
+ re="${re}, [0-9]+ [0-9]+"
+ re="${re}, [0-9]+\.$"
+ atf_check -s exit:0 -o match:"${re}" /bin/sh script
+}
+
atf_init_test_cases()
{
atf_add_test_case oomprotect_all
atf_add_test_case oomprotect_yes
+ atf_add_test_case wait_for_pids_progress
}
diff --git a/sys/kern/vfs_inotify.c b/sys/kern/vfs_inotify.c
index d3cd0d1f9832..746a5a39208e 100644
--- a/sys/kern/vfs_inotify.c
+++ b/sys/kern/vfs_inotify.c
@@ -34,6 +34,7 @@
#include <sys/sysent.h>
#include <sys/syslimits.h>
#include <sys/sysproto.h>
+#include <sys/taskqueue.h>
#include <sys/tree.h>
#include <sys/user.h>
#include <sys/vnode.h>
@@ -168,6 +169,8 @@ struct inotify_softc {
size_t nbpending; /* bytes available to read */
uint64_t ino; /* unique identifier */
struct inotify_watch_tree watches; /* active watches */
+ TAILQ_HEAD(, inotify_watch) deadwatches; /* watches pending vrele() */
+ struct task reaptask; /* task to reap dead watches */
struct selinfo sel; /* select/poll/kevent info */
struct ucred *cred; /* credential ref */
};
@@ -374,6 +377,13 @@ inotify_unlink_watch_locked(struct inotify_softc *sc, struct inotify_watch *watc
vn_irflag_unset(vp, VIRF_INOTIFY);
}
+static void
+inotify_free_watch(struct inotify_watch *watch)
+{
+ vrele(watch->vp);
+ free(watch, M_INOTIFY);
+}
+
/*
* Assumes that the watch has already been removed from its softc.
*/
@@ -389,9 +399,24 @@ inotify_remove_watch(struct inotify_watch *watch)
mtx_lock(&vp->v_pollinfo->vpi_lock);
inotify_unlink_watch_locked(sc, watch);
mtx_unlock(&vp->v_pollinfo->vpi_lock);
+ inotify_free_watch(watch);
+}
- vrele(vp);
- free(watch, M_INOTIFY);
+static void
+inotify_reap(void *arg, int pending)
+{
+ struct inotify_softc *sc;
+ struct inotify_watch *watch;
+
+ sc = arg;
+ mtx_lock(&sc->lock);
+ while ((watch = TAILQ_FIRST(&sc->deadwatches)) != NULL) {
+ TAILQ_REMOVE(&sc->deadwatches, watch, vlink);
+ mtx_unlock(&sc->lock);
+ inotify_free_watch(watch);
+ mtx_lock(&sc->lock);
+ }
+ mtx_unlock(&sc->lock);
}
static int
@@ -403,6 +428,7 @@ inotify_close(struct file *fp, struct thread *td)
sc = fp->f_data;
+ /* Detach watches from their vnodes. */
mtx_lock(&sc->lock);
(void)chginotifycnt(sc->cred->cr_ruidinfo, -1, 0);
while ((watch = RB_MIN(inotify_watch_tree, &sc->watches)) != NULL) {
@@ -411,6 +437,17 @@ inotify_close(struct file *fp, struct thread *td)
inotify_remove_watch(watch);
mtx_lock(&sc->lock);
}
+
+ /* Make sure that any asynchronous vrele() calls are done. */
+ mtx_unlock(&sc->lock);
+ taskqueue_drain(taskqueue_thread, &sc->reaptask);
+ mtx_lock(&sc->lock);
+ KASSERT(RB_EMPTY(&sc->watches),
+ ("%s: watches not empty in %p", __func__, sc));
+ KASSERT(TAILQ_EMPTY(&sc->deadwatches),
+ ("%s: deadwatches not empty in %p", __func__, sc));
+
+ /* Drop pending events. */
while (!STAILQ_EMPTY(&sc->pending)) {
rec = inotify_dequeue(sc);
if (rec != &sc->overflow)
@@ -456,6 +493,8 @@ inotify_create_file(struct thread *td, struct file *fp, int flags, int *fflagsp)
sc->nextwatch = 1; /* Required for compatibility. */
STAILQ_INIT(&sc->pending);
RB_INIT(&sc->watches);
+ TAILQ_INIT(&sc->deadwatches);
+ TASK_INIT(&sc->reaptask, 0, inotify_reap, sc);
mtx_init(&sc->lock, "inotify", NULL, MTX_DEF);
knlist_init_mtx(&sc->sel.si_note, &sc->lock);
sc->cred = crhold(td->td_ucred);
@@ -560,17 +599,16 @@ inotify_queue_record(struct inotify_softc *sc, struct inotify_record *rec)
return (true);
}
-static int
+static void
inotify_log_one(struct inotify_watch *watch, const char *name, size_t namelen,
int event, uint32_t cookie)
{
struct inotify_watch key;
struct inotify_softc *sc;
struct inotify_record *rec;
- int relecount;
bool allocfail;
- relecount = 0;
+ mtx_assert(&watch->vp->v_pollinfo->vpi_lock, MA_OWNED);
sc = watch->sc;
rec = inotify_alloc_record(watch->wd, name, namelen, event, cookie,
@@ -599,20 +637,22 @@ inotify_log_one(struct inotify_watch *watch, const char *name, size_t namelen,
/*
* Remove the watch, taking care to handle races with
- * inotify_close().
+ * inotify_close(). The thread that removes the watch is
+ * responsible for freeing it.
*/
key.wd = watch->wd;
if (RB_FIND(inotify_watch_tree, &sc->watches, &key) != NULL) {
RB_REMOVE(inotify_watch_tree, &sc->watches, watch);
inotify_unlink_watch_locked(sc, watch);
- free(watch, M_INOTIFY);
- /* Defer vrele() to until locks are dropped. */
- relecount++;
+ /*
+ * Defer the vrele() to a sleepable thread context.
+ */
+ TAILQ_INSERT_TAIL(&sc->deadwatches, watch, vlink);
+ taskqueue_enqueue(taskqueue_thread, &sc->reaptask);
}
}
mtx_unlock(&sc->lock);
- return (relecount);
}
void
@@ -620,25 +660,18 @@ inotify_log(struct vnode *vp, const char *name, size_t namelen, int event,
uint32_t cookie)
{
struct inotify_watch *watch, *tmp;
- int relecount;
KASSERT((event & ~(IN_ALL_EVENTS | IN_ISDIR | IN_UNMOUNT)) == 0,
("inotify_log: invalid event %#x", event));
- relecount = 0;
mtx_lock(&vp->v_pollinfo->vpi_lock);
TAILQ_FOREACH_SAFE(watch, &vp->v_pollinfo->vpi_inotify, vlink, tmp) {
KASSERT(watch->vp == vp,
("inotify_log: watch %p vp != vp", watch));
- if ((watch->mask & event) != 0 || event == IN_UNMOUNT) {
- relecount += inotify_log_one(watch, name, namelen, event,
- cookie);
- }
+ if ((watch->mask & event) != 0 || event == IN_UNMOUNT)
+ inotify_log_one(watch, name, namelen, event, cookie);
}
mtx_unlock(&vp->v_pollinfo->vpi_lock);
-
- for (int i = 0; i < relecount; i++)
- vrele(vp);
}
/*
diff --git a/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_swinstalled_tbl.c b/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_swinstalled_tbl.c
index 8b7e4608d673..f7484e90189b 100644
--- a/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_swinstalled_tbl.c
+++ b/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_swinstalled_tbl.c
@@ -372,7 +372,7 @@ swins_get_packages(void)
}
if (errno != 0) {
- syslog(LOG_ERR, "hrSWInstalledTable: readdir_r(\"%s\") failed:"
+ syslog(LOG_ERR, "hrSWInstalledTable: readdir(\"%s\") failed:"
" %m", pkg_dir);
ret = -1;
} else {