tty_audit.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Creating audit events from TTY input.
  4. *
  5. * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
  6. *
  7. * Authors: Miloslav Trmac <mitr@redhat.com>
  8. */
  9. #include <linux/audit.h>
  10. #include <linux/slab.h>
  11. #include <linux/tty.h>
  12. #include "tty.h"
  13. #define TTY_AUDIT_BUF_SIZE 4096
  14. struct tty_audit_buf {
  15. struct mutex mutex; /* Protects all data below */
  16. dev_t dev; /* The TTY which the data is from */
  17. bool icanon;
  18. size_t valid;
  19. u8 *data; /* Allocated size TTY_AUDIT_BUF_SIZE */
  20. };
  21. static struct tty_audit_buf *tty_audit_buf_ref(void)
  22. {
  23. struct tty_audit_buf *buf;
  24. buf = current->signal->tty_audit_buf;
  25. WARN_ON(buf == ERR_PTR(-ESRCH));
  26. return buf;
  27. }
  28. static struct tty_audit_buf *tty_audit_buf_alloc(void)
  29. {
  30. struct tty_audit_buf *buf;
  31. buf = kzalloc_obj(*buf);
  32. if (!buf)
  33. goto err;
  34. buf->data = kmalloc(TTY_AUDIT_BUF_SIZE, GFP_KERNEL);
  35. if (!buf->data)
  36. goto err_buf;
  37. mutex_init(&buf->mutex);
  38. return buf;
  39. err_buf:
  40. kfree(buf);
  41. err:
  42. return NULL;
  43. }
  44. static void tty_audit_buf_free(struct tty_audit_buf *buf)
  45. {
  46. WARN_ON(buf->valid != 0);
  47. kfree(buf->data);
  48. kfree(buf);
  49. }
  50. static void tty_audit_log(const char *description, dev_t dev,
  51. const u8 *data, size_t size)
  52. {
  53. struct audit_buffer *ab;
  54. pid_t pid = task_pid_nr(current);
  55. uid_t uid = from_kuid(&init_user_ns, task_uid(current));
  56. uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current));
  57. unsigned int sessionid = audit_get_sessionid(current);
  58. char name[TASK_COMM_LEN];
  59. ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_TTY);
  60. if (!ab)
  61. return;
  62. audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d minor=%d comm=",
  63. description, pid, uid, loginuid, sessionid,
  64. MAJOR(dev), MINOR(dev));
  65. get_task_comm(name, current);
  66. audit_log_untrustedstring(ab, name);
  67. audit_log_format(ab, " data=");
  68. audit_log_n_hex(ab, data, size);
  69. audit_log_end(ab);
  70. }
  71. /*
  72. * tty_audit_buf_push - Push buffered data out
  73. *
  74. * Generate an audit message from the contents of @buf, which is owned by
  75. * the current task. @buf->mutex must be locked.
  76. */
  77. static void tty_audit_buf_push(struct tty_audit_buf *buf)
  78. {
  79. if (buf->valid == 0)
  80. return;
  81. if (audit_enabled == AUDIT_OFF) {
  82. buf->valid = 0;
  83. return;
  84. }
  85. tty_audit_log("tty", buf->dev, buf->data, buf->valid);
  86. buf->valid = 0;
  87. }
  88. /**
  89. * tty_audit_exit - Handle a task exit
  90. *
  91. * Make sure all buffered data is written out and deallocate the buffer.
  92. * Only needs to be called if current->signal->tty_audit_buf != %NULL.
  93. *
  94. * The process is single-threaded at this point; no other threads share
  95. * current->signal.
  96. */
  97. void tty_audit_exit(void)
  98. {
  99. struct tty_audit_buf *buf;
  100. buf = xchg(&current->signal->tty_audit_buf, ERR_PTR(-ESRCH));
  101. if (!buf)
  102. return;
  103. tty_audit_buf_push(buf);
  104. tty_audit_buf_free(buf);
  105. }
  106. /*
  107. * tty_audit_fork - Copy TTY audit state for a new task
  108. *
  109. * Set up TTY audit state in @sig from current. @sig needs no locking.
  110. */
  111. void tty_audit_fork(struct signal_struct *sig)
  112. {
  113. sig->audit_tty = current->signal->audit_tty;
  114. }
  115. /*
  116. * tty_audit_tiocsti - Log TIOCSTI
  117. */
  118. void tty_audit_tiocsti(const struct tty_struct *tty, u8 ch)
  119. {
  120. dev_t dev;
  121. dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
  122. if (tty_audit_push())
  123. return;
  124. if (audit_enabled)
  125. tty_audit_log("ioctl=TIOCSTI", dev, &ch, 1);
  126. }
  127. /*
  128. * tty_audit_push - Flush current's pending audit data
  129. *
  130. * Returns 0 if success, -EPERM if tty audit is disabled
  131. */
  132. int tty_audit_push(void)
  133. {
  134. struct tty_audit_buf *buf;
  135. if (~current->signal->audit_tty & AUDIT_TTY_ENABLE)
  136. return -EPERM;
  137. buf = tty_audit_buf_ref();
  138. if (!IS_ERR_OR_NULL(buf)) {
  139. mutex_lock(&buf->mutex);
  140. tty_audit_buf_push(buf);
  141. mutex_unlock(&buf->mutex);
  142. }
  143. return 0;
  144. }
  145. /*
  146. * tty_audit_buf_get - Get an audit buffer.
  147. *
  148. * Get an audit buffer, allocate it if necessary. Return %NULL
  149. * if out of memory or ERR_PTR(-ESRCH) if tty_audit_exit() has already
  150. * occurred. Otherwise, return a new reference to the buffer.
  151. */
  152. static struct tty_audit_buf *tty_audit_buf_get(void)
  153. {
  154. struct tty_audit_buf *buf;
  155. buf = tty_audit_buf_ref();
  156. if (buf)
  157. return buf;
  158. buf = tty_audit_buf_alloc();
  159. if (buf == NULL) {
  160. audit_log_lost("out of memory in TTY auditing");
  161. return NULL;
  162. }
  163. /* Race to use this buffer, free it if another wins */
  164. if (cmpxchg(&current->signal->tty_audit_buf, NULL, buf) != NULL)
  165. tty_audit_buf_free(buf);
  166. return tty_audit_buf_ref();
  167. }
  168. /*
  169. * tty_audit_add_data - Add data for TTY auditing.
  170. *
  171. * Audit @data of @size from @tty, if necessary.
  172. */
  173. void tty_audit_add_data(const struct tty_struct *tty, const void *data,
  174. size_t size)
  175. {
  176. struct tty_audit_buf *buf;
  177. unsigned int audit_tty;
  178. bool icanon = L_ICANON(tty);
  179. dev_t dev;
  180. audit_tty = READ_ONCE(current->signal->audit_tty);
  181. if (~audit_tty & AUDIT_TTY_ENABLE)
  182. return;
  183. if (unlikely(size == 0))
  184. return;
  185. if (tty->driver->type == TTY_DRIVER_TYPE_PTY
  186. && tty->driver->subtype == PTY_TYPE_MASTER)
  187. return;
  188. if ((~audit_tty & AUDIT_TTY_LOG_PASSWD) && icanon && !L_ECHO(tty))
  189. return;
  190. buf = tty_audit_buf_get();
  191. if (IS_ERR_OR_NULL(buf))
  192. return;
  193. mutex_lock(&buf->mutex);
  194. dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
  195. if (buf->dev != dev || buf->icanon != icanon) {
  196. tty_audit_buf_push(buf);
  197. buf->dev = dev;
  198. buf->icanon = icanon;
  199. }
  200. do {
  201. size_t run;
  202. run = TTY_AUDIT_BUF_SIZE - buf->valid;
  203. if (run > size)
  204. run = size;
  205. memcpy(buf->data + buf->valid, data, run);
  206. buf->valid += run;
  207. data += run;
  208. size -= run;
  209. if (buf->valid == TTY_AUDIT_BUF_SIZE)
  210. tty_audit_buf_push(buf);
  211. } while (size != 0);
  212. mutex_unlock(&buf->mutex);
  213. }