Skip to content
  • Kentaro Takeda's avatar
    LSM adapter functions. · f7433243
    Kentaro Takeda authored
    
    
    DAC's permissions and TOMOYO's permissions are not one-to-one mapping.
    
    Regarding DAC, there are "read", "write", "execute" permissions.
    Regarding TOMOYO, there are "allow_read", "allow_write", "allow_read/write",
    "allow_execute", "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
    "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar",
    "allow_truncate", "allow_symlink", "allow_rewrite", "allow_link",
    "allow_rename" permissions.
    
    +----------------------------------+----------------------------------+
    | requested operation              | required TOMOYO's permission     |
    +----------------------------------+----------------------------------+
    | sys_open(O_RDONLY)               | allow_read                       |
    +----------------------------------+----------------------------------+
    | sys_open(O_WRONLY)               | allow_write                      |
    +----------------------------------+----------------------------------+
    | sys_open(O_RDWR)                 | allow_read/write                 |
    +----------------------------------+----------------------------------+
    | open_exec() from do_execve()     | allow_execute                    |
    +----------------------------------+----------------------------------+
    | open_exec() from !do_execve()    | allow_read                       |
    +----------------------------------+----------------------------------+
    | sys_read()                       | (none)                           |
    +----------------------------------+----------------------------------+
    | sys_write()                      | (none)                           |
    +----------------------------------+----------------------------------+
    | sys_mmap()                       | (none)                           |
    +----------------------------------+----------------------------------+
    | sys_uselib()                     | allow_read                       |
    +----------------------------------+----------------------------------+
    | sys_open(O_CREAT)                | allow_create                     |
    +----------------------------------+----------------------------------+
    | sys_open(O_TRUNC)                | allow_truncate                   |
    +----------------------------------+----------------------------------+
    | sys_truncate()                   | allow_truncate                   |
    +----------------------------------+----------------------------------+
    | sys_ftruncate()                  | allow_truncate                   |
    +----------------------------------+----------------------------------+
    | sys_open() without O_APPEND      | allow_rewrite                    |
    +----------------------------------+----------------------------------+
    | setfl() without O_APPEND         | allow_rewrite                    |
    +----------------------------------+----------------------------------+
    | sys_sysctl() for writing         | allow_write                      |
    +----------------------------------+----------------------------------+
    | sys_sysctl() for reading         | allow_read                       |
    +----------------------------------+----------------------------------+
    | sys_unlink()                     | allow_unlink                     |
    +----------------------------------+----------------------------------+
    | sys_mknod(S_IFREG)               | allow_create                     |
    +----------------------------------+----------------------------------+
    | sys_mknod(0)                     | allow_create                     |
    +----------------------------------+----------------------------------+
    | sys_mknod(S_IFIFO)               | allow_mkfifo                     |
    +----------------------------------+----------------------------------+
    | sys_mknod(S_IFSOCK)              | allow_mksock                     |
    +----------------------------------+----------------------------------+
    | sys_bind(AF_UNIX)                | allow_mksock                     |
    +----------------------------------+----------------------------------+
    | sys_mknod(S_IFBLK)               | allow_mkblock                    |
    +----------------------------------+----------------------------------+
    | sys_mknod(S_IFCHR)               | allow_mkchar                     |
    +----------------------------------+----------------------------------+
    | sys_symlink()                    | allow_symlink                    |
    +----------------------------------+----------------------------------+
    | sys_mkdir()                      | allow_mkdir                      |
    +----------------------------------+----------------------------------+
    | sys_rmdir()                      | allow_rmdir                      |
    +----------------------------------+----------------------------------+
    | sys_link()                       | allow_link                       |
    +----------------------------------+----------------------------------+
    | sys_rename()                     | allow_rename                     |
    +----------------------------------+----------------------------------+
    
    TOMOYO requires "allow_execute" permission of a pathname passed to do_execve()
    but does not require "allow_read" permission of that pathname.
    Let's consider 3 patterns (statically linked, dynamically linked,
    shell script). This description is to some degree simplified.
    
      $ cat hello.c
      #include <stdio.h>
      int main() {
              printf("Hello\n");
              return 0;
      }
      $ cat hello.sh
      #! /bin/sh
      echo "Hello"
      $ gcc -static -o hello-static hello.c
      $ gcc -o hello-dynamic hello.c
      $ chmod 755 hello.sh
    
    Case 1 -- Executing hello-static from bash.
    
      (1) The bash process calls fork() and the child process requests
          do_execve("hello-static").
    
      (2) The kernel checks "allow_execute hello-static" from "bash" domain.
    
      (3) The kernel calculates "bash hello-static" as the domain to transit to.
    
      (4) The kernel overwrites the child process by "hello-static".
    
      (5) The child process transits to "bash hello-static" domain.
    
      (6) The "hello-static" starts and finishes.
    
    Case 2 -- Executing hello-dynamic from bash.
    
      (1) The bash process calls fork() and the child process requests
          do_execve("hello-dynamic").
    
      (2) The kernel checks "allow_execute hello-dynamic" from "bash" domain.
    
      (3) The kernel calculates "bash hello-dynamic" as the domain to transit to.
    
      (4) The kernel checks "allow_read ld-linux.so" from "bash hello-dynamic"
          domain. I think permission to access ld-linux.so should be charged
          hello-dynamic program, for "hello-dynamic needs ld-linux.so" is not
          a fault of bash program.
    
      (5) The kernel overwrites the child process by "hello-dynamic".
    
      (6) The child process transits to "bash hello-dynamic" domain.
    
      (7) The "hello-dynamic" starts and finishes.
    
    Case 3 -- Executing hello.sh from bash.
    
      (1) The bash process calls fork() and the child process requests
          do_execve("hello.sh").
    
      (2) The kernel checks "allow_execute hello.sh" from "bash" domain.
    
      (3) The kernel calculates "bash hello.sh" as the domain to transit to.
    
      (4) The kernel checks "allow_read /bin/sh" from "bash hello.sh" domain.
          I think permission to access /bin/sh should be charged hello.sh program,
          for "hello.sh needs /bin/sh" is not a fault of bash program.
    
      (5) The kernel overwrites the child process by "/bin/sh".
    
      (6) The child process transits to "bash hello.sh" domain.
    
      (7) The "/bin/sh" requests open("hello.sh").
    
      (8) The kernel checks "allow_read hello.sh" from  "bash hello.sh" domain.
    
      (9) The "/bin/sh" starts and finishes.
    
    Whether a file is interpreted as a program or not depends on an application.
    The kernel cannot know whether the file is interpreted as a program or not.
    Thus, TOMOYO treats "hello-static" "hello-dynamic" "ld-linux.so" "hello.sh"
    "/bin/sh" equally as merely files; no distinction between executable and
    non-executable. Therefore, TOMOYO doesn't check DAC's execute permission.
    TOMOYO checks "allow_read" permission instead.
    
    Calling do_execve() is a bold gesture that an old program's instance (i.e.
    current process) is ready to be overwritten by a new program and is ready to
    transfer control to the new program. To split purview of programs, TOMOYO
    requires "allow_execute" permission of the new program against the old
    program's instance and performs domain transition. If do_execve() succeeds,
    the old program is no longer responsible against the consequence of the new
    program's behavior. Only the new program is responsible for all consequences.
    
    But TOMOYO doesn't require "allow_read" permission of the new program.
    If TOMOYO requires "allow_read" permission of the new program, TOMOYO will
    allow an attacker (who hijacked the old program's instance) to open the new
    program and steal data from the new program. Requiring "allow_read" permission
    will widen purview of the old program.
    
    Not requiring "allow_read" permission of the new program against the old
    program's instance is my design for reducing purview of the old program.
    To be able to know whether the current process is in do_execve() or not,
    I want to add in_execve flag to "task_struct".
    
    Signed-off-by: default avatarKentaro Takeda <takedakn@nttdata.co.jp>
    Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
    Signed-off-by: default avatarToshiharu Harada <haradats@nttdata.co.jp>
    Signed-off-by: default avatarJames Morris <jmorris@namei.org>
    f7433243