MFH: r523920

Fix accidental removal of devfs_rulesets on jail stop

Pulls in a bugfix[0] that has been merged upstream[1].

This bug caused manually configured devfs_rulesets to get deleted on jail
stop, causing jails to come up with a default devfs rules on next start,
which can be a nuisance or even dangerous, depending on the specific setup.

Also adds a minimum devfs_ruleset id for dynamically created devfs rulesets
and fixes a devfs_ruleset resource leak when using plugins.

Take maintainership, as suggested by araujo@ (thanks for taking care of that
port for so long!).

[0]https://github.com/iocage/iocage/pull/1106
[1]753b2f3573

PR:		243510
Approved by:	araujo (maintainer)

Approved by:	ports-secteam (joneum)
This commit is contained in:
Michael Gmelin 2020-01-24 11:36:16 +00:00
parent d3c8474bc2
commit ae7ffb545b
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/branches/2020Q1/; revision=523962
4 changed files with 253 additions and 2 deletions

View File

@ -2,11 +2,11 @@
PORTNAME= iocage
PORTVERSION= 1.2
PORTREVISION= 3
PORTREVISION= 4
CATEGORIES= sysutils python
PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX}
MAINTAINER= araujo@FreeBSD.org
MAINTAINER= grembo@FreeBSD.org
COMMENT= FreeBSD jail manager written in Python3
LICENSE= BSD2CLAUSE

View File

@ -0,0 +1,73 @@
Originates here
https://github.com/iocage/iocage/commit/753b2f35731423597d7f51f33427b6d619fcd0b5
https://github.com/iocage/iocage/pull/1106
and most likely can be removed on the next release of iocage.
--- iocage_lib/ioc_common.py.orig 2019-09-26 07:23:24 UTC
+++ iocage_lib/ioc_common.py
@@ -44,6 +44,9 @@ import iocage_lib.ioc_exceptions
import iocage_lib.ioc_exec
INTERACTIVE = False
+# 4 is a magic number for default and doesn't refer
+# to the actual ruleset 4 in devfs.rules(!)
+IOCAGE_DEVFS_RULESET = 4
def callback(_log, callback_exception):
@@ -737,7 +740,7 @@ def generate_devfs_ruleset(conf, paths=N
Will add a per jail devfs ruleset with the specified rules,
specifying defaults that equal devfs_ruleset 4
"""
- ruleset = conf['devfs_ruleset']
+ configured_ruleset = conf['devfs_ruleset']
devfs_includes = []
devfs_rulesets = su.run(
['devfs', 'rule', 'showsets'],
@@ -745,22 +748,26 @@ def generate_devfs_ruleset(conf, paths=N
)
ruleset_list = [int(i) for i in devfs_rulesets.stdout.splitlines()]
- if ruleset != '4':
- if int(ruleset) in ruleset_list:
- return str(ruleset)
-
- logit({
- "level": "INFO",
- "message": f'* Ruleset {ruleset} does not exist, using defaults'
- },
- _callback=callback,
- silent=silent)
-
- ruleset = 5 # 0-4 is always reserved
+ ruleset = int(conf["min_dyn_devfs_ruleset"])
while ruleset in ruleset_list:
ruleset += 1
ruleset = str(ruleset)
+ # Custom devfs_ruleset configured, clone to dynamic ruleset
+ if int(configured_ruleset) != IOCAGE_DEVFS_RULESET:
+ if int(configured_ruleset) not in ruleset_list:
+ return (True, configured_ruleset, '0')
+ rules = su.run(
+ ['devfs', 'rule', '-s', configured_ruleset, 'show'],
+ stdout=su.PIPE, universal_newlines=True
+ )
+ for rule in rules.stdout.splitlines():
+ su.run(['devfs', 'rule', '-s', ruleset, 'add'] +
+ rule.split(' ')[1:], stdout=su.PIPE)
+
+ return (True, configured_ruleset, ruleset)
+
+ # Create default ruleset
devfs_dict = dict((dev, None) for dev in (
'hide', 'null', 'zero', 'crypto', 'random', 'urandom', 'ptyp*',
'ptyq*', 'ptyr*', 'ptys*', 'ptyP*', 'ptyQ*', 'ptyR*', 'ptyS*', 'ptyl*',
@@ -812,7 +819,7 @@ def generate_devfs_ruleset(conf, paths=N
su.run(['devfs', 'rule', '-s', ruleset] + path, stdout=su.PIPE)
- return ruleset
+ return (False, configured_ruleset, ruleset)
def runscript(script):

View File

@ -0,0 +1,74 @@
Originates here
https://github.com/iocage/iocage/commit/753b2f35731423597d7f51f33427b6d619fcd0b5
https://github.com/iocage/iocage/pull/1106
and most likely can be removed on the next release of iocage.
--- iocage_lib/ioc_json.py.orig 2019-09-26 07:23:24 UTC
+++ iocage_lib/ioc_json.py
@@ -671,7 +671,7 @@ class IOCConfiguration(IOCZFS):
@staticmethod
def get_version():
"""Sets the iocage configuration version."""
- version = '26'
+ version = '27'
return version
@@ -1104,6 +1104,10 @@ class IOCConfiguration(IOCZFS):
if conf.get(option) == 'none':
conf[option] = 'auto'
+ # Version 27 key
+ if not conf.get('min_dyn_devfs_ruleset'):
+ conf['min_dyn_devfs_ruleset'] = '1000'
+
if not default:
conf.update(jail_conf)
@@ -1321,7 +1325,7 @@ class IOCConfiguration(IOCZFS):
'vnet2_mac': 'none',
'vnet3_mac': 'none',
'vnet_default_interface': 'auto',
- 'devfs_ruleset': '4',
+ 'devfs_ruleset': str(iocage_lib.ioc_common.IOCAGE_DEVFS_RULESET),
'exec_start': '/bin/sh /etc/rc',
'exec_stop': '/bin/sh /etc/rc.shutdown',
'exec_prestart': '/usr/bin/true',
@@ -1432,6 +1436,7 @@ class IOCConfiguration(IOCZFS):
'nat_forwards': 'none',
'plugin_name': 'none',
'plugin_repository': 'none',
+ 'min_dyn_devfs_ruleset': '1000',
}
def check_default_config(self):
@@ -2369,6 +2374,7 @@ class IOCJson(IOCConfiguration):
'nat_forwards': ('string', ),
'plugin_name': ('string', ),
'plugin_repository': ('string', ),
+ 'min_dyn_devfs_ruleset': ('string', ),
}
zfs_props = {
@@ -2648,6 +2654,22 @@ class IOCJson(IOCConfiguration):
silent=self.silent,
exception=ioc_exceptions.ValidationFailed
)
+ elif key in ('devfs_ruleset', 'min_dyn_devfs_ruleset'):
+ try:
+ intval = int(value)
+ if intval <= 0:
+ raise ValueError()
+ conf[key] = str(intval)
+ except ValueError:
+ iocage_lib.ioc_common.logit(
+ {
+ 'level': 'EXCEPTION',
+ 'message': f'Invalid {key} value: {value}'
+ },
+ _callback=self.callback,
+ silent=self.silent,
+ exception=ioc_exceptions.ValidationFailed
+ )
return value, conf
else:

View File

@ -0,0 +1,104 @@
Originates here
https://github.com/iocage/iocage/commit/753b2f35731423597d7f51f33427b6d619fcd0b5
https://github.com/iocage/iocage/pull/1106
and most likely can be removed on the next release of iocage.
--- iocage_lib/ioc_start.py.orig 2019-09-26 07:23:24 UTC
+++ iocage_lib/ioc_start.py
@@ -145,7 +145,6 @@ class IOCStart(object):
allow_quotas = self.conf["allow_quotas"]
allow_socket_af = self.conf["allow_socket_af"]
allow_vmm = self.conf["allow_vmm"]
- devfs_ruleset = iocage_lib.ioc_common.generate_devfs_ruleset(self.conf)
exec_prestart = self.conf["exec_prestart"]
exec_poststart = self.conf["exec_poststart"]
exec_clean = self.conf["exec_clean"]
@@ -486,16 +485,8 @@ class IOCStart(object):
_callback=self.callback,
silent=self.silent)
- if wants_dhcp and self.conf['type'] != 'pluginv2' \
- and self.conf['devfs_ruleset'] != '4':
- iocage_lib.ioc_common.logit({
- "level": "WARNING",
- "message": f" {self.uuid} is not using the devfs_ruleset"
- f" of 4, not generating a ruleset for the jail,"
- " DHCP may not work."
- },
- _callback=self.callback,
- silent=self.silent)
+ devfs_paths = None
+ devfs_includes = None
if self.conf['type'] == 'pluginv2' and os.path.isfile(
os.path.join(self.path, f'{self.conf["plugin_name"]}.json')
@@ -509,17 +500,51 @@ class IOCStart(object):
plugin_name = self.conf['plugin_name']
plugin_devfs = devfs_json[
"devfs_ruleset"][f"plugin_{plugin_name}"]
- plugin_devfs_paths = plugin_devfs['paths']
-
- plugin_devfs_includes = None if 'includes' not in \
+ devfs_paths = plugin_devfs['paths']
+ devfs_includes = None if 'includes' not in \
plugin_devfs else plugin_devfs['includes']
- devfs_ruleset = \
- iocage_lib.ioc_common.generate_devfs_ruleset(
- self.conf,
- paths=plugin_devfs_paths,
- includes=plugin_devfs_includes
- )
+ # Generate dynamic devfs ruleset from configured one
+ (manual_devfs_config, configured_devfs_ruleset, devfs_ruleset) \
+ = iocage_lib.ioc_common.generate_devfs_ruleset(
+ self.conf, devfs_paths, devfs_includes)
+
+ if int(devfs_ruleset) <= 0:
+ iocage_lib.ioc_common.logit({
+ "level": "ERROR",
+ "message": f"{self.uuid} devfs_ruleset"
+ f" {configured_devfs_ruleset} does not exist!"
+ " - Not starting jail"
+ },
+ _callback=self.callback,
+ silent=self.silent)
+ return
+
+ # Manually configured devfs_ruleset doesn't support all iocage features
+ if manual_devfs_config:
+ if devfs_paths is not None or devfs_includes is not None:
+ iocage_lib.ioc_common.logit({
+ "level": "WARNING",
+ "message": f" {self.uuid} is not using the devfs_ruleset"
+ " of "
+ f"{iocage_lib.ioc_common.IOCAGE_DEVFS_RULESET}"
+ ", devices and includes from plugin not added"
+ ", some features of the plugin may not work."
+ },
+ _callback=self.callback,
+ silent=self.silent)
+
+ if wants_dhcp and self.conf['type'] != 'pluginv2':
+ iocage_lib.ioc_common.logit({
+ "level": "WARNING",
+ "message": f" {self.uuid} is not using the devfs_ruleset"
+ " of "
+ f"{iocage_lib.ioc_common.IOCAGE_DEVFS_RULESET}"
+ ", not generating a ruleset for the jail,"
+ " DHCP may not work."
+ },
+ _callback=self.callback,
+ silent=self.silent)
parameters = [
fdescfs, _allow_mlock, tmpfs,
@@ -619,6 +644,9 @@ class IOCStart(object):
iocage_lib.ioc_common.logit({
'level': 'INFO',
'message': f' + Using devfs_ruleset: {devfs_ruleset}'
+ + (' (cloned from devfs_ruleset '
+ f'{configured_devfs_ruleset})' if manual_devfs_config
+ else ' (iocage generated default)')
},
_callback=self.callback,
silent=self.silent)