Commit Graph

3620 Commits

Author SHA1 Message Date
Christian Göttsche
3459dfd92e libselinux/utils: update selabel_partial_match
Print usage information and exit if required path option is not given
or superfluous arguments are given.

Constify read-only variables assigned command line arguments.

Simplify bool evaluation.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-10-11 14:57:17 -04:00
Bruno Victal
bb5a8541fb secilc: Use versioned DocBook public identifier.
Fix xml validation issues that often crop up since the XML catalogs
for DocBook often only contain versioned public identifiers.

Signed-off-by: Bruno Victal <mirai@makinata.eu>
Acked-by: James Carter <jwcart2@gmail.com>
2023-10-11 14:54:47 -04:00
James Carter
01da3a9ca3 libsepol: Fix the version number for the latest exported function
cil_write_post_ast() should be in libsepol version 3.6, since version
3.5 has already been released.

Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-10-11 14:54:35 -04:00
James Carter
e609391105 checkpolicy: Remove support for role dominance rules
Role dominance has been deprecated for a very, very long time (since
at least August 2008) and has never been used in any widely deployed
policy.

Remove support for compiling role dominance rules.

Support will remain, for now, in libsepol for backwards compatibility.

Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:20 -04:00
James Carter
17c2247f20 secilc/docs: Add deny rule to CIL documentation
Signed-off-by: James Carter <jwcart2@gmail.com>
Reviewed-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:18 -04:00
James Carter
cc02a5f53f secilc/test: Add deny rule tests
Signed-off-by: James Carter <jwcart2@gmail.com>
Reviewed-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:16 -04:00
James Carter
409b4d3bd4 secilc/secil2tree: Add option to write CIL AST after post processing
This will show the resulting CIL AST after deny rules have been
processed.

Signed-off-by: James Carter <jwcart2@gmail.com>
Reviewed-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:14 -04:00
James Carter
5d5a871cb1 libsepol: Export the cil_write_post_ast function
Signed-off-by: James Carter <jwcart2@gmail.com>
Reviewed-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:11 -04:00
James Carter
2fe8a49566 libsepol/cil: Add cil_write_post_ast function
The function cil_write_post_ast() will write the CIL AST after
post processing is done. Most post processing does not change the
CIL AST, this is where deny rules are processed (because to process
them, type attributes have to have been evaluated.)

When processed, deny rules may add new rules and attributes and the
deny rule itself will be removed from the AST, so using this new
function will show the results of the deny rule processing.

Signed-off-by: James Carter <jwcart2@gmail.com>
Reviewed-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:09 -04:00
James Carter
b0ed365ed7 libsepol/cil: Process deny rules
A deny rule is like a neverallow rule, except that permissions are
removed rather than an error reported.

(allow S1 T1 P1)
(deny  S2 T2 P2)

First, write the allow rule with all of the permissions not in the deny rule
P3 = P1 and not P2
(allow S1 T1 P3)

Obviously, the rule is only written if P3 is not an empty list. This goes
for the rest of the rules as well--they are only written if the source and
target exist.

The remaining rules will only involve the common permissions
P4 = P1 and P2

Next, write the allow rule for any types in S1 that are not in S2
S3 = S1 and not S2
(allow S3 T1 P4)

Finally, write the allow rules needed to cover the types in T1 that are
not in T2. Since, T1 and T2 might be "self", "notself", or "other", this
requires more complicated handling. Any rule with "self" will not match
a rule with either "notself" or "other".

if (T1 is self and T2 is self) or (T1 is notself and T2 is notself) then
  Nothing more needs to be done.

The rest of the rules will depend on the intersection of S1 and S2
which cannot be the empty set since the allow and deny rules match.
S4 = S1 and S2

if T1 is notself or T1 is other or T2 is notself or T2 is other then
  if T1 is notself then
    if T2 is other then
      T = ALL and not S2
      (allow S4 T P4)
    else [T2 is not self, notself, or other]
      S5 = S4 and not T2
      S6 = S4 and T2
      TA = ALL and not T2
      TB = TA and not S4
      (allow S6 TA P4)
      (allow S5 TB P4)
      if cardinality(S5) > 1 then
        (allow S5 other P4)
  else if T1 is other then
    (allow S3 S4 P4)
    if T2 is notself then
      [Nothing else is needed]
    else if T2 is other then
      (allow S4 S3 P4)
    else [T2 is not self, notself, or other]
      S5 = S4 and not T2
      S6 = S4 and T2
      TC = S1 and not T2
      TD = S3 and not T2
      (allow S6 TC P4)
      (allow S5 TD P4)
      if cardinality(S5) > 1 then
        (allow S5 other P4)
  else [T1 is not self, notself, or other]
    S8 = S4 and T1
    (allow S8 self P4)
    if T2 is notself then
      [Nothing else is needed]
    else [T2 is other]
      T = T1 and not S2
      (allow S4 T P4)
else [Neither T1 nor T2 are notself or other]
  if T1 is self and T2 is not self then
    S5 = S4 and not T2
    (allow S5 self P4)
  else if T1 is not self and T2 is self then
    S7 = S4 and not T1
    S8 = S4 and T1
    T8 = T1 and not S4
    (allow S7 T1 P4)
    (allow S8 T8 P4)
    if cardinality(S8) > 1 then
      (allow S8 other P4)
  else [Neither T1 nor T2 is self]
    T3 = T1 and not T2
    (allow S4 T3 P4)

Signed-off-by: James Carter <jwcart2@gmail.com>
Reviewed-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:07 -04:00
James Carter
9d5ca92be1 libsepol/cil: Add cil_tree_node_remove function
Add the function cil_tree_node_remove() which takes a node pointer
as an input, finds the parent, walks the list of nodes to the node
prior to the given node, updates that node's next pointer to remove
the given node from the tree, and then destroys the node.

Signed-off-by: James Carter <jwcart2@gmail.com>
Reviewed-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:05 -04:00
James Carter
085e330062 libsepol/cil: Add cil_list_is_empty macro
Add a macro, called cil_list_is_empty, that returns true if the
list pointer or list head is NULL.

Signed-off-by: James Carter <jwcart2@gmail.com>
Reviewed-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:03 -04:00
James Carter
347254695f libsepol/cil: Parse and add deny rule to AST, but do not process
Adds the ability to parse a deny rule, add it to the AST, and
write it out when writing the AST, but the deny rule is otherwise
ignored and does nothing.

When it is fully supported, the deny rule will work like a neverallow
except that it will remove permissions rather than give an error.

Signed-off-by: James Carter <jwcart2@gmail.com>
Reviewed-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:01 -04:00
James Carter
0e88ee26fb secilc/test: Add notself and other tests
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:34:00 -04:00
James Carter
ed8f4a9508 secilc/docs: Add notself and other keywords to CIL documentation
Also reorganize the access vector rules section to minimize duplication
explanation of the parts of access vector rules.

Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:58 -04:00
James Carter
1936a23a0e libsepol: Use ERR() instead of log_err()
Since log_err() has been removed, use ERR() instead of log_err() in
module_to_cil.c.

Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:56 -04:00
Christian Göttsche
902f0f94a1 libsepol: update CIL generation for trivial not-self rules
Convert trivial not-self neverallow rules to CIL, e.g.

    neverallow TYPE1 ~self:CLASS1 PERM1;

into

    (neverallow TYPE1 notself (CLASS1 (PERM1)))

More complex targets are not yet supported in CIL and will fail to
convert, e.g.:

    neverallow TYPE1 ~{ self ATTR1 } : CLASS1 PERM1;
    neverallow TYPE2 { ATTR2 -self } : CLASS2 PERM2;

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:55 -04:00
James Carter
e55621c032 libsepol/cil: Add notself and other support to CIL
Like "self", both of these reserved words can be used as a target
in an access vector rule. "notself" means all types other than
the source type. "other" is meant to be used with an attribute and
its use results in the rule being expanded with each type of the
attribute being used as the source type with each of the other types
being used as the target type. Using "other" with just a type will
result in no rule.

Example 1
  (allow TYPE1 notself (CLASS (PERM)))

This rule is expanded to a number of rules with TYPE1 as the source
and every type except for TYPE1 as the target.

Example 2
  (allow ATTR1 notself (CLASS (PERM)))

Like Example 1, this rule will be expanded to each type in ATTR1
being the source with every type except for the type used as the
source being the target.

Example 3
  (allow TYPE1 other (CLASS (PERM)))

This expands to no rule.

Example 4
  (allow ATTR1 other (CLASS (PERM)))

Like Example 2, but the target types will be limited to the types
in the attribute ATTR1 instead of all types. So if ATTR1 has the
type t1, t2, and t3, then this rule expands to the following rules.
  (allow t1 t2 (CLASS (PERM)))
  (allow t1 t3 (CLASS (PERM)))
  (allow t2 t1 (CLASS (PERM)))
  (allow t2 t3 (CLASS (PERM)))
  (allow t3 t1 (CLASS (PERM)))
  (allow t3 t2 (CLASS (PERM)))

Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:52 -04:00
James Carter
2b3dd2c77d libsepol/cil: Do not call ebitmap_init twice for an ebitmap
While it does no harm to call ebitmap_init() twice for an ebitmap,
since it is just memsetting the ebitmap to 0, it is poor practice.

In the function cil_type_matches() in cil_find.c, either ebitmap_and()
or ebitmap_set_bit() will be called. The function ebitmap_and() will
call ebitmap_init() on the destination ebitmap, but ebitmap_set_bit()
does not.

Instead of calling ebitmap_init() before the call to cil_type_matches(),
let cil_type_matches() make the call if it is going to call
ebitmap_set_bit(). It can also call ebitmap_destroy() on an error.

Since we are removing the call to ebitmap_init() in cil_self_match_any(),
cleanup some other things in the function (like using the FLAVOR()
macro and using ebitmap_is_empty()).

Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:50 -04:00
James Carter
cd575089db libsepol: Changes to ebitmap.h to fix compiler warnings
When compiling with the "-Wnull-dereference" flag, the compiler is
not smart enough to realize that anytime the ebitmap_t node field is
NULL, the highbit field will equal 0. This causes false positive
warnings to be generated.

Change the ebitmap_is_empty() and ebitmap_length() macros to check
for the node being NULL instead of just relying on the value of
highbit to eliminate these false warnings.

Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:48 -04:00
James Carter
14f35fde50 Do not automatically install Russian translations
Since they are being removed, there will be nothing to install.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:47 -04:00
James Carter
5149c39a4e semodule-utils: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:45 -04:00
James Carter
8b2148f238 sandbox: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:44 -04:00
James Carter
7021ccd4fb restorecond: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:42 -04:00
James Carter
cb0b5f3aeb python: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them. This removes the translations from sepolicy.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:40 -04:00
James Carter
fda3a45903 python: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them. Because of the size, this patch just removes
the translations from audit2allow, chcat, and semanage.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:39 -04:00
James Carter
5c3312e0af policycoreutils: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:30 -04:00
James Carter
fd7eba9313 mcstrans: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:27 -04:00
James Carter
c3d1301073 libsepol: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:25 -04:00
James Carter
1303a6af48 libsemanage: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:22 -04:00
James Carter
84c195e18c libselinux: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them. This removes the man8 translations and the
ru directory.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:20 -04:00
James Carter
8e6e044352 libselinux: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them. Because of the size, this just removes the
man5 translations.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:19 -04:00
James Carter
fb58fa9735 gui: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:17 -04:00
James Carter
b7e39e509b checkpolicy: Remove the Russian translations
The Russian translations have not been maintained and are out of
date, so remove them.

Suggested-by: Petr Lautrbach <plautrba@redhat.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Petr Lautrbach <lautrbach@redhat.com>
2023-08-16 13:33:14 -04:00
Christian Göttsche
8e3a532880 libsemanage/tests: use strict prototypes
utilities.c:39:22: error: a function declaration without a prototype is deprecated in all versions of C [-Werror,-Wstrict-prototypes]
    int create_test_store() {
                         ^
                          void
    utilities.c:171:23: error: a function declaration without a prototype is deprecated in all versions of C [-Werror,-Wstrict-prototypes]
    int destroy_test_store() {
                          ^
                           void

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-16 13:33:12 -04:00
Christian Göttsche
8b0acb0535 libsepol: ebitmap: avoid branches for iteration
Otherwise Linus might think we don't understand pointers.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-16 13:33:11 -04:00
James Carter
f6dc6acfa0 python: Use isinstance() instead of type()
CI testing fails while running flake8 on python scripts with the
message "./python/semanage/seobject.py:250:16: E721 do not compare
types, for exact checks use `is` / `is not`, for instance checks use
`isinstance()`"

Use "isinstance(args, str)" instead of "type(args) == str"

Signed-off-by: James Carter <jwcart2@gmail.com>
2023-08-08 13:00:12 +02:00
Christian Göttsche
1c19dc4f64 libsepol: expand: check for memory allocation failure
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-07 09:44:50 -04:00
Christian Göttsche
ace9ec17ff libsepol: expand: use identical type to avoid implicit conversion
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-07 09:44:45 -04:00
Christian Göttsche
0d1445067c hashtab: update
Avoid overflowing number of elements in hashtab_insert().

Use identical type for hashed values to avoid implicit conversions.

Declare tag parameter of hashtab_hash_eval() const since it is only
printed.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-07 09:44:42 -04:00
Christian Göttsche
511f43478f libsepol: validate: use fixed sized integers
Avoid issues on architectures where unsigned int and uint32_t are not of
the same size.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-07 09:42:17 -04:00
Stephen Smalley
8963492b5d checkpolicy,libselinux,libsepol,policycoreutils,semodule-utils: update my email
Update my email address.

Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-04 13:57:01 -04:00
Stephen Smalley
f189e8afc8 libselinux,policycoreutils,python,semodule-utils: de-brand SELinux
Change "NSA SELinux" to just "SELinux" and remove NSA from the
SELinux manual pages.

Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-04 13:56:44 -04:00
Christian Göttsche
ec35d1d802 libselinux/utils: introduce getpolicyload
Introduce a helper binary to print the number of policy reloads on the
running system.
Print only a single number to ease the usage by scripts.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-04 13:55:55 -04:00
Huaxin Lu
04613f6875 secilc: add check for malloc in secilc
Check the return value of malloc() to avoid null pointer reference.

Signed-off-by: Huaxin Lu <luhuaxin1@huawei.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-04 13:52:55 -04:00
Huaxin Lu
8730e0762e restorecond: add check for strdup in strings_list_add
Check the return value of strdup() to avoid null pointer reference.

Signed-off-by: Huaxin Lu <luhuaxin1@huawei.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-04 13:52:40 -04:00
Christian Göttsche
a7e975285c semodule_unpackage: update
Drop unnecessary declarations.
Check closing file for incomplete write.
Rework resource cleanup, so that all files and allocated memory are
released in all branches, useful to minimize reports while debugging
libsepol under valgrind(8) or sanitizers.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-04 13:51:56 -04:00
Christian Göttsche
f40d4f3dda semodule_package: update
Drop unnecessary declarations.
Add missing error messages.
More strict command line argument parsing.
Check closing file for incomplete write.
Rework resource cleanup, so that all files and allocated memory are
released in all branches, useful to minimize reports while debugging
libsepol under valgrind(8) or sanitizers.
Set close-on-exec flag in case of any sibling thread.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-04 13:51:51 -04:00
Christian Göttsche
63e798a203 semodule_link: update
Drop unnecessary declarations.
More verbose error messages and add missing trailing newline.
More strict argument count checking.
Check closing file for incomplete write.
Rework resource cleanup, so that all files and allocated memory are
released in all branches, useful to minimize reports while debugging
libsepol under valgrind(8) or sanitizers.
Add help argument option -h.
Set close-on-exec flag in case of any sibling thread.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-04 13:51:50 -04:00
Christian Göttsche
2b89a35fcc semodule_expand: update
Drop unnecessary declarations.
Reduce scope of file global variable.
Mention -v argument in help usage message.
More strict integer conversion.
More strict argument count checking.
Check closing file for incomplete write.
Rework resource cleanup, so that all files and allocated memory are
released in all branches, useful to minimize reports while debugging
libsepol under valgrind(8) or sanitizers.
Add help argument option -h.
Set close-on-exec flag in case of any sibling threads.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2023-08-04 13:51:47 -04:00