canonical / prompting-client

GNU General Public License v3.0
8 stars 4 forks source link

When granting write access to files, lock (k) permission should also be granted #92

Open alexmurray opened 1 month ago

alexmurray commented 1 month ago

It is quite common for applications to want to lock a file when writing to it - k permission should be granted in addition to w for write access otherwise errors like the following are seen when using audacity to try and save/open a file:

Sep 06 14:06:19 graphene kernel: audit: type=1400 audit(1725597379.439:8450): apparmor="DENIED" operation="file_lock" class="file" profile="snap.audacity.audacity" name=2F686F6D652F616D75727261792F5562756E747520536563757269747920506F64636173742F5553505F453233362E61757033 pid=789955 comm="audacity" requested_mask="wk" denied_mask="wk" fsuid=1000 ouid=1000

This path can be decoded using aa-decode:

aa-decode 2F686F6D652F616D75727261792F5562756E747520536563757269747920506F64636173742F5553505F453233362E61757033
Decoded: /home/amurray/Ubuntu Security Podcast/USP_E236.aup3

And we can see this matches a rule already granted as write access in the security center

image

alexmurray commented 1 month ago

cc @olivercalder I wasn't sure if this should be filed against prompting-client or snapd

sminez commented 1 month ago

This is one for snapd I suspect: the client is only able to respond to snapd in terms of rwx permissions which then get mapped to the reply to the kernel.

olivercalder commented 1 month ago

At the moment, we're abstracting away the distinction between AppArmor w, k and a permissions into simply "write", which grants all of these. This is to simplify life for the client/users who might not know/care about this distinction.

Here are where the mappings from AppArmor permission to "abstract" permission are defined: https://github.com/canonical/snapd/blob/8eda46e426b3f64157e4628f1e9cb534cadc7f72/interfaces/prompting/constraints.go#L130-L150

In particular:

"home": {
    "read":    notify.AA_MAY_READ | notify.AA_MAY_GETATTR,
    "write":   notify.AA_MAY_WRITE | notify.AA_MAY_APPEND | notify.AA_MAY_CREATE | notify.AA_MAY_DELETE | notify.AA_MAY_RENAME | notify.AA_MAY_SETATTR | notify.AA_MAY_CHMOD | notify.AA_MAY_LOCK | notify.AA_MAY_LINK,
    "execute": notify.AA_MAY_EXEC | notify.AA_EXEC_MMAP,
},

"write" is already mapped to AA_MAY_LOCK. So any rule which grants AppArmor w also grants k.

If you're hitting a problem with multiple prompts appearing when trying to (presumably) open and then lock the file, if you're not replying with a rule-creating reply (e.g. "Allow always") then the problem is likely just that the application is using two distinct syscalls, and the reply to the first doesn't affect the second. An "Allow always" reply should handle both syscalls with a single reply, however.

alexmurray commented 1 month ago

So something is still not working right - even after rebooting I can still reproduce this - I have granted what appears to be appropriate rules for read+write to the affected paths yet audacity still getting denied to lock the file:

Screenshot From 2024-09-09 09-38-57

Screenshot From 2024-09-09 09-39-17

Sep 09 09:39:12 graphene kernel: audit: type=1400 audit(1725840552.141:3196): apparmor="DENIED" operation="file_lock" class="file" profile="snap.audacity.audacity" name=2F686F6D652F616D75727261792F5562756E747520536563757269747920506F64636173742F5553505F453233332E61757033 pid=97149 comm="audacity" requested_mask="wk" denied_mask="wk" fsuid=1000 ouid=1000
$ aa-decode 2F686F6D652F616D75727261792F5562756E747520536563757269747920506F64636173742F5553505F453233332E61757033
Decoded: /home/amurray/Ubuntu Security Podcast/USP_E233.aup3
olivercalder commented 1 month ago

Could you please try to collect some journalctl logs with SNAPD_DEBUG=1 set? I'd recommend setting it in /etc/environment and restarting.

I'm curious if this might be related to the kernel bug for which JJ worked on a fix. In that case, there was an allow rule by snapd, but still an audit deny from the kernel. Seems like a similar problem here, if we see snapd sending back an explicit allow for the lock permission. If we don't see snapd sending back an allow, the logs should shed some light on what snapd is doing wrong.

alexmurray commented 1 month ago

Let me know if you more logs than the following:

Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: received prompt request from the kernel: {MsgNotificationOp:{MsgNotification:{MsgHeader:{Length:127 Version:3} NotificationType:APPARMOR_NOTIF_OP Signalled:0 NoCache:0 ID:4 Error:-13} Allow:0 Deny:4 Pid:10418 Label:snap.audacity.audacity Class:AA_CLASS_FILE Op:0} SUID:1000 OUID:1000 Name:/home/amurray/Ubuntu Security Podcast/USP_E237.aup3}
Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: received from kernel requests channel: &{10418 snap.audacity.audacity 1000 /home/amurray/Ubuntu Security Podcast/USP_E237.aup3 AA_CLASS_FILE read 0xc000164000 0}
Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: request allowed by existing rule: &{PID:10418 Label:snap.audacity.audacity SubjectUID:1000 Path:/home/amurray/Ubuntu Security Podcast/USP_E237.aup3 Class:AA_CLASS_FILE Permission:read replyChan:0xc000164000 replied:0}
Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: waiting prompt loop
Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: sending request response back to the kernel: {MsgNotification:{MsgHeader:{Length:0 Version:0} NotificationType:APPARMOR_NOTIF_RESP Signalled:0 NoCache:1 ID:4 Error:0} Error:0 Allow:4 Deny:0}
Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: received prompt request from the kernel: {MsgNotificationOp:{MsgNotification:{MsgHeader:{Length:127 Version:3} NotificationType:APPARMOR_NOTIF_OP Signalled:0 NoCache:0 ID:5 Error:-13} Allow:0 Deny:22 Pid:10418 Label:snap.audacity.audacity Class:AA_CLASS_FILE Op:0} SUID:1000 OUID:1000 Name:/home/amurray/Ubuntu Security Podcast/USP_E237.aup3}
Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: received from kernel requests channel: &{10418 snap.audacity.audacity 1000 /home/amurray/Ubuntu Security Podcast/USP_E237.aup3 AA_CLASS_FILE write|read|create 0xc000164230 0}
Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: request allowed by existing rule: &{PID:10418 Label:snap.audacity.audacity SubjectUID:1000 Path:/home/amurray/Ubuntu Security Podcast/USP_E237.aup3 Class:AA_CLASS_FILE Permission:write|read|create replyChan:0xc000164230 replied:0}
Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: waiting prompt loop
Sep 30 15:20:26 graphene snapd[4059]: logger.go:99: DEBUG: sending request response back to the kernel: {MsgNotification:{MsgHeader:{Length:0 Version:0} NotificationType:APPARMOR_NOTIF_RESP Signalled:0 NoCache:1 ID:5 Error:0} Error:0 Allow:22 Deny:0}
Sep 30 15:20:26 graphene kernel: audit: type=1400 audit(1727675426.620:804): apparmor="DENIED" operation="file_lock" class="file" profile="snap.audacity.audacity" name=2F686F6D652F616D75727261792F5562756E747520536563757269747920506F64636173742F5553505F453233372E61757033 pid=10418 comm="audacity" requested_mask="wk" denied_mask="wk" fsuid=1000 ouid=1000
Sep 30 15:20:26 graphene kernel: audit: type=1400 audit(1727675426.620:805): apparmor="DENIED" operation="file_lock" class="file" profile="snap.audacity.audacity" name=2F686F6D652F616D75727261792F5562756E747520536563757269747920506F64636173742F5553505F453233372E61757033 pid=10418 comm="audacity" requested_mask="wk" denied_mask="wk" fsuid=1000 ouid=1000
alexmurray commented 1 day ago

Any more progress on this? There is no way to workaround this other than disabling prompting entirely.