Skip to content

apparmor: align quoting with libapparmor - #44

Merged
thaJeztah merged 3 commits into
moby:mainfrom
thaJeztah:apparmor_improve_whitespace_handling
Sep 25, 2026
Merged

thaJeztah merged 3 commits into
moby:mainfrom
thaJeztah:apparmor_improve_whitespace_handling

Conversation

@thaJeztah

@thaJeztah thaJeztah commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

apparmor: splitCon: touch-up GoDoc

apparmor: align profile-name quoting with libapparmor

Commit 47d6e85 updated the template to
quote profile names. While the manpage (apparmor.d(5)) documents quoted
names, it is unclear how quoting must be handled:

PROFILE NAME = UNQUOTED PROFILE NAME | QUOTED PROFILE NAME

QUOTED PROFILE NAME = '"' UNQUOTED PROFILE NAME '"'

UNQUOTED PROFILE NAME = (must start with alphanumeric character (after
variable expansion), or '/' AARE have special meanings; see below. May
include VARIABLE. Rules with embedded spaces or tabs must be quoted.)

The lexer in parser/parser_lex.l further describes the syntax of quoted
identifiers:

ALLOWED_QUOTED_ID  [^\0"]|\\\"
QUOTED_ID          \"{ALLOWED_QUOTED_ID}*\"

However, quoting alone does not preserve a profile name literally.
processunquoted decodes recognized escape sequences and preserves
escaping for AARE special characters so that they remain literal when
processed by the pattern-matching backend. In particular, backslashes
must be escaped to prevent sequences such as \n from being decoded,
and AARE special characters such as *, ?, [], and {} must be
escaped to prevent them from acquiring pattern semantics. See
processunquoted and strn_escseq.

Update profile-name quoting to account for both AppArmor escape sequences
and AARE special characters, preserving the profile name literally. NUL
values are not handled, as they are not valid in quoted identifiers and
should not reach this code.

Also update profileData to provide accessors for its fields, allowing
profile names to be quoted by those methods instead of exposing raw
values directly to the template.

This also fixes handling of the unconfined daemon profile. The previous
quoting change rendered it as "unconfined", which changes its AppArmor
semantics from the special unconfined selector to a literal profile-name
expression. Keep this sentinel unquoted while continuing to quote actual
profile names.

Updates 47d6e85

@thaJeztah
thaJeztah requested a lite review from Copilot September 23, 2026 22:12
@thaJeztah
thaJeztah force-pushed the apparmor_improve_whitespace_handling branch from e6c37cd to aed3cd0 Compare September 23, 2026 22:14

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as outdated.

@thaJeztah
thaJeztah force-pushed the apparmor_improve_whitespace_handling branch 2 times, most recently from 7be3f28 to e30519d Compare September 23, 2026 23:24
@thaJeztah
thaJeztah requested a balanced review from Copilot September 23, 2026 23:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

Only a non-blocking GoDoc clarification remains.

Review effort: Balanced
Findings: None

Resolved since last review (1)

@vvoland

vvoland commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

I think profile declarations and peer patterns need different escaping here.
.Name is used for both, but AppArmor preserves AARE escapes and serializes the profile name as-is.

Opened thaJeztah#1 for consideration

@thaJeztah
thaJeztah force-pushed the apparmor_improve_whitespace_handling branch from 62df3d8 to afd0b8f Compare September 25, 2026 07:45
@thaJeztah

Copy link
Copy Markdown
Member Author

Making some extra changes inspired by your "let's also check what apparmor_parser says about this" - I'll give you a nudge when done

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Commit 47d6e85 updated the template to
quote profile names. While the manpage ([apparmor.d(5)]) documents quoted
names, it is unclear how quoting must be handled:

    PROFILE NAME = UNQUOTED PROFILE NAME | QUOTED PROFILE NAME

    QUOTED PROFILE NAME = '"' UNQUOTED PROFILE NAME '"'

    UNQUOTED PROFILE NAME = (must start with alphanumeric character (after
    variable expansion), or '/' AARE have special meanings; see below. May
    include VARIABLE. Rules with embedded spaces or tabs must be quoted.)

The lexer in [parser/parser_lex.l] further describes the syntax of quoted
identifiers:

    ALLOWED_QUOTED_ID  [^\0"]|\\\"
    QUOTED_ID          \"{ALLOWED_QUOTED_ID}*\"

However, quoting alone does not preserve a profile name literally.
[processunquoted] decodes recognized escape sequences and preserves
escaping for AARE special characters so that they remain literal when
processed by the pattern-matching backend. In particular, backslashes
must be escaped to prevent sequences such as `\n` from being decoded,
and AARE special characters such as `*`, `?`, `[]`, and `{}` must be
escaped to prevent them from acquiring pattern semantics. See
[processunquoted] and [strn_escseq].

Update profile-name quoting to account for both AppArmor escape sequences
and AARE special characters, preserving the profile name literally. NUL
values are not handled, as they are not valid in quoted identifiers and
should not reach this code.

Also update profileData to provide accessors for its fields, allowing
profile names to be quoted by those methods instead of exposing raw
values directly to the template.

This also fixes handling of the `unconfined` daemon profile. The previous
quoting change rendered it as `"unconfined"`, which changes its AppArmor
semantics from the special unconfined selector to a literal profile-name
expression. Keep this sentinel unquoted while continuing to quote actual
profile names.

Updates 47d6e85

[apparmor.d(5)]: https://manpages.ubuntu.com/manpages/xenial/man5/apparmor.d.5.html
[parser/parser_lex.l]: https://gitlab.com/apparmor/apparmor/-/blob/v5.0.2/parser/parser_lex.l#L286-287
[processunquoted]: https://gitlab.com/apparmor/apparmor/-/blob/v5.0.2/parser/parser_misc.c#L468-507
[strn_escseq]: https://gitlab.com/apparmor/apparmor/-/blob/v5.0.2/parser/lib.c#L178-218

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
@thaJeztah
thaJeztah force-pushed the apparmor_improve_whitespace_handling branch from afd0b8f to ad1e7de Compare September 25, 2026 12:35
Comment on lines +281 to +287
{
name: "with-special-characters",
data: profileData{
name: `foo"bar,*?[ab]{c,d}^\baz`,
daemonProfile: `daemon"bar,*?[ab]{c,d}^\baz`,
},
},

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test-case here as well, so that the before/after is more apparent. Test passes "before", but because it just takes the quoted profile as a name.

@{PROC}=/proc/

profile "foo\"bar\,\*\?\[ab\]\{c\,d\}\^\\baz" flags=(attach_disconnected,mediate_deleted) {
profile "foo\"bar,*?[ab]{c,d}^\baz" flags=(attach_disconnected,mediate_deleted) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this shows the diff clearly before/after 👍

Comment thread apparmor/template_test.go Outdated
Comment on lines +97 to +107
// Declarations retain AARE escapes, while peer patterns consume them.
for _, want := range []string{
`profile "foo\"bar,*?[ab]{c,d}^\baz" flags=(attach_disconnected,mediate_deleted) {`,
` signal (receive) peer="daemon\,profile\\baz",`,
` signal (send,receive) peer="foo\"bar\,\*\?\[ab\]\{c\,d\}\^\\baz",`,
` ptrace (trace,tracedby,read,readby) peer="foo\"bar\,\*\?\[ab\]\{c\,d\}\^\\baz",`,
} {
if !strings.Contains(out.String(), "\n"+want+"\n") {
t.Errorf("generated profile is missing line %q", want)
}
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, perhaps this is redundant now, because I added it to the test-table 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this one 😅

(but probably we could move the test-table to a non-linux file, or just make it non-linux; most tests should be testable cross-platform)

AARE escaping changed the declared profile name. Keep declaration
quoting separate from peer-pattern escaping.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
@thaJeztah
thaJeztah force-pushed the apparmor_improve_whitespace_handling branch from ad1e7de to f0494f1 Compare September 25, 2026 12:42
@thaJeztah
thaJeztah merged commit 85e237f into moby:main Sep 25, 2026
10 checks passed
@thaJeztah
thaJeztah deleted the apparmor_improve_whitespace_handling branch September 25, 2026 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants