cred.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Landlock - Credential hooks
  4. *
  5. * Copyright © 2019-2020 Mickaël Salaün <mic@digikod.net>
  6. * Copyright © 2019-2020 ANSSI
  7. * Copyright © 2021-2025 Microsoft Corporation
  8. */
  9. #ifndef _SECURITY_LANDLOCK_CRED_H
  10. #define _SECURITY_LANDLOCK_CRED_H
  11. #include <linux/container_of.h>
  12. #include <linux/cred.h>
  13. #include <linux/init.h>
  14. #include <linux/rcupdate.h>
  15. #include "access.h"
  16. #include "limits.h"
  17. #include "ruleset.h"
  18. #include "setup.h"
  19. /**
  20. * struct landlock_cred_security - Credential security blob
  21. *
  22. * This structure is packed to minimize the size of struct
  23. * landlock_file_security. However, it is always aligned in the LSM cred blob,
  24. * see lsm_set_blob_size().
  25. *
  26. * When updating this, also update landlock_cred_copy() if needed.
  27. */
  28. struct landlock_cred_security {
  29. /**
  30. * @domain: Immutable ruleset enforced on a task.
  31. */
  32. struct landlock_ruleset *domain;
  33. #ifdef CONFIG_AUDIT
  34. /**
  35. * @domain_exec: Bitmask identifying the domain layers that were enforced by
  36. * the current task's executed file (i.e. no new execve(2) since
  37. * landlock_restrict_self(2)).
  38. */
  39. u16 domain_exec;
  40. /**
  41. * @log_subdomains_off: Set if the domain descendants's log_status should be
  42. * set to %LANDLOCK_LOG_DISABLED. This is not a landlock_hierarchy
  43. * configuration because it applies to future descendant domains and it does
  44. * not require a current domain.
  45. */
  46. u8 log_subdomains_off : 1;
  47. #endif /* CONFIG_AUDIT */
  48. } __packed;
  49. #ifdef CONFIG_AUDIT
  50. /* Makes sure all layer executions can be stored. */
  51. static_assert(BITS_PER_TYPE(typeof_member(struct landlock_cred_security,
  52. domain_exec)) >=
  53. LANDLOCK_MAX_NUM_LAYERS);
  54. #endif /* CONFIG_AUDIT */
  55. static inline struct landlock_cred_security *
  56. landlock_cred(const struct cred *cred)
  57. {
  58. return cred->security + landlock_blob_sizes.lbs_cred;
  59. }
  60. static inline void landlock_cred_copy(struct landlock_cred_security *dst,
  61. const struct landlock_cred_security *src)
  62. {
  63. landlock_put_ruleset(dst->domain);
  64. *dst = *src;
  65. landlock_get_ruleset(src->domain);
  66. }
  67. static inline struct landlock_ruleset *landlock_get_current_domain(void)
  68. {
  69. return landlock_cred(current_cred())->domain;
  70. }
  71. /*
  72. * The call needs to come from an RCU read-side critical section.
  73. */
  74. static inline const struct landlock_ruleset *
  75. landlock_get_task_domain(const struct task_struct *const task)
  76. {
  77. return landlock_cred(__task_cred(task))->domain;
  78. }
  79. static inline bool landlocked(const struct task_struct *const task)
  80. {
  81. bool has_dom;
  82. if (task == current)
  83. return !!landlock_get_current_domain();
  84. rcu_read_lock();
  85. has_dom = !!landlock_get_task_domain(task);
  86. rcu_read_unlock();
  87. return has_dom;
  88. }
  89. /**
  90. * landlock_get_applicable_subject - Return the subject's Landlock credential
  91. * if its enforced domain applies to (i.e.
  92. * handles) at least one of the access rights
  93. * specified in @masks
  94. *
  95. * @cred: credential
  96. * @masks: access masks
  97. * @handle_layer: returned youngest layer handling a subset of @masks. Not set
  98. * if the function returns NULL.
  99. *
  100. * Returns: landlock_cred(@cred) if any access rights specified in @masks is
  101. * handled, or NULL otherwise.
  102. */
  103. static inline const struct landlock_cred_security *
  104. landlock_get_applicable_subject(const struct cred *const cred,
  105. const struct access_masks masks,
  106. size_t *const handle_layer)
  107. {
  108. const union access_masks_all masks_all = {
  109. .masks = masks,
  110. };
  111. const struct landlock_ruleset *domain;
  112. ssize_t layer_level;
  113. if (!cred)
  114. return NULL;
  115. domain = landlock_cred(cred)->domain;
  116. if (!domain)
  117. return NULL;
  118. for (layer_level = domain->num_layers - 1; layer_level >= 0;
  119. layer_level--) {
  120. union access_masks_all layer = {
  121. .masks = domain->access_masks[layer_level],
  122. };
  123. if (layer.all & masks_all.all) {
  124. if (handle_layer)
  125. *handle_layer = layer_level;
  126. return landlock_cred(cred);
  127. }
  128. }
  129. return NULL;
  130. }
  131. __init void landlock_add_cred_hooks(void);
  132. #endif /* _SECURITY_LANDLOCK_CRED_H */