Bug 291025 - periodic weekly/security runs scripts twice inside jails (duplicate Security/daily security output)
Summary: periodic weekly/security runs scripts twice inside jails (duplicate Security/...
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 14.3-STABLE
Hardware: amd64 Any
: --- Affects Some People
Assignee: freebsd-jail (Nobody)
URL:
Keywords:
: 291024 (view as bug list)
Depends on:
Blocks:
 
Reported: 2025-11-15 06:23 UTC by Alex Soto Aguilera
Modified: 2025-11-15 15:31 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alex Soto Aguilera 2025-11-15 06:23:21 UTC
Environment:

/etc/rc.conf inside the jail:
cron_flags="-J 60"
hostname="qbittorrent.example.org"
# sendmail disabled, no custom periodic-related entries

/etc/periodic.conf inside the jail:
daily_status_network_enable="NO"
security_status_ipfwlimit_enable="NO"
security_status_ipfwdenied_enable="NO"
weekly_whatis_enable="NO"
weekly_locate_enable="NO"
security_status_neggrpperm_enable="NO"
daily_status_disks_enable="NO"
daily_status_uptime_enable="NO"
daily_ntpd_leapfile_enable="NO"
security_status_chksetuid_enable="NO"
security_status_chkuid0_enable="NO"
security_status_ipfdenied_enable="NO"
security_status_ipf6denied_enable="NO"
security_status_tcpwrap_enable="NO"]​



Description:

The effect is that the weekly and daily security outputs from the jail contain the same blocks printed twice in the same message/run.

On the host system (outside jails), periodic daily/weekly behave normally; each script is executed once and there are no duplicated blocks in the output.]​



How to reproduce (weekly in the jail):

1 3 * * * root periodic daily
15 4 * * 6 root periodic weekly
30 5 1 * * root periodic monthly

Inside the jail, temporarily set:

weekly_output=/tmp/weekly.debug

in /etc/periodic.conf.

Run periodic weekly manually inside the jail.

Inspect the file /tmp/weekly.debug.]​

Actual result (weekly in the jail):

For example (simplified):

Security check:
(output mailed separately)

[...]

Security check:
(output mailed separately)

-- End of weekly output --

In other words, the Security check: (output mailed separately) block from the weekly status-security script appears twice in a single periodic weekly run inside the jail.]​



How to reproduce (daily security in the jail):

1. Use the same qbittorrent jail with /etc/periodic.conf as described in the Environment section.
2. Let cron run normally inside the jail with the default periodic daily line in /etc/crontab.
3. Observe the daily security run output mail from that jail (or redirect daily_output to a file and run periodic security manually).​

Actual result (daily security in the jail):

Checking for passwordless accounts:
root::0:0::0:0:Charlie &:/root:/bin/sh

Checking login.conf permissions:

qbittorrent.example.org login failures:

Checking for passwordless accounts:
root::0:0::0:0:Charlie &:/root:/bin/sh

Checking login.conf permissions:

qbittorrent.example.org login failures:

-- End of security output --

This is from a single daily security run, not from two separate mails.]​



Expected result:


One Security check: (output mailed separately) block per weekly run.

One set of daily security checks (passwordless accounts, login.conf permissions, login failures, etc.) per daily security run.]​



Additional information:

/etc/crontab contains only the standard periodic lines.

crontab -l -u root is empty (no additional cron jobs for periodic).

/var/log/cron inside the jail shows exactly one (root) CMD (periodic daily) per day and one (root) CMD (periodic weekly) per week.

ps aux inside the jail shows exactly one /usr/sbin/cron process.

The duplication happens even when periodic weekly or periodic security is run manually inside the jail with weekly_output / daily_output pointed to a file, confirming that it is not caused by cron running the jobs twice.

Jails are created and managed with BastilleBSD. The generated jail.conf for the qbittorrent jail looks like:

qbittorrent {
exec.start = '/bin/sh /etc/rc';
exec.stop = '/bin/sh /etc/rc.shutdown';
[...]
}

There are no extra exec.start lines and no jexec ... periodic jobs on the host.

The basejail release directory /usr/local/bastille/releases/14.3-RELEASE contains only the standard /etc/periodic/{daily,weekly,monthly,security} directories and no custom periodic scripts; /usr/local/etc/periodic in the release is empty.



Given that:

The host behaves normally.

All jails show duplicated weekly and daily security output for a single periodic run.

Cron is not running these jobs twice.

this seems to indicate an issue with how periodic runs weekly/security classes inside jails in this environment.]​
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2025-11-15 11:22:09 UTC
*** Bug 291024 has been marked as a duplicate of this bug. ***
Comment 2 Alex Soto Aguilera 2025-11-15 14:59:57 UTC
After more investigation this appears to be caused by my local periodic configuration inside the jails, not by periodic(8) itself.

In /etc/defaults/periodic.conf the following defaults are present:

periodic_conf_files="/etc/periodic.conf /etc/periodic.conf.local ${_localbase}/etc/periodic.conf"
local_periodic="${_localbase}/etc/periodic"

_localbase is set inside /usr/sbin/periodic, and local_periodic is then used to add the “local” periodic tree (normally /usr/local/etc/periodic).

In my jails, for some reason local_periodic was not effectively pointing to /usr/local/etc/periodic, which resulted in periodic walking the periodic directories in an unexpected way and running the scripts twice per invocation.

I fixed the issue inside the jails by explicitly setting local_periodic in /etc/periodic.conf:

local_periodic="/usr/local/etc/periodic"

After adding this line and re-running periodic inside the jails, the output is no longer duplicated: each script runs once per run and the daily/weekly mails from the jails contain a single copy of each block.

From my point of view the problem is resolved with this configuration change. I am leaving the PR open so that someone can confirm whether this behavior is expected in jails (e.g. whether local_periodic/_localbase should be documented more clearly for jailed environments, or if there is anything that should be adjusted in periodic or jail setups to avoid this pitfall)
Comment 3 Alex Soto Aguilera 2025-11-15 15:31:52 UTC
(In reply to Alex Soto Aguilera from comment #2)


I did some more checks to better understand what is going on in this environment.

Release tree used by Bastille

The base tree that Bastille uses for jails is located at:

/usr/local/bastille/releases/14.3-RELEASE/

In that tree, the periodic defaults and directories are exactly as in a stock 14.3-RELEASE installation. In particular:

/etc/defaults/periodic.conf contains:

periodic_conf_files="/etc/periodic.conf /etc/periodic.conf.local ${_localbase}/etc/periodic.conf"
local_periodic="${_localbase}/etc/periodic"

and it defines _localbase as:

_set_localbase() {
_localbase=/sbin/sysctl -n user.localbase 2> /dev/null
: ${_localbase:="/usr/local"}
}

_set_localbase

So by default local_periodic resolves to /usr/local/etc/periodic.

There is no /etc/periodic.conf in that release tree, which matches expectations for a clean system.

/etc/periodic/{daily,weekly,monthly,security} contains only the standard base scripts from 14.3.

There is no /usr/local/etc/periodic in the release tree (no local periodic scripts by default).

user.localbase inside the jail

Inside the affected jails (e.g. the qbittorrent jail), sysctl user.localbase works and returns /usr/local, for example:

root@qbittorrent:~ # sysctl user.localbase
user.localbase: /usr/local

root@qbittorrent:~ # sysctl -n user.localbase
/usr/local

This means that inside the jail _localbase is correctly set to /usr/local by the code in defaults/periodic.conf, and therefore the default value of local_periodic is also /usr/local/etc/periodic inside the jail, same as on the host.

Summary of the situation

The base release tree used by Bastille has the expected defaults: user.localbase → _localbase=/usr/local → local_periodic="/usr/local/etc/periodic".

Inside the jails, sysctl user.localbase correctly reports /usr/local.

On the host, periodic runs daily/weekly without duplicate output.

Inside the jails, before adding any overrides, periodic weekly and periodic security were producing duplicated security blocks in a single run.

Explicitly setting in /etc/periodic.conf inside the jail:

local_periodic="/usr/local/etc/periodic"

stops the duplication and makes periodic behave as expected.

So from what I can see:

The defaults in /etc/defaults/periodic.conf are correct and user.localbase is correct in both host and jails.

The duplicate execution only manifested inside the jails until local_periodic="/usr/local/etc/periodic" was explicitly set in /etc/periodic.conf there.

I am not sure yet why the explicit override in /etc/periodic.conf changes the behavior while the defaults already resolve to the same path, but it seems to be specific to running periodic inside these jails. I am leaving this note here in case it helps someone reproduce the environment or reason about the interaction between periodic_conf_files, local_periodic and the jail context.