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 12 #include <linux/audit.h> 13 #include <linux/slab.h> 14 #include <linux/tty.h> 15 16 struct tty_audit_buf { 17 atomic_t count; 18 struct mutex mutex; /* Protects all data below */ 19 int major, minor; /* The TTY which the data is from */ 20 unsigned icanon:1; 21 size_t valid; 22 unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ 23 }; 24 25 static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, 26 unsigned icanon) 27 { 28 struct tty_audit_buf *buf; 29 30 buf = kmalloc(sizeof(*buf), GFP_KERNEL); 31 if (!buf) 32 goto err; 33 buf->data = kmalloc(N_TTY_BUF_SIZE, 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 44 err_buf: 45 kfree(buf); 46 err: 47 return NULL; 48 } 49 50 static void tty_audit_buf_free(struct tty_audit_buf *buf) 51 { 52 WARN_ON(buf->valid != 0); 53 kfree(buf->data); 54 kfree(buf); 55 } 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 static void tty_audit_log(const char *description, int major, int minor, 64 unsigned char *data, size_t size) 65 { 66 struct audit_buffer *ab; 67 struct task_struct *tsk = current; 68 uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); 69 uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); 70 u32 sessionid = audit_get_sessionid(tsk); 71 72 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); 73 if (ab) { 74 char name[sizeof(tsk->comm)]; 75 76 audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" 77 " minor=%d comm=", description, tsk->pid, uid, 78 loginuid, sessionid, major, minor); 79 get_task_comm(name, tsk); 80 audit_log_untrustedstring(ab, name); 81 audit_log_format(ab, " data="); 82 audit_log_n_hex(ab, data, size); 83 audit_log_end(ab); 84 } 85 } 86 87 /** 88 * tty_audit_buf_push - Push buffered data out 89 * 90 * Generate an audit message from the contents of @buf, which is owned by 91 * the current task. @buf->mutex must be locked. 92 */ 93 static void tty_audit_buf_push(struct tty_audit_buf *buf) 94 { 95 if (buf->valid == 0) 96 return; 97 if (audit_enabled == 0) { 98 buf->valid = 0; 99 return; 100 } 101 tty_audit_log("tty", buf->major, buf->minor, buf->data, buf->valid); 102 buf->valid = 0; 103 } 104 105 /** 106 * tty_audit_exit - Handle a task exit 107 * 108 * Make sure all buffered data is written out and deallocate the buffer. 109 * Only needs to be called if current->signal->tty_audit_buf != %NULL. 110 */ 111 void tty_audit_exit(void) 112 { 113 struct tty_audit_buf *buf; 114 115 buf = current->signal->tty_audit_buf; 116 current->signal->tty_audit_buf = NULL; 117 if (!buf) 118 return; 119 120 mutex_lock(&buf->mutex); 121 tty_audit_buf_push(buf); 122 mutex_unlock(&buf->mutex); 123 124 tty_audit_buf_put(buf); 125 } 126 127 /** 128 * tty_audit_fork - Copy TTY audit state for a new task 129 * 130 * Set up TTY audit state in @sig from current. @sig needs no locking. 131 */ 132 void tty_audit_fork(struct signal_struct *sig) 133 { 134 sig->audit_tty = current->signal->audit_tty; 135 sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd; 136 } 137 138 /** 139 * tty_audit_tiocsti - Log TIOCSTI 140 */ 141 void tty_audit_tiocsti(struct tty_struct *tty, char ch) 142 { 143 struct tty_audit_buf *buf; 144 int major, minor, should_audit; 145 unsigned long flags; 146 147 spin_lock_irqsave(¤t->sighand->siglock, flags); 148 should_audit = current->signal->audit_tty; 149 buf = current->signal->tty_audit_buf; 150 if (buf) 151 atomic_inc(&buf->count); 152 spin_unlock_irqrestore(¤t->sighand->siglock, flags); 153 154 major = tty->driver->major; 155 minor = tty->driver->minor_start + tty->index; 156 if (buf) { 157 mutex_lock(&buf->mutex); 158 if (buf->major == major && buf->minor == minor) 159 tty_audit_buf_push(buf); 160 mutex_unlock(&buf->mutex); 161 tty_audit_buf_put(buf); 162 } 163 164 if (should_audit && audit_enabled) { 165 kuid_t auid; 166 unsigned int sessionid; 167 168 auid = audit_get_loginuid(current); 169 sessionid = audit_get_sessionid(current); 170 tty_audit_log("ioctl=TIOCSTI", major, minor, &ch, 1); 171 } 172 } 173 174 /** 175 * tty_audit_push_current - Flush current's pending audit data 176 * 177 * Try to lock sighand and get a reference to the tty audit buffer if available. 178 * Flush the buffer or return an appropriate error code. 179 */ 180 int tty_audit_push_current(void) 181 { 182 struct tty_audit_buf *buf = ERR_PTR(-EPERM); 183 struct task_struct *tsk = current; 184 unsigned long flags; 185 186 if (!lock_task_sighand(tsk, &flags)) 187 return -ESRCH; 188 189 if (tsk->signal->audit_tty) { 190 buf = tsk->signal->tty_audit_buf; 191 if (buf) 192 atomic_inc(&buf->count); 193 } 194 unlock_task_sighand(tsk, &flags); 195 196 /* 197 * Return 0 when signal->audit_tty set 198 * but tsk->signal->tty_audit_buf == NULL. 199 */ 200 if (!buf || IS_ERR(buf)) 201 return PTR_ERR(buf); 202 203 mutex_lock(&buf->mutex); 204 tty_audit_buf_push(buf); 205 mutex_unlock(&buf->mutex); 206 207 tty_audit_buf_put(buf); 208 return 0; 209 } 210 211 /** 212 * tty_audit_buf_get - Get an audit buffer. 213 * 214 * Get an audit buffer for @tty, allocate it if necessary. Return %NULL 215 * if TTY auditing is disabled or out of memory. Otherwise, return a new 216 * reference to the buffer. 217 */ 218 static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, 219 unsigned icanon) 220 { 221 struct tty_audit_buf *buf, *buf2; 222 unsigned long flags; 223 224 buf = NULL; 225 buf2 = NULL; 226 spin_lock_irqsave(¤t->sighand->siglock, flags); 227 if (likely(!current->signal->audit_tty)) 228 goto out; 229 buf = current->signal->tty_audit_buf; 230 if (buf) { 231 atomic_inc(&buf->count); 232 goto out; 233 } 234 spin_unlock_irqrestore(¤t->sighand->siglock, flags); 235 236 buf2 = tty_audit_buf_alloc(tty->driver->major, 237 tty->driver->minor_start + tty->index, 238 icanon); 239 if (buf2 == NULL) { 240 audit_log_lost("out of memory in TTY auditing"); 241 return NULL; 242 } 243 244 spin_lock_irqsave(¤t->sighand->siglock, flags); 245 if (!current->signal->audit_tty) 246 goto out; 247 buf = current->signal->tty_audit_buf; 248 if (!buf) { 249 current->signal->tty_audit_buf = buf2; 250 buf = buf2; 251 buf2 = NULL; 252 } 253 atomic_inc(&buf->count); 254 /* Fall through */ 255 out: 256 spin_unlock_irqrestore(¤t->sighand->siglock, flags); 257 if (buf2) 258 tty_audit_buf_free(buf2); 259 return buf; 260 } 261 262 /** 263 * tty_audit_add_data - Add data for TTY auditing. 264 * 265 * Audit @data of @size from @tty, if necessary. 266 */ 267 void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, 268 size_t size, unsigned icanon) 269 { 270 struct tty_audit_buf *buf; 271 int major, minor; 272 int audit_log_tty_passwd; 273 unsigned long flags; 274 275 if (unlikely(size == 0)) 276 return; 277 278 spin_lock_irqsave(¤t->sighand->siglock, flags); 279 audit_log_tty_passwd = current->signal->audit_tty_log_passwd; 280 spin_unlock_irqrestore(¤t->sighand->siglock, flags); 281 if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) 282 return; 283 284 if (tty->driver->type == TTY_DRIVER_TYPE_PTY 285 && tty->driver->subtype == PTY_TYPE_MASTER) 286 return; 287 288 buf = tty_audit_buf_get(tty, icanon); 289 if (!buf) 290 return; 291 292 mutex_lock(&buf->mutex); 293 major = tty->driver->major; 294 minor = tty->driver->minor_start + tty->index; 295 if (buf->major != major || buf->minor != minor 296 || buf->icanon != icanon) { 297 tty_audit_buf_push(buf); 298 buf->major = major; 299 buf->minor = minor; 300 buf->icanon = icanon; 301 } 302 do { 303 size_t run; 304 305 run = N_TTY_BUF_SIZE - buf->valid; 306 if (run > size) 307 run = size; 308 memcpy(buf->data + buf->valid, data, run); 309 buf->valid += run; 310 data += run; 311 size -= run; 312 if (buf->valid == N_TTY_BUF_SIZE) 313 tty_audit_buf_push(buf); 314 } while (size != 0); 315 mutex_unlock(&buf->mutex); 316 tty_audit_buf_put(buf); 317 } 318 319 /** 320 * tty_audit_push - Push buffered data out 321 * 322 * Make sure no audit data is pending for @tty on the current process. 323 */ 324 void tty_audit_push(struct tty_struct *tty) 325 { 326 struct tty_audit_buf *buf; 327 unsigned long flags; 328 329 spin_lock_irqsave(¤t->sighand->siglock, flags); 330 if (likely(!current->signal->audit_tty)) { 331 spin_unlock_irqrestore(¤t->sighand->siglock, flags); 332 return; 333 } 334 buf = current->signal->tty_audit_buf; 335 if (buf) 336 atomic_inc(&buf->count); 337 spin_unlock_irqrestore(¤t->sighand->siglock, flags); 338 339 if (buf) { 340 int major, minor; 341 342 major = tty->driver->major; 343 minor = tty->driver->minor_start + tty->index; 344 mutex_lock(&buf->mutex); 345 if (buf->major == major && buf->minor == minor) 346 tty_audit_buf_push(buf); 347 mutex_unlock(&buf->mutex); 348 tty_audit_buf_put(buf); 349 } 350 } 351