tty_audit.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * Creating audit events from TTY input.
  3. *
  4. * Copyright (C) 2007 Red Hat, Inc. All rights reserved. This copyrighted
  5. * material is made available to anyone wishing to use, modify, copy, or
  6. * redistribute it subject to the terms and conditions of the GNU General
  7. * Public License v.2.
  8. *
  9. * Authors: Miloslav Trmac <mitr@redhat.com>
  10. */
  11. #include <linux/audit.h>
  12. #include <linux/file.h>
  13. #include <linux/fdtable.h>
  14. #include <linux/tty.h>
  15. struct tty_audit_buf {
  16. atomic_t count;
  17. struct mutex mutex; /* Protects all data below */
  18. int major, minor; /* The TTY which the data is from */
  19. unsigned icanon:1;
  20. size_t valid;
  21. unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */
  22. };
  23. static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
  24. int icanon)
  25. {
  26. struct tty_audit_buf *buf;
  27. buf = kmalloc(sizeof(*buf), GFP_KERNEL);
  28. if (!buf)
  29. goto err;
  30. if (PAGE_SIZE != N_TTY_BUF_SIZE)
  31. buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
  32. else
  33. buf->data = (unsigned char *)__get_free_page(GFP_KERNEL);
  34. if (!buf->data)
  35. goto err_buf;
  36. atomic_set(&buf->count, 1);
  37. mutex_init(&buf->mutex);
  38. buf->major = major;
  39. buf->minor = minor;
  40. buf->icanon = icanon;
  41. buf->valid = 0;
  42. return buf;
  43. err_buf:
  44. kfree(buf);
  45. err:
  46. return NULL;
  47. }
  48. static void tty_audit_buf_free(struct tty_audit_buf *buf)
  49. {
  50. WARN_ON(buf->valid != 0);
  51. if (PAGE_SIZE != N_TTY_BUF_SIZE)
  52. kfree(buf->data);
  53. else
  54. free_page((unsigned long)buf->data);
  55. kfree(buf);
  56. }
  57. static void tty_audit_buf_put(struct tty_audit_buf *buf)
  58. {
  59. if (atomic_dec_and_test(&buf->count))
  60. tty_audit_buf_free(buf);
  61. }
  62. /**
  63. * tty_audit_buf_push - Push buffered data out
  64. *
  65. * Generate an audit message from the contents of @buf, which is owned by
  66. * @tsk with @loginuid. @buf->mutex must be locked.
  67. */
  68. static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
  69. unsigned int sessionid,
  70. struct tty_audit_buf *buf)
  71. {
  72. struct audit_buffer *ab;
  73. if (buf->valid == 0)
  74. return;
  75. if (audit_enabled == 0)
  76. return;
  77. ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
  78. if (ab) {
  79. char name[sizeof(tsk->comm)];
  80. audit_log_format(ab, "tty pid=%u uid=%u auid=%u ses=%u "
  81. "major=%d minor=%d comm=", tsk->pid, tsk->uid,
  82. loginuid, sessionid, buf->major, buf->minor);
  83. get_task_comm(name, tsk);
  84. audit_log_untrustedstring(ab, name);
  85. audit_log_format(ab, " data=");
  86. audit_log_n_untrustedstring(ab, buf->data, buf->valid);
  87. audit_log_end(ab);
  88. }
  89. buf->valid = 0;
  90. }
  91. /**
  92. * tty_audit_buf_push_current - Push buffered data out
  93. *
  94. * Generate an audit message from the contents of @buf, which is owned by
  95. * the current task. @buf->mutex must be locked.
  96. */
  97. static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
  98. {
  99. uid_t auid = audit_get_loginuid(current);
  100. unsigned int sessionid = audit_get_sessionid(current);
  101. tty_audit_buf_push(current, auid, sessionid, buf);
  102. }
  103. /**
  104. * tty_audit_exit - Handle a task exit
  105. *
  106. * Make sure all buffered data is written out and deallocate the buffer.
  107. * Only needs to be called if current->signal->tty_audit_buf != %NULL.
  108. */
  109. void tty_audit_exit(void)
  110. {
  111. struct tty_audit_buf *buf;
  112. spin_lock_irq(&current->sighand->siglock);
  113. buf = current->signal->tty_audit_buf;
  114. current->signal->tty_audit_buf = NULL;
  115. spin_unlock_irq(&current->sighand->siglock);
  116. if (!buf)
  117. return;
  118. mutex_lock(&buf->mutex);
  119. tty_audit_buf_push_current(buf);
  120. mutex_unlock(&buf->mutex);
  121. tty_audit_buf_put(buf);
  122. }
  123. /**
  124. * tty_audit_fork - Copy TTY audit state for a new task
  125. *
  126. * Set up TTY audit state in @sig from current. @sig needs no locking.
  127. */
  128. void tty_audit_fork(struct signal_struct *sig)
  129. {
  130. spin_lock_irq(&current->sighand->siglock);
  131. sig->audit_tty = current->signal->audit_tty;
  132. spin_unlock_irq(&current->sighand->siglock);
  133. sig->tty_audit_buf = NULL;
  134. }
  135. /**
  136. * tty_audit_push_task - Flush task's pending audit data
  137. */
  138. void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
  139. {
  140. struct tty_audit_buf *buf;
  141. spin_lock_irq(&tsk->sighand->siglock);
  142. buf = tsk->signal->tty_audit_buf;
  143. if (buf)
  144. atomic_inc(&buf->count);
  145. spin_unlock_irq(&tsk->sighand->siglock);
  146. if (!buf)
  147. return;
  148. mutex_lock(&buf->mutex);
  149. tty_audit_buf_push(tsk, loginuid, sessionid, buf);
  150. mutex_unlock(&buf->mutex);
  151. tty_audit_buf_put(buf);
  152. }
  153. /**
  154. * tty_audit_buf_get - Get an audit buffer.
  155. *
  156. * Get an audit buffer for @tty, allocate it if necessary. Return %NULL
  157. * if TTY auditing is disabled or out of memory. Otherwise, return a new
  158. * reference to the buffer.
  159. */
  160. static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
  161. {
  162. struct tty_audit_buf *buf, *buf2;
  163. buf = NULL;
  164. buf2 = NULL;
  165. spin_lock_irq(&current->sighand->siglock);
  166. if (likely(!current->signal->audit_tty))
  167. goto out;
  168. buf = current->signal->tty_audit_buf;
  169. if (buf) {
  170. atomic_inc(&buf->count);
  171. goto out;
  172. }
  173. spin_unlock_irq(&current->sighand->siglock);
  174. buf2 = tty_audit_buf_alloc(tty->driver->major,
  175. tty->driver->minor_start + tty->index,
  176. tty->icanon);
  177. if (buf2 == NULL) {
  178. audit_log_lost("out of memory in TTY auditing");
  179. return NULL;
  180. }
  181. spin_lock_irq(&current->sighand->siglock);
  182. if (!current->signal->audit_tty)
  183. goto out;
  184. buf = current->signal->tty_audit_buf;
  185. if (!buf) {
  186. current->signal->tty_audit_buf = buf2;
  187. buf = buf2;
  188. buf2 = NULL;
  189. }
  190. atomic_inc(&buf->count);
  191. /* Fall through */
  192. out:
  193. spin_unlock_irq(&current->sighand->siglock);
  194. if (buf2)
  195. tty_audit_buf_free(buf2);
  196. return buf;
  197. }
  198. /**
  199. * tty_audit_add_data - Add data for TTY auditing.
  200. *
  201. * Audit @data of @size from @tty, if necessary.
  202. */
  203. void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
  204. size_t size)
  205. {
  206. struct tty_audit_buf *buf;
  207. int major, minor;
  208. if (unlikely(size == 0))
  209. return;
  210. if (tty->driver->type == TTY_DRIVER_TYPE_PTY
  211. && tty->driver->subtype == PTY_TYPE_MASTER)
  212. return;
  213. buf = tty_audit_buf_get(tty);
  214. if (!buf)
  215. return;
  216. mutex_lock(&buf->mutex);
  217. major = tty->driver->major;
  218. minor = tty->driver->minor_start + tty->index;
  219. if (buf->major != major || buf->minor != minor
  220. || buf->icanon != tty->icanon) {
  221. tty_audit_buf_push_current(buf);
  222. buf->major = major;
  223. buf->minor = minor;
  224. buf->icanon = tty->icanon;
  225. }
  226. do {
  227. size_t run;
  228. run = N_TTY_BUF_SIZE - buf->valid;
  229. if (run > size)
  230. run = size;
  231. memcpy(buf->data + buf->valid, data, run);
  232. buf->valid += run;
  233. data += run;
  234. size -= run;
  235. if (buf->valid == N_TTY_BUF_SIZE)
  236. tty_audit_buf_push_current(buf);
  237. } while (size != 0);
  238. mutex_unlock(&buf->mutex);
  239. tty_audit_buf_put(buf);
  240. }
  241. /**
  242. * tty_audit_push - Push buffered data out
  243. *
  244. * Make sure no audit data is pending for @tty on the current process.
  245. */
  246. void tty_audit_push(struct tty_struct *tty)
  247. {
  248. struct tty_audit_buf *buf;
  249. spin_lock_irq(&current->sighand->siglock);
  250. if (likely(!current->signal->audit_tty)) {
  251. spin_unlock_irq(&current->sighand->siglock);
  252. return;
  253. }
  254. buf = current->signal->tty_audit_buf;
  255. if (buf)
  256. atomic_inc(&buf->count);
  257. spin_unlock_irq(&current->sighand->siglock);
  258. if (buf) {
  259. int major, minor;
  260. major = tty->driver->major;
  261. minor = tty->driver->minor_start + tty->index;
  262. mutex_lock(&buf->mutex);
  263. if (buf->major == major && buf->minor == minor)
  264. tty_audit_buf_push_current(buf);
  265. mutex_unlock(&buf->mutex);
  266. tty_audit_buf_put(buf);
  267. }
  268. }