AppArmor file permission 'append' denies file creation

Bug #1339099 reported by Damian Gerow on 2014-07-08
12
This bug affects 2 people
Affects Status Importance Assigned to Milestone
AppArmor
Low
Unassigned
apparmor (Ubuntu)
Low
Unassigned

Bug Description

This bug started as a question, to make sure I know how to computer before filing a bug: https://answers.launchpad.net/ubuntu/+source/apparmor/+question/251315

All this work is being done on an up-to-date 14.04 server running apparmor{-profiles,-utils} 2.8.95~2430-0ubuntu5.

While trying to sort out the appropriate AppArmor bits to control logging, I'm seeing the file permission 'append' deny create access to a file, where I would have expected this to not be denied. It also denies 'file_perm', but it's unclear if this would be expected to work. I can fix the situation by updating the profile to use the 'write' permission instead of 'append', but this is less than ideal.

http://manpages.ubuntu.com/manpages/trusty/en/man5/apparmor.d.5.html indicates that the 'append' file permission "Allows the program to have a limited appending only write access to the file."

In addition, http://wiki.apparmor.net/index.php/AppArmor_Core_Policy_Reference explicitly states that 'append' grants "permission to create, and extend a file. The append permission is limited that it only gives permission for applications to open a file with O_APPEND, it can not be used to enforce a generic file write is append only."

From https://en.opensuse.org/Archive:AppArmor_2_3_changes#Minor_Semantic_Changes, it appears as though granting 'create' permissions to 'append' is new in AppArmor 2.3.

However, in writing up a simple test program in Go, I'm seeing AppArmor deny create permissions where 'append' is allowed.

The Go code:
-----
func main() {
        logFile, err = os.OpenFile("/opt/test/log/test.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
        n, err := logFile.WriteString("direct write\n")
        if err != nil {
                fmt.Println(n, err)
        }
        log.SetOutput(logFile)
        log.Println("Log file initialized.")
        logFile.Close()
}
-----

The AppArmor profile:
-----
#include <tunables/global>

/opt/test/bin/test {
  #include <abstractions/base>

  /opt/test/log/test.log a,
}
-----

When set to enforce, the program spits out an error:
-----
% /opt/test/bin/test
0 invalid argument
%
-----

And AppArmor logs the DENIED message:
-----
kernel: [ 5687.957758] type=1400 audit(1404743687.548:92): apparmor="DENIED" operation="open" profile="/opt/test/bin/test" name="/opt/test/log/test.log" pid=7766 comm="test" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
-----

When set to complain, the program works as expected (as expected):
-----
% /opt/test/bin/test
%
-----

And AppArmor logs three calls with which it has an issue:
-----
kernel: [ 5949.505626] type=1400 audit(1404743948.872:98): apparmor="ALLOWED" operation="open" profile="/opt/test/bin/test" name="/opt/test/log/test.log" pid=8158 comm="test" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
kernel: [ 5949.505643] type=1400 audit(1404743948.872:99): apparmor="ALLOWED" operation="file_perm" profile="/opt/test/bin/test" name="/opt/test/log/test.log" pid=8158 comm="test" requested_mask="w" denied_mask="w" fsuid=1000 ouid=1000
kernel: [ 5949.505758] type=1400 audit(1404743948.872:100): apparmor="ALLOWED" operation="file_perm" profile="/opt/test/bin/test" name="/opt/test/log/test.log" pid=8158 comm="test" requested_mask="w" denied_mask="w" fsuid=1000 ouid=1000
-----

I'm not sure what's going on with the 'file_perm' stuff either -- I thought that would have required 'chmod', but that doesn't appear to be the case.

Seth Arnold (seth-arnold) wrote :

I did some testing with C to ensure Go wasn't doing something behind our backs:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {
 int fd, ret;

 fd = open("testing", O_WRONLY | O_APPEND
#if 1
         | O_CREAT , 0660);
#else
  );
#endif
 if (fd == -1) {
  perror("open");
  exit(1);
 } else {
  ret = write(fd, "hello\n", 6);
  if (ret != 6) {
   perror("write");
   exit(1);
  }
 }
 return 0;
}

Change the #if 1 to #if 0 to see the difference the O_CREAT flag has on the log output.

Here is the profile I used:

#include <tunables/global>

/home/sarnold/demos/append flags=(complain) {
  #include <abstractions/base>

  /home/sarnold/demos/append mr,
  /home/sarnold/demos/testing a,

}

Without O_CREAT here are the log messages:

type=AVC msg=audit(1404847907.250:4570): apparmor="ALLOWED" operation="file_perm" profile="/home/sarnold/demos/append" name="/home/sarnold/demos/testing" pid=4409 comm="append" requested_mask="w" denied_mask="w" fsuid=1000 ouid=1000

With O_CREAT here are the log messages:

type=AVC msg=audit(1404847924.482:4571): apparmor="ALLOWED" operation="open" profile="/home/sarnold/demos/append" name="/home/sarnold/demos/testing" pid=4419 comm="append" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
type=AVC msg=audit(1404847924.482:4572): apparmor="ALLOWED" operation="file_perm" profile="/home/sarnold/demos/append" name="/home/sarnold/demos/testing" pid=4419 comm="append" requested_mask="w" denied_mask="w" fsuid=1000 ouid=1000

It sure feels like the semantics of the 'a' permission have changed.

Thanks

Seth Arnold (seth-arnold) wrote :

Ah, right, launchpad destroys formatting. So here's append.c source in an attachment to make it tolerable to view.

Changed in apparmor (Ubuntu):
status: New → Confirmed
importance: Undecided → Low
Changed in apparmor:
status: New → Confirmed
importance: Undecided → Low
tags: added: aa-kernel aa-parser
Christian Boltz (cboltz) wrote :

This bug could be the reason for bug 1324608

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Related questions

Bug attachments