diff options
Diffstat (limited to 'drivers/tty/tty_audit.c')
-rw-r--r-- | drivers/tty/tty_audit.c | 104 |
1 files changed, 45 insertions, 59 deletions
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 6953dc82850c..a4fdce74f883 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c | |||
@@ -60,24 +60,22 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf) | |||
60 | tty_audit_buf_free(buf); | 60 | tty_audit_buf_free(buf); |
61 | } | 61 | } |
62 | 62 | ||
63 | static void tty_audit_log(const char *description, struct task_struct *tsk, | 63 | static void tty_audit_log(const char *description, int major, int minor, |
64 | kuid_t loginuid, unsigned sessionid, int major, | 64 | unsigned char *data, size_t size) |
65 | int minor, unsigned char *data, size_t size) | ||
66 | { | 65 | { |
67 | struct audit_buffer *ab; | 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); | ||
68 | 71 | ||
69 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); | 72 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); |
70 | if (ab) { | 73 | if (ab) { |
71 | char name[sizeof(tsk->comm)]; | 74 | char name[sizeof(tsk->comm)]; |
72 | kuid_t uid = task_uid(tsk); | 75 | |
73 | 76 | audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" | |
74 | audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u " | 77 | " minor=%d comm=", description, tsk->pid, uid, |
75 | "major=%d minor=%d comm=", description, | 78 | loginuid, sessionid, major, minor); |
76 | tsk->pid, | ||
77 | from_kuid(&init_user_ns, uid), | ||
78 | from_kuid(&init_user_ns, loginuid), | ||
79 | sessionid, | ||
80 | major, minor); | ||
81 | get_task_comm(name, tsk); | 79 | get_task_comm(name, tsk); |
82 | audit_log_untrustedstring(ab, name); | 80 | audit_log_untrustedstring(ab, name); |
83 | audit_log_format(ab, " data="); | 81 | audit_log_format(ab, " data="); |
@@ -90,11 +88,9 @@ static void tty_audit_log(const char *description, struct task_struct *tsk, | |||
90 | * tty_audit_buf_push - Push buffered data out | 88 | * tty_audit_buf_push - Push buffered data out |
91 | * | 89 | * |
92 | * Generate an audit message from the contents of @buf, which is owned by | 90 | * Generate an audit message from the contents of @buf, which is owned by |
93 | * @tsk with @loginuid. @buf->mutex must be locked. | 91 | * the current task. @buf->mutex must be locked. |
94 | */ | 92 | */ |
95 | static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid, | 93 | static void tty_audit_buf_push(struct tty_audit_buf *buf) |
96 | unsigned int sessionid, | ||
97 | struct tty_audit_buf *buf) | ||
98 | { | 94 | { |
99 | if (buf->valid == 0) | 95 | if (buf->valid == 0) |
100 | return; | 96 | return; |
@@ -102,25 +98,11 @@ static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid, | |||
102 | buf->valid = 0; | 98 | buf->valid = 0; |
103 | return; | 99 | return; |
104 | } | 100 | } |
105 | tty_audit_log("tty", tsk, loginuid, sessionid, buf->major, buf->minor, | 101 | tty_audit_log("tty", buf->major, buf->minor, buf->data, buf->valid); |
106 | buf->data, buf->valid); | ||
107 | buf->valid = 0; | 102 | buf->valid = 0; |
108 | } | 103 | } |
109 | 104 | ||
110 | /** | 105 | /** |
111 | * tty_audit_buf_push_current - Push buffered data out | ||
112 | * | ||
113 | * Generate an audit message from the contents of @buf, which is owned by | ||
114 | * the current task. @buf->mutex must be locked. | ||
115 | */ | ||
116 | static void tty_audit_buf_push_current(struct tty_audit_buf *buf) | ||
117 | { | ||
118 | kuid_t auid = audit_get_loginuid(current); | ||
119 | unsigned int sessionid = audit_get_sessionid(current); | ||
120 | tty_audit_buf_push(current, auid, sessionid, buf); | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * tty_audit_exit - Handle a task exit | 106 | * tty_audit_exit - Handle a task exit |
125 | * | 107 | * |
126 | * Make sure all buffered data is written out and deallocate the buffer. | 108 | * Make sure all buffered data is written out and deallocate the buffer. |
@@ -130,15 +112,13 @@ void tty_audit_exit(void) | |||
130 | { | 112 | { |
131 | struct tty_audit_buf *buf; | 113 | struct tty_audit_buf *buf; |
132 | 114 | ||
133 | spin_lock_irq(¤t->sighand->siglock); | ||
134 | buf = current->signal->tty_audit_buf; | 115 | buf = current->signal->tty_audit_buf; |
135 | current->signal->tty_audit_buf = NULL; | 116 | current->signal->tty_audit_buf = NULL; |
136 | spin_unlock_irq(¤t->sighand->siglock); | ||
137 | if (!buf) | 117 | if (!buf) |
138 | return; | 118 | return; |
139 | 119 | ||
140 | mutex_lock(&buf->mutex); | 120 | mutex_lock(&buf->mutex); |
141 | tty_audit_buf_push_current(buf); | 121 | tty_audit_buf_push(buf); |
142 | mutex_unlock(&buf->mutex); | 122 | mutex_unlock(&buf->mutex); |
143 | 123 | ||
144 | tty_audit_buf_put(buf); | 124 | tty_audit_buf_put(buf); |
@@ -151,9 +131,8 @@ void tty_audit_exit(void) | |||
151 | */ | 131 | */ |
152 | void tty_audit_fork(struct signal_struct *sig) | 132 | void tty_audit_fork(struct signal_struct *sig) |
153 | { | 133 | { |
154 | spin_lock_irq(¤t->sighand->siglock); | ||
155 | sig->audit_tty = current->signal->audit_tty; | 134 | sig->audit_tty = current->signal->audit_tty; |
156 | spin_unlock_irq(¤t->sighand->siglock); | 135 | sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd; |
157 | } | 136 | } |
158 | 137 | ||
159 | /** | 138 | /** |
@@ -163,20 +142,21 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) | |||
163 | { | 142 | { |
164 | struct tty_audit_buf *buf; | 143 | struct tty_audit_buf *buf; |
165 | int major, minor, should_audit; | 144 | int major, minor, should_audit; |
145 | unsigned long flags; | ||
166 | 146 | ||
167 | spin_lock_irq(¤t->sighand->siglock); | 147 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
168 | should_audit = current->signal->audit_tty; | 148 | should_audit = current->signal->audit_tty; |
169 | buf = current->signal->tty_audit_buf; | 149 | buf = current->signal->tty_audit_buf; |
170 | if (buf) | 150 | if (buf) |
171 | atomic_inc(&buf->count); | 151 | atomic_inc(&buf->count); |
172 | spin_unlock_irq(¤t->sighand->siglock); | 152 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
173 | 153 | ||
174 | major = tty->driver->major; | 154 | major = tty->driver->major; |
175 | minor = tty->driver->minor_start + tty->index; | 155 | minor = tty->driver->minor_start + tty->index; |
176 | if (buf) { | 156 | if (buf) { |
177 | mutex_lock(&buf->mutex); | 157 | mutex_lock(&buf->mutex); |
178 | if (buf->major == major && buf->minor == minor) | 158 | if (buf->major == major && buf->minor == minor) |
179 | tty_audit_buf_push_current(buf); | 159 | tty_audit_buf_push(buf); |
180 | mutex_unlock(&buf->mutex); | 160 | mutex_unlock(&buf->mutex); |
181 | tty_audit_buf_put(buf); | 161 | tty_audit_buf_put(buf); |
182 | } | 162 | } |
@@ -187,24 +167,20 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) | |||
187 | 167 | ||
188 | auid = audit_get_loginuid(current); | 168 | auid = audit_get_loginuid(current); |
189 | sessionid = audit_get_sessionid(current); | 169 | sessionid = audit_get_sessionid(current); |
190 | tty_audit_log("ioctl=TIOCSTI", current, auid, sessionid, major, | 170 | tty_audit_log("ioctl=TIOCSTI", major, minor, &ch, 1); |
191 | minor, &ch, 1); | ||
192 | } | 171 | } |
193 | } | 172 | } |
194 | 173 | ||
195 | /** | 174 | /** |
196 | * tty_audit_push_task - Flush task's pending audit data | 175 | * tty_audit_push_current - Flush current's pending audit data |
197 | * @tsk: task pointer | ||
198 | * @loginuid: sender login uid | ||
199 | * @sessionid: sender session id | ||
200 | * | 176 | * |
201 | * Called with a ref on @tsk held. Try to lock sighand and get a | 177 | * Try to lock sighand and get a reference to the tty audit buffer if available. |
202 | * reference to the tty audit buffer if available. | ||
203 | * Flush the buffer or return an appropriate error code. | 178 | * Flush the buffer or return an appropriate error code. |
204 | */ | 179 | */ |
205 | int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid) | 180 | int tty_audit_push_current(void) |
206 | { | 181 | { |
207 | struct tty_audit_buf *buf = ERR_PTR(-EPERM); | 182 | struct tty_audit_buf *buf = ERR_PTR(-EPERM); |
183 | struct task_struct *tsk = current; | ||
208 | unsigned long flags; | 184 | unsigned long flags; |
209 | 185 | ||
210 | if (!lock_task_sighand(tsk, &flags)) | 186 | if (!lock_task_sighand(tsk, &flags)) |
@@ -225,7 +201,7 @@ int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid) | |||
225 | return PTR_ERR(buf); | 201 | return PTR_ERR(buf); |
226 | 202 | ||
227 | mutex_lock(&buf->mutex); | 203 | mutex_lock(&buf->mutex); |
228 | tty_audit_buf_push(tsk, loginuid, sessionid, buf); | 204 | tty_audit_buf_push(buf); |
229 | mutex_unlock(&buf->mutex); | 205 | mutex_unlock(&buf->mutex); |
230 | 206 | ||
231 | tty_audit_buf_put(buf); | 207 | tty_audit_buf_put(buf); |
@@ -243,10 +219,11 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, | |||
243 | unsigned icanon) | 219 | unsigned icanon) |
244 | { | 220 | { |
245 | struct tty_audit_buf *buf, *buf2; | 221 | struct tty_audit_buf *buf, *buf2; |
222 | unsigned long flags; | ||
246 | 223 | ||
247 | buf = NULL; | 224 | buf = NULL; |
248 | buf2 = NULL; | 225 | buf2 = NULL; |
249 | spin_lock_irq(¤t->sighand->siglock); | 226 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
250 | if (likely(!current->signal->audit_tty)) | 227 | if (likely(!current->signal->audit_tty)) |
251 | goto out; | 228 | goto out; |
252 | buf = current->signal->tty_audit_buf; | 229 | buf = current->signal->tty_audit_buf; |
@@ -254,7 +231,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, | |||
254 | atomic_inc(&buf->count); | 231 | atomic_inc(&buf->count); |
255 | goto out; | 232 | goto out; |
256 | } | 233 | } |
257 | spin_unlock_irq(¤t->sighand->siglock); | 234 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
258 | 235 | ||
259 | buf2 = tty_audit_buf_alloc(tty->driver->major, | 236 | buf2 = tty_audit_buf_alloc(tty->driver->major, |
260 | tty->driver->minor_start + tty->index, | 237 | tty->driver->minor_start + tty->index, |
@@ -264,7 +241,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, | |||
264 | return NULL; | 241 | return NULL; |
265 | } | 242 | } |
266 | 243 | ||
267 | spin_lock_irq(¤t->sighand->siglock); | 244 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
268 | if (!current->signal->audit_tty) | 245 | if (!current->signal->audit_tty) |
269 | goto out; | 246 | goto out; |
270 | buf = current->signal->tty_audit_buf; | 247 | buf = current->signal->tty_audit_buf; |
@@ -276,7 +253,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, | |||
276 | atomic_inc(&buf->count); | 253 | atomic_inc(&buf->count); |
277 | /* Fall through */ | 254 | /* Fall through */ |
278 | out: | 255 | out: |
279 | spin_unlock_irq(¤t->sighand->siglock); | 256 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
280 | if (buf2) | 257 | if (buf2) |
281 | tty_audit_buf_free(buf2); | 258 | tty_audit_buf_free(buf2); |
282 | return buf; | 259 | return buf; |
@@ -292,10 +269,18 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | |||
292 | { | 269 | { |
293 | struct tty_audit_buf *buf; | 270 | struct tty_audit_buf *buf; |
294 | int major, minor; | 271 | int major, minor; |
272 | int audit_log_tty_passwd; | ||
273 | unsigned long flags; | ||
295 | 274 | ||
296 | if (unlikely(size == 0)) | 275 | if (unlikely(size == 0)) |
297 | return; | 276 | return; |
298 | 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 | |||
299 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY | 284 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY |
300 | && tty->driver->subtype == PTY_TYPE_MASTER) | 285 | && tty->driver->subtype == PTY_TYPE_MASTER) |
301 | return; | 286 | return; |
@@ -309,7 +294,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | |||
309 | minor = tty->driver->minor_start + tty->index; | 294 | minor = tty->driver->minor_start + tty->index; |
310 | if (buf->major != major || buf->minor != minor | 295 | if (buf->major != major || buf->minor != minor |
311 | || buf->icanon != icanon) { | 296 | || buf->icanon != icanon) { |
312 | tty_audit_buf_push_current(buf); | 297 | tty_audit_buf_push(buf); |
313 | buf->major = major; | 298 | buf->major = major; |
314 | buf->minor = minor; | 299 | buf->minor = minor; |
315 | buf->icanon = icanon; | 300 | buf->icanon = icanon; |
@@ -325,7 +310,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | |||
325 | data += run; | 310 | data += run; |
326 | size -= run; | 311 | size -= run; |
327 | if (buf->valid == N_TTY_BUF_SIZE) | 312 | if (buf->valid == N_TTY_BUF_SIZE) |
328 | tty_audit_buf_push_current(buf); | 313 | tty_audit_buf_push(buf); |
329 | } while (size != 0); | 314 | } while (size != 0); |
330 | mutex_unlock(&buf->mutex); | 315 | mutex_unlock(&buf->mutex); |
331 | tty_audit_buf_put(buf); | 316 | tty_audit_buf_put(buf); |
@@ -339,16 +324,17 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | |||
339 | void tty_audit_push(struct tty_struct *tty) | 324 | void tty_audit_push(struct tty_struct *tty) |
340 | { | 325 | { |
341 | struct tty_audit_buf *buf; | 326 | struct tty_audit_buf *buf; |
327 | unsigned long flags; | ||
342 | 328 | ||
343 | spin_lock_irq(¤t->sighand->siglock); | 329 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
344 | if (likely(!current->signal->audit_tty)) { | 330 | if (likely(!current->signal->audit_tty)) { |
345 | spin_unlock_irq(¤t->sighand->siglock); | 331 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
346 | return; | 332 | return; |
347 | } | 333 | } |
348 | buf = current->signal->tty_audit_buf; | 334 | buf = current->signal->tty_audit_buf; |
349 | if (buf) | 335 | if (buf) |
350 | atomic_inc(&buf->count); | 336 | atomic_inc(&buf->count); |
351 | spin_unlock_irq(¤t->sighand->siglock); | 337 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
352 | 338 | ||
353 | if (buf) { | 339 | if (buf) { |
354 | int major, minor; | 340 | int major, minor; |
@@ -357,7 +343,7 @@ void tty_audit_push(struct tty_struct *tty) | |||
357 | minor = tty->driver->minor_start + tty->index; | 343 | minor = tty->driver->minor_start + tty->index; |
358 | mutex_lock(&buf->mutex); | 344 | mutex_lock(&buf->mutex); |
359 | if (buf->major == major && buf->minor == minor) | 345 | if (buf->major == major && buf->minor == minor) |
360 | tty_audit_buf_push_current(buf); | 346 | tty_audit_buf_push(buf); |
361 | mutex_unlock(&buf->mutex); | 347 | mutex_unlock(&buf->mutex); |
362 | tty_audit_buf_put(buf); | 348 | tty_audit_buf_put(buf); |
363 | } | 349 | } |