libapparmor に AppArmor のプロファイルの適用などに関するライブラリが用意されている。その中に execve のタイミングでプロファイルを変更する aa_change_onexec というものがある。

これがどのように適用されるのか調べたのでメモ。

setprocattr を見ればわかるとおり、内部的には /proc/self/attr/execexec <profilename> を書き込んでいる。

...
ctl = procattr_path(tid, attr);
if (!ctl)
  goto out;

fd = open(ctl, O_WRONLY);
if (fd == -1) {
  goto out;
}

ret = write(fd, buf, len);
...
open("/proc/14963/attr/exec", O_WRONLY) = 4
write(4, "exec haconiwa-test", 18)      = 18
close(4)  

以下のようなプログラムを用いて確認してみる。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/syscall.h>

int main(void)
{
  int fd, res, len;
  char *path = NULL;
  char *buf = NULL;
  char *const cmd[] = {"/bin/bash", NULL};

  pid_t tid = syscall(SYS_gettid);

  asprintf(&path, "/proc/%d/attr/%s", tid, "exec");

  fd = open(path, O_WRONLY);
  if (fd == -1) { printf("failed open\n"); return 1;  }

  len = asprintf(&buf, "exec %s", "top-deny-profile");

  res = write(fd, buf, len);
  if (res == -1) { printf("Error: write(%d) \n", errno); exit(errno);  }
  close(fd);

  execv("/bin/bash", cmd);

  return 0;
}

top-deny-profile には deny /usr/bin/top mrwklx というルールを適用しており、top コマンドを使用できないようにしている。

上記プログラムを実行し、起動した bash では top コマンドは AppArmor によって拒否されることが確認できる。

$ gcc test.c
$ ./a.out
$ top
bash: /usr/bin/top: Permission denied

ref