[PATCH v1 1/2] Landlock: Add signal control
Tahera Fahimi <[email protected]>
| Newsgroups | dev.linux.lists.outreachy,org.kernel.vger.linux-kernel,org.kernel.vger.linux-security-module,org.kernel.vger.netdev |
|---|---|
| Message-ID | <36958dbc486e1f975f4d4ecdfa51ae65c2c4ced0.1720213293.git.fahimitahera@gmail.com> |
Currently, a sandbox process is not restricted to send a signal (e.g. SIGKILL) to a process outside of the sandbox environment. Ability to sending a signal for a sandboxed process should be scoped the same way abstract unix sockets are scoped. The same way as abstract unix socket, we extend "scoped" field in a ruleset with "LANDLOCK_SCOPED_SIGNAL" to specify that a ruleset will deny sending any signal from within a sandbox process to its parent(i.e. any parent sandbox or non-sandboxed procsses). Signed-off-by: Tahera Fahimi <[email protected]> --- include/uapi/linux/landlock.h | 3 +++ security/landlock/limits.h | 2 +- security/landlock/task.c | 49 +++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index 010aaca5b05a..878479a1b9dd 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -291,8 +291,11 @@ struct landlock_net_port_attr { * from connecting to an abstract unix socket created by a process * outside the related Landlock domain (e.g. a parent domain or a process * which is not sandboxed). + * - %LANDLOCK_SCOPED_SIGNAL: Restrict a sandboxed process from sending a signal + * to another process outside sandbox domain. */ /* clang-format off */ #define LANDLOCK_SCOPED_ABSTRACT_UNIX_SOCKET (1ULL << 0) +#define LANDLOCK_SCOPED_SIGNAL (1ULL << 1) /* clang-format on*/ #endif /* _UAPI_LINUX_LANDLOCK_H */ diff --git a/security/landlock/limits.h b/security/landlock/limits.h index eb01d0fb2165..fa28f9236407 100644 --- a/security/landlock/limits.h +++ b/security/landlock/limits.h @@ -26,7 +26,7 @@ #define LANDLOCK_MASK_ACCESS_NET ((LANDLOCK_LAST_ACCESS_NET << 1) - 1) #define LANDLOCK_NUM_ACCESS_NET __const_hweight64(LANDLOCK_MASK_ACCESS_NET) -#define LANDLOCK_LAST_SCOPE LANDLOCK_SCOPED_ABSTRACT_UNIX_SOCKET +#define LANDLOCK_LAST_SCOPE LANDLOCK_SCOPED_SIGNAL #define LANDLOCK_MASK_SCOPE ((LANDLOCK_LAST_SCOPE << 1) - 1) #define LANDLOCK_NUM_SCOPE __const_hweight64(LANDLOCK_MASK_SCOPE) /* clang-format on */ diff --git a/security/landlock/task.c b/security/landlock/task.c index acc6e0fbc111..caee485b97b2 100644 --- a/security/landlock/task.c +++ b/security/landlock/task.c @@ -168,11 +168,60 @@ static int hook_unix_may_send(struct socket *const sock, return -EPERM; } +static bool signal_is_scoped(const struct landlock_ruleset *const sender_dom, + struct task_struct *const target) +{ + const struct landlock_ruleset *target_dom = + landlock_get_task_domain(target); + + /* quick return if there is no domain or .scoped is not set */ + if (!sender_dom || !get_scoped_accesses(sender_dom)) + return true; + + if (!target_dom || !get_scoped_accesses(target_dom)) + return false; + + /* other is scoped, they connect if they are in the same domain */ + return domain_scope_le(sender_dom, target_dom); +} + +static int hook_task_kill(struct task_struct *const p, + struct kernel_siginfo *const info, const int sig, + const struct cred *const cred) +{ + const struct landlock_ruleset *const dom = + landlock_get_current_domain(); + bool ret = false; + + if (!cred) + ret = signal_is_scoped(dom, p); + else + ret = signal_is_scoped(landlock_cred(cred)->domain, p); + if (ret) + return 0; + return EPERM; +} + +static int hook_file_send_sigiotask(struct task_struct *tsk, + struct fown_struct *fown, int signum) +{ + const struct task_struct *result = + get_pid_task(fown->pid, fown->pid_type); + + const struct landlock_ruleset *const dom = + landlock_get_task_domain(result); + if (signal_is_scoped(dom, tsk)) + return 0; + return EPERM; +} + static struct security_hook_list landlock_hooks[] __ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme), LSM_HOOK_INIT(unix_stream_connect, hook_unix_stream_connect), LSM_HOOK_INIT(unix_may_send, hook_unix_may_send), + LSM_HOOK_INIT(task_kill, hook_task_kill), + LSM_HOOK_INIT(file_send_sigiotask, hook_file_send_sigiotask), }; __init void landlock_add_task_hooks(void) -- 2.34.1