OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [tty_audit.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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/file.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
                                                 int icanon)
27
{
28
        struct tty_audit_buf *buf;
29
 
30
        buf = kmalloc(sizeof (*buf), GFP_KERNEL);
31
        if (!buf)
32
                goto err;
33
        if (PAGE_SIZE != N_TTY_BUF_SIZE)
34
                buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
35
        else
36
                buf->data = (unsigned char *)__get_free_page(GFP_KERNEL);
37
        if (!buf->data)
38
                goto err_buf;
39
        atomic_set(&buf->count, 1);
40
        mutex_init(&buf->mutex);
41
        buf->major = major;
42
        buf->minor = minor;
43
        buf->icanon = icanon;
44
        buf->valid = 0;
45
        return buf;
46
 
47
err_buf:
48
        kfree(buf);
49
err:
50
        return NULL;
51
}
52
 
53
static void tty_audit_buf_free(struct tty_audit_buf *buf)
54
{
55
        WARN_ON(buf->valid != 0);
56
        if (PAGE_SIZE != N_TTY_BUF_SIZE)
57
                kfree(buf->data);
58
        else
59
                free_page((unsigned long)buf->data);
60
        kfree(buf);
61
}
62
 
63
static void tty_audit_buf_put(struct tty_audit_buf *buf)
64
{
65
        if (atomic_dec_and_test(&buf->count))
66
                tty_audit_buf_free(buf);
67
}
68
 
69
/**
70
 *      tty_audit_buf_push      -       Push buffered data out
71
 *
72
 *      Generate an audit message from the contents of @buf, which is owned by
73
 *      @tsk with @loginuid.  @buf->mutex must be locked.
74
 */
75
static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
76
                               struct tty_audit_buf *buf)
77
{
78
        struct audit_buffer *ab;
79
 
80
        if (buf->valid == 0)
81
                return;
82
        if (audit_enabled == 0)
83
                return;
84
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
85
        if (ab) {
86
                char name[sizeof(tsk->comm)];
87
 
88
                audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d "
89
                                 "minor=%d comm=", tsk->pid, tsk->uid,
90
                                 loginuid, buf->major, buf->minor);
91
                get_task_comm(name, tsk);
92
                audit_log_untrustedstring(ab, name);
93
                audit_log_format(ab, " data=");
94
                audit_log_n_untrustedstring(ab, buf->valid, buf->data);
95
                audit_log_end(ab);
96
        }
97
        buf->valid = 0;
98
}
99
 
100
/**
101
 *      tty_audit_buf_push_current      -       Push buffered data out
102
 *
103
 *      Generate an audit message from the contents of @buf, which is owned by
104
 *      the current task.  @buf->mutex must be locked.
105
 */
106
static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
107
{
108
        tty_audit_buf_push(current, audit_get_loginuid(current->audit_context),
109
                           buf);
110
}
111
 
112
/**
113
 *      tty_audit_exit  -       Handle a task exit
114
 *
115
 *      Make sure all buffered data is written out and deallocate the buffer.
116
 *      Only needs to be called if current->signal->tty_audit_buf != %NULL.
117
 */
118
void tty_audit_exit(void)
119
{
120
        struct tty_audit_buf *buf;
121
 
122
        spin_lock_irq(&current->sighand->siglock);
123
        buf = current->signal->tty_audit_buf;
124
        current->signal->tty_audit_buf = NULL;
125
        spin_unlock_irq(&current->sighand->siglock);
126
        if (!buf)
127
                return;
128
 
129
        mutex_lock(&buf->mutex);
130
        tty_audit_buf_push_current(buf);
131
        mutex_unlock(&buf->mutex);
132
 
133
        tty_audit_buf_put(buf);
134
}
135
 
136
/**
137
 *      tty_audit_fork  -       Copy TTY audit state for a new task
138
 *
139
 *      Set up TTY audit state in @sig from current.  @sig needs no locking.
140
 */
141
void tty_audit_fork(struct signal_struct *sig)
142
{
143
        spin_lock_irq(&current->sighand->siglock);
144
        sig->audit_tty = current->signal->audit_tty;
145
        spin_unlock_irq(&current->sighand->siglock);
146
        sig->tty_audit_buf = NULL;
147
}
148
 
149
/**
150
 *      tty_audit_push_task     -       Flush task's pending audit data
151
 */
152
void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
153
{
154
        struct tty_audit_buf *buf;
155
 
156
        spin_lock_irq(&tsk->sighand->siglock);
157
        buf = tsk->signal->tty_audit_buf;
158
        if (buf)
159
                atomic_inc(&buf->count);
160
        spin_unlock_irq(&tsk->sighand->siglock);
161
        if (!buf)
162
                return;
163
 
164
        mutex_lock(&buf->mutex);
165
        tty_audit_buf_push(tsk, loginuid, buf);
166
        mutex_unlock(&buf->mutex);
167
 
168
        tty_audit_buf_put(buf);
169
}
170
 
171
/**
172
 *      tty_audit_buf_get       -       Get an audit buffer.
173
 *
174
 *      Get an audit buffer for @tty, allocate it if necessary.  Return %NULL
175
 *      if TTY auditing is disabled or out of memory.  Otherwise, return a new
176
 *      reference to the buffer.
177
 */
178
static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
179
{
180
        struct tty_audit_buf *buf, *buf2;
181
 
182
        buf = NULL;
183
        buf2 = NULL;
184
        spin_lock_irq(&current->sighand->siglock);
185
        if (likely(!current->signal->audit_tty))
186
                goto out;
187
        buf = current->signal->tty_audit_buf;
188
        if (buf) {
189
                atomic_inc(&buf->count);
190
                goto out;
191
        }
192
        spin_unlock_irq(&current->sighand->siglock);
193
 
194
        buf2 = tty_audit_buf_alloc(tty->driver->major,
195
                                   tty->driver->minor_start + tty->index,
196
                                   tty->icanon);
197
        if (buf2 == NULL) {
198
                audit_log_lost("out of memory in TTY auditing");
199
                return NULL;
200
        }
201
 
202
        spin_lock_irq(&current->sighand->siglock);
203
        if (!current->signal->audit_tty)
204
                goto out;
205
        buf = current->signal->tty_audit_buf;
206
        if (!buf) {
207
                current->signal->tty_audit_buf = buf2;
208
                buf = buf2;
209
                buf2 = NULL;
210
        }
211
        atomic_inc(&buf->count);
212
        /* Fall through */
213
 out:
214
        spin_unlock_irq(&current->sighand->siglock);
215
        if (buf2)
216
                tty_audit_buf_free(buf2);
217
        return buf;
218
}
219
 
220
/**
221
 *      tty_audit_add_data      -       Add data for TTY auditing.
222
 *
223
 *      Audit @data of @size from @tty, if necessary.
224
 */
225
void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
226
                        size_t size)
227
{
228
        struct tty_audit_buf *buf;
229
        int major, minor;
230
 
231
        if (unlikely(size == 0))
232
                return;
233
 
234
        buf = tty_audit_buf_get(tty);
235
        if (!buf)
236
                return;
237
 
238
        mutex_lock(&buf->mutex);
239
        major = tty->driver->major;
240
        minor = tty->driver->minor_start + tty->index;
241
        if (buf->major != major || buf->minor != minor
242
            || buf->icanon != tty->icanon) {
243
                tty_audit_buf_push_current(buf);
244
                buf->major = major;
245
                buf->minor = minor;
246
                buf->icanon = tty->icanon;
247
        }
248
        do {
249
                size_t run;
250
 
251
                run = N_TTY_BUF_SIZE - buf->valid;
252
                if (run > size)
253
                        run = size;
254
                memcpy(buf->data + buf->valid, data, run);
255
                buf->valid += run;
256
                data += run;
257
                size -= run;
258
                if (buf->valid == N_TTY_BUF_SIZE)
259
                        tty_audit_buf_push_current(buf);
260
        } while (size != 0);
261
        mutex_unlock(&buf->mutex);
262
        tty_audit_buf_put(buf);
263
}
264
 
265
/**
266
 *      tty_audit_push  -       Push buffered data out
267
 *
268
 *      Make sure no audit data is pending for @tty on the current process.
269
 */
270
void tty_audit_push(struct tty_struct *tty)
271
{
272
        struct tty_audit_buf *buf;
273
 
274
        spin_lock_irq(&current->sighand->siglock);
275
        if (likely(!current->signal->audit_tty)) {
276
                spin_unlock_irq(&current->sighand->siglock);
277
                return;
278
        }
279
        buf = current->signal->tty_audit_buf;
280
        if (buf)
281
                atomic_inc(&buf->count);
282
        spin_unlock_irq(&current->sighand->siglock);
283
 
284
        if (buf) {
285
                int major, minor;
286
 
287
                major = tty->driver->major;
288
                minor = tty->driver->minor_start + tty->index;
289
                mutex_lock(&buf->mutex);
290
                if (buf->major == major && buf->minor == minor)
291
                        tty_audit_buf_push_current(buf);
292
                mutex_unlock(&buf->mutex);
293
                tty_audit_buf_put(buf);
294
        }
295
}
296
 
297
/**
298
 *      tty_audit_opening       -       A TTY is being opened.
299
 *
300
 *      As a special hack, tasks that close all their TTYs and open new ones
301
 *      are assumed to be system daemons (e.g. getty) and auditing is
302
 *      automatically disabled for them.
303
 */
304
void tty_audit_opening(void)
305
{
306
        int disable;
307
 
308
        disable = 1;
309
        spin_lock_irq(&current->sighand->siglock);
310
        if (current->signal->audit_tty == 0)
311
                disable = 0;
312
        spin_unlock_irq(&current->sighand->siglock);
313
        if (!disable)
314
                return;
315
 
316
        task_lock(current);
317
        if (current->files) {
318
                struct fdtable *fdt;
319
                unsigned i;
320
 
321
                /*
322
                 * We don't take a ref to the file, so we must hold ->file_lock
323
                 * instead.
324
                 */
325
                spin_lock(&current->files->file_lock);
326
                fdt = files_fdtable(current->files);
327
                for (i = 0; i < fdt->max_fds; i++) {
328
                        struct file *filp;
329
 
330
                        filp = fcheck_files(current->files, i);
331
                        if (filp && is_tty(filp)) {
332
                                disable = 0;
333
                                break;
334
                        }
335
                }
336
                spin_unlock(&current->files->file_lock);
337
        }
338
        task_unlock(current);
339
        if (!disable)
340
                return;
341
 
342
        spin_lock_irq(&current->sighand->siglock);
343
        current->signal->audit_tty = 0;
344
        spin_unlock_irq(&current->sighand->siglock);
345
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.