diff options
| -rw-r--r-- | arch/powerpc/kernel/entry_64.S | 2 | ||||
| -rw-r--r-- | drivers/tty/tty_audit.c | 104 | ||||
| -rw-r--r-- | fs/namei.c | 2 | ||||
| -rw-r--r-- | include/linux/audit.h | 48 | ||||
| -rw-r--r-- | include/linux/sched.h | 1 | ||||
| -rw-r--r-- | include/linux/tty.h | 6 | ||||
| -rw-r--r-- | include/uapi/linux/audit.h | 4 | ||||
| -rw-r--r-- | kernel/audit.c | 516 | ||||
| -rw-r--r-- | kernel/audit.h | 156 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 360 | ||||
| -rw-r--r-- | kernel/auditsc.c | 407 | ||||
| -rw-r--r-- | net/socket.c | 6 |
12 files changed, 745 insertions, 867 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 3fe5259e2fea..915fbb4fc2fe 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -150,7 +150,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | |||
| 150 | CURRENT_THREAD_INFO(r11, r1) | 150 | CURRENT_THREAD_INFO(r11, r1) |
| 151 | ld r10,TI_FLAGS(r11) | 151 | ld r10,TI_FLAGS(r11) |
| 152 | andi. r11,r10,_TIF_SYSCALL_T_OR_A | 152 | andi. r11,r10,_TIF_SYSCALL_T_OR_A |
| 153 | bne- syscall_dotrace | 153 | bne syscall_dotrace |
| 154 | .Lsyscall_dotrace_cont: | 154 | .Lsyscall_dotrace_cont: |
| 155 | cmpldi 0,r0,NR_syscalls | 155 | cmpldi 0,r0,NR_syscalls |
| 156 | bge- syscall_enosys | 156 | bge- syscall_enosys |
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 | } |
diff --git a/fs/namei.c b/fs/namei.c index 57ae9c8c66bf..85e40d1c0a8f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -2740,7 +2740,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
| 2740 | if (error) | 2740 | if (error) |
| 2741 | return error; | 2741 | return error; |
| 2742 | 2742 | ||
| 2743 | audit_inode(name, dir, 0); | 2743 | audit_inode(name, dir, LOOKUP_PARENT); |
| 2744 | error = -EISDIR; | 2744 | error = -EISDIR; |
| 2745 | /* trailing slashes? */ | 2745 | /* trailing slashes? */ |
| 2746 | if (nd->last.name[nd->last.len]) | 2746 | if (nd->last.name[nd->last.len]) |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 5a6d718adf34..b20b03852f21 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -84,8 +84,13 @@ extern int audit_classify_arch(int arch); | |||
| 84 | #define AUDIT_TYPE_CHILD_DELETE 3 /* a child being deleted */ | 84 | #define AUDIT_TYPE_CHILD_DELETE 3 /* a child being deleted */ |
| 85 | #define AUDIT_TYPE_CHILD_CREATE 4 /* a child being created */ | 85 | #define AUDIT_TYPE_CHILD_CREATE 4 /* a child being created */ |
| 86 | 86 | ||
| 87 | /* maximized args number that audit_socketcall can process */ | ||
| 88 | #define AUDITSC_ARGS 6 | ||
| 89 | |||
| 87 | struct filename; | 90 | struct filename; |
| 88 | 91 | ||
| 92 | extern void audit_log_session_info(struct audit_buffer *ab); | ||
| 93 | |||
| 89 | #ifdef CONFIG_AUDITSYSCALL | 94 | #ifdef CONFIG_AUDITSYSCALL |
| 90 | /* These are defined in auditsc.c */ | 95 | /* These are defined in auditsc.c */ |
| 91 | /* Public API */ | 96 | /* Public API */ |
| @@ -120,7 +125,7 @@ static inline void audit_syscall_entry(int arch, int major, unsigned long a0, | |||
| 120 | unsigned long a1, unsigned long a2, | 125 | unsigned long a1, unsigned long a2, |
| 121 | unsigned long a3) | 126 | unsigned long a3) |
| 122 | { | 127 | { |
| 123 | if (unlikely(!audit_dummy_context())) | 128 | if (unlikely(current->audit_context)) |
| 124 | __audit_syscall_entry(arch, major, a0, a1, a2, a3); | 129 | __audit_syscall_entry(arch, major, a0, a1, a2, a3); |
| 125 | } | 130 | } |
| 126 | static inline void audit_syscall_exit(void *pt_regs) | 131 | static inline void audit_syscall_exit(void *pt_regs) |
| @@ -185,12 +190,10 @@ static inline int audit_get_sessionid(struct task_struct *tsk) | |||
| 185 | return tsk->sessionid; | 190 | return tsk->sessionid; |
| 186 | } | 191 | } |
| 187 | 192 | ||
| 188 | extern void audit_log_task_context(struct audit_buffer *ab); | ||
| 189 | extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk); | ||
| 190 | extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); | 193 | extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); |
| 191 | extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); | 194 | extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); |
| 192 | extern int __audit_bprm(struct linux_binprm *bprm); | 195 | extern int __audit_bprm(struct linux_binprm *bprm); |
| 193 | extern void __audit_socketcall(int nargs, unsigned long *args); | 196 | extern int __audit_socketcall(int nargs, unsigned long *args); |
| 194 | extern int __audit_sockaddr(int len, void *addr); | 197 | extern int __audit_sockaddr(int len, void *addr); |
| 195 | extern void __audit_fd_pair(int fd1, int fd2); | 198 | extern void __audit_fd_pair(int fd1, int fd2); |
| 196 | extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr); | 199 | extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr); |
| @@ -224,10 +227,11 @@ static inline int audit_bprm(struct linux_binprm *bprm) | |||
| 224 | return __audit_bprm(bprm); | 227 | return __audit_bprm(bprm); |
| 225 | return 0; | 228 | return 0; |
| 226 | } | 229 | } |
| 227 | static inline void audit_socketcall(int nargs, unsigned long *args) | 230 | static inline int audit_socketcall(int nargs, unsigned long *args) |
| 228 | { | 231 | { |
| 229 | if (unlikely(!audit_dummy_context())) | 232 | if (unlikely(!audit_dummy_context())) |
| 230 | __audit_socketcall(nargs, args); | 233 | return __audit_socketcall(nargs, args); |
| 234 | return 0; | ||
| 231 | } | 235 | } |
| 232 | static inline int audit_sockaddr(int len, void *addr) | 236 | static inline int audit_sockaddr(int len, void *addr) |
| 233 | { | 237 | { |
| @@ -340,11 +344,6 @@ static inline int audit_get_sessionid(struct task_struct *tsk) | |||
| 340 | { | 344 | { |
| 341 | return -1; | 345 | return -1; |
| 342 | } | 346 | } |
| 343 | static inline void audit_log_task_context(struct audit_buffer *ab) | ||
| 344 | { } | ||
| 345 | static inline void audit_log_task_info(struct audit_buffer *ab, | ||
| 346 | struct task_struct *tsk) | ||
| 347 | { } | ||
| 348 | static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) | 347 | static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) |
| 349 | { } | 348 | { } |
| 350 | static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, | 349 | static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, |
| @@ -354,8 +353,10 @@ static inline int audit_bprm(struct linux_binprm *bprm) | |||
| 354 | { | 353 | { |
| 355 | return 0; | 354 | return 0; |
| 356 | } | 355 | } |
| 357 | static inline void audit_socketcall(int nargs, unsigned long *args) | 356 | static inline int audit_socketcall(int nargs, unsigned long *args) |
| 358 | { } | 357 | { |
| 358 | return 0; | ||
| 359 | } | ||
| 359 | static inline void audit_fd_pair(int fd1, int fd2) | 360 | static inline void audit_fd_pair(int fd1, int fd2) |
| 360 | { } | 361 | { } |
| 361 | static inline int audit_sockaddr(int len, void *addr) | 362 | static inline int audit_sockaddr(int len, void *addr) |
| @@ -390,6 +391,11 @@ static inline void audit_ptrace(struct task_struct *t) | |||
| 390 | #define audit_signals 0 | 391 | #define audit_signals 0 |
| 391 | #endif /* CONFIG_AUDITSYSCALL */ | 392 | #endif /* CONFIG_AUDITSYSCALL */ |
| 392 | 393 | ||
| 394 | static inline bool audit_loginuid_set(struct task_struct *tsk) | ||
| 395 | { | ||
| 396 | return uid_valid(audit_get_loginuid(tsk)); | ||
| 397 | } | ||
| 398 | |||
| 393 | #ifdef CONFIG_AUDIT | 399 | #ifdef CONFIG_AUDIT |
| 394 | /* These are defined in audit.c */ | 400 | /* These are defined in audit.c */ |
| 395 | /* Public API */ | 401 | /* Public API */ |
| @@ -429,14 +435,17 @@ static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) | |||
| 429 | { } | 435 | { } |
| 430 | #endif | 436 | #endif |
| 431 | 437 | ||
| 438 | extern int audit_log_task_context(struct audit_buffer *ab); | ||
| 439 | extern void audit_log_task_info(struct audit_buffer *ab, | ||
| 440 | struct task_struct *tsk); | ||
| 441 | |||
| 432 | extern int audit_update_lsm_rules(void); | 442 | extern int audit_update_lsm_rules(void); |
| 433 | 443 | ||
| 434 | /* Private API (for audit.c only) */ | 444 | /* Private API (for audit.c only) */ |
| 435 | extern int audit_filter_user(void); | 445 | extern int audit_filter_user(int type); |
| 436 | extern int audit_filter_type(int type); | 446 | extern int audit_filter_type(int type); |
| 437 | extern int audit_receive_filter(int type, int pid, int seq, | 447 | extern int audit_receive_filter(int type, int pid, int seq, |
| 438 | void *data, size_t datasz, kuid_t loginuid, | 448 | void *data, size_t datasz); |
| 439 | u32 sessionid, u32 sid); | ||
| 440 | extern int audit_enabled; | 449 | extern int audit_enabled; |
| 441 | #else /* CONFIG_AUDIT */ | 450 | #else /* CONFIG_AUDIT */ |
| 442 | static inline __printf(4, 5) | 451 | static inline __printf(4, 5) |
| @@ -476,6 +485,13 @@ static inline void audit_log_link_denied(const char *string, | |||
| 476 | { } | 485 | { } |
| 477 | static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) | 486 | static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) |
| 478 | { } | 487 | { } |
| 488 | static inline int audit_log_task_context(struct audit_buffer *ab) | ||
| 489 | { | ||
| 490 | return 0; | ||
| 491 | } | ||
| 492 | static inline void audit_log_task_info(struct audit_buffer *ab, | ||
| 493 | struct task_struct *tsk) | ||
| 494 | { } | ||
| 479 | #define audit_enabled 0 | 495 | #define audit_enabled 0 |
| 480 | #endif /* CONFIG_AUDIT */ | 496 | #endif /* CONFIG_AUDIT */ |
| 481 | static inline void audit_log_string(struct audit_buffer *ab, const char *buf) | 497 | static inline void audit_log_string(struct audit_buffer *ab, const char *buf) |
diff --git a/include/linux/sched.h b/include/linux/sched.h index caa8f4d0186b..178a8d909f14 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -593,6 +593,7 @@ struct signal_struct { | |||
| 593 | #endif | 593 | #endif |
| 594 | #ifdef CONFIG_AUDIT | 594 | #ifdef CONFIG_AUDIT |
| 595 | unsigned audit_tty; | 595 | unsigned audit_tty; |
| 596 | unsigned audit_tty_log_passwd; | ||
| 596 | struct tty_audit_buf *tty_audit_buf; | 597 | struct tty_audit_buf *tty_audit_buf; |
| 597 | #endif | 598 | #endif |
| 598 | #ifdef CONFIG_CGROUPS | 599 | #ifdef CONFIG_CGROUPS |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 7e92bd86a808..8780bd2a272a 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -575,8 +575,7 @@ extern void tty_audit_exit(void); | |||
| 575 | extern void tty_audit_fork(struct signal_struct *sig); | 575 | extern void tty_audit_fork(struct signal_struct *sig); |
| 576 | extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); | 576 | extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); |
| 577 | extern void tty_audit_push(struct tty_struct *tty); | 577 | extern void tty_audit_push(struct tty_struct *tty); |
| 578 | extern int tty_audit_push_task(struct task_struct *tsk, | 578 | extern int tty_audit_push_current(void); |
| 579 | kuid_t loginuid, u32 sessionid); | ||
| 580 | #else | 579 | #else |
| 581 | static inline void tty_audit_add_data(struct tty_struct *tty, | 580 | static inline void tty_audit_add_data(struct tty_struct *tty, |
| 582 | unsigned char *data, size_t size, unsigned icanon) | 581 | unsigned char *data, size_t size, unsigned icanon) |
| @@ -594,8 +593,7 @@ static inline void tty_audit_fork(struct signal_struct *sig) | |||
| 594 | static inline void tty_audit_push(struct tty_struct *tty) | 593 | static inline void tty_audit_push(struct tty_struct *tty) |
| 595 | { | 594 | { |
| 596 | } | 595 | } |
| 597 | static inline int tty_audit_push_task(struct task_struct *tsk, | 596 | static inline int tty_audit_push_current(void) |
| 598 | kuid_t loginuid, u32 sessionid) | ||
| 599 | { | 597 | { |
| 600 | return 0; | 598 | return 0; |
| 601 | } | 599 | } |
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 9f096f1c0907..75cef3fd97ad 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h | |||
| @@ -246,6 +246,7 @@ | |||
| 246 | #define AUDIT_OBJ_TYPE 21 | 246 | #define AUDIT_OBJ_TYPE 21 |
| 247 | #define AUDIT_OBJ_LEV_LOW 22 | 247 | #define AUDIT_OBJ_LEV_LOW 22 |
| 248 | #define AUDIT_OBJ_LEV_HIGH 23 | 248 | #define AUDIT_OBJ_LEV_HIGH 23 |
| 249 | #define AUDIT_LOGINUID_SET 24 | ||
| 249 | 250 | ||
| 250 | /* These are ONLY useful when checking | 251 | /* These are ONLY useful when checking |
| 251 | * at syscall exit time (AUDIT_AT_EXIT). */ | 252 | * at syscall exit time (AUDIT_AT_EXIT). */ |
| @@ -369,7 +370,8 @@ struct audit_status { | |||
| 369 | }; | 370 | }; |
| 370 | 371 | ||
| 371 | struct audit_tty_status { | 372 | struct audit_tty_status { |
| 372 | __u32 enabled; /* 1 = enabled, 0 = disabled */ | 373 | __u32 enabled; /* 1 = enabled, 0 = disabled */ |
| 374 | __u32 log_passwd; /* 1 = enabled, 0 = disabled */ | ||
| 373 | }; | 375 | }; |
| 374 | 376 | ||
| 375 | /* audit_rule_data supports filter rules with both integer and string | 377 | /* audit_rule_data supports filter rules with both integer and string |
diff --git a/kernel/audit.c b/kernel/audit.c index 0b084fa44b1f..21c7fa615bd3 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -49,6 +49,8 @@ | |||
| 49 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
| 50 | #include <linux/err.h> | 50 | #include <linux/err.h> |
| 51 | #include <linux/kthread.h> | 51 | #include <linux/kthread.h> |
| 52 | #include <linux/kernel.h> | ||
| 53 | #include <linux/syscalls.h> | ||
| 52 | 54 | ||
| 53 | #include <linux/audit.h> | 55 | #include <linux/audit.h> |
| 54 | 56 | ||
| @@ -265,7 +267,6 @@ void audit_log_lost(const char *message) | |||
| 265 | } | 267 | } |
| 266 | 268 | ||
| 267 | static int audit_log_config_change(char *function_name, int new, int old, | 269 | static int audit_log_config_change(char *function_name, int new, int old, |
| 268 | kuid_t loginuid, u32 sessionid, u32 sid, | ||
| 269 | int allow_changes) | 270 | int allow_changes) |
| 270 | { | 271 | { |
| 271 | struct audit_buffer *ab; | 272 | struct audit_buffer *ab; |
| @@ -274,29 +275,17 @@ static int audit_log_config_change(char *function_name, int new, int old, | |||
| 274 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 275 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 275 | if (unlikely(!ab)) | 276 | if (unlikely(!ab)) |
| 276 | return rc; | 277 | return rc; |
| 277 | audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, | 278 | audit_log_format(ab, "%s=%d old=%d", function_name, new, old); |
| 278 | old, from_kuid(&init_user_ns, loginuid), sessionid); | 279 | audit_log_session_info(ab); |
| 279 | if (sid) { | 280 | rc = audit_log_task_context(ab); |
| 280 | char *ctx = NULL; | 281 | if (rc) |
| 281 | u32 len; | 282 | allow_changes = 0; /* Something weird, deny request */ |
| 282 | |||
| 283 | rc = security_secid_to_secctx(sid, &ctx, &len); | ||
| 284 | if (rc) { | ||
| 285 | audit_log_format(ab, " sid=%u", sid); | ||
| 286 | allow_changes = 0; /* Something weird, deny request */ | ||
| 287 | } else { | ||
| 288 | audit_log_format(ab, " subj=%s", ctx); | ||
| 289 | security_release_secctx(ctx, len); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | audit_log_format(ab, " res=%d", allow_changes); | 283 | audit_log_format(ab, " res=%d", allow_changes); |
| 293 | audit_log_end(ab); | 284 | audit_log_end(ab); |
| 294 | return rc; | 285 | return rc; |
| 295 | } | 286 | } |
| 296 | 287 | ||
| 297 | static int audit_do_config_change(char *function_name, int *to_change, | 288 | static int audit_do_config_change(char *function_name, int *to_change, int new) |
| 298 | int new, kuid_t loginuid, u32 sessionid, | ||
| 299 | u32 sid) | ||
| 300 | { | 289 | { |
| 301 | int allow_changes, rc = 0, old = *to_change; | 290 | int allow_changes, rc = 0, old = *to_change; |
| 302 | 291 | ||
| @@ -307,8 +296,7 @@ static int audit_do_config_change(char *function_name, int *to_change, | |||
| 307 | allow_changes = 1; | 296 | allow_changes = 1; |
| 308 | 297 | ||
| 309 | if (audit_enabled != AUDIT_OFF) { | 298 | if (audit_enabled != AUDIT_OFF) { |
| 310 | rc = audit_log_config_change(function_name, new, old, loginuid, | 299 | rc = audit_log_config_change(function_name, new, old, allow_changes); |
| 311 | sessionid, sid, allow_changes); | ||
| 312 | if (rc) | 300 | if (rc) |
| 313 | allow_changes = 0; | 301 | allow_changes = 0; |
| 314 | } | 302 | } |
| @@ -322,44 +310,37 @@ static int audit_do_config_change(char *function_name, int *to_change, | |||
| 322 | return rc; | 310 | return rc; |
| 323 | } | 311 | } |
| 324 | 312 | ||
| 325 | static int audit_set_rate_limit(int limit, kuid_t loginuid, u32 sessionid, | 313 | static int audit_set_rate_limit(int limit) |
| 326 | u32 sid) | ||
| 327 | { | 314 | { |
| 328 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, | 315 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, limit); |
| 329 | limit, loginuid, sessionid, sid); | ||
| 330 | } | 316 | } |
| 331 | 317 | ||
| 332 | static int audit_set_backlog_limit(int limit, kuid_t loginuid, u32 sessionid, | 318 | static int audit_set_backlog_limit(int limit) |
| 333 | u32 sid) | ||
| 334 | { | 319 | { |
| 335 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, | 320 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, limit); |
| 336 | limit, loginuid, sessionid, sid); | ||
| 337 | } | 321 | } |
| 338 | 322 | ||
| 339 | static int audit_set_enabled(int state, kuid_t loginuid, u32 sessionid, u32 sid) | 323 | static int audit_set_enabled(int state) |
| 340 | { | 324 | { |
| 341 | int rc; | 325 | int rc; |
| 342 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) | 326 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) |
| 343 | return -EINVAL; | 327 | return -EINVAL; |
| 344 | 328 | ||
| 345 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state, | 329 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state); |
| 346 | loginuid, sessionid, sid); | ||
| 347 | |||
| 348 | if (!rc) | 330 | if (!rc) |
| 349 | audit_ever_enabled |= !!state; | 331 | audit_ever_enabled |= !!state; |
| 350 | 332 | ||
| 351 | return rc; | 333 | return rc; |
| 352 | } | 334 | } |
| 353 | 335 | ||
| 354 | static int audit_set_failure(int state, kuid_t loginuid, u32 sessionid, u32 sid) | 336 | static int audit_set_failure(int state) |
| 355 | { | 337 | { |
| 356 | if (state != AUDIT_FAIL_SILENT | 338 | if (state != AUDIT_FAIL_SILENT |
| 357 | && state != AUDIT_FAIL_PRINTK | 339 | && state != AUDIT_FAIL_PRINTK |
| 358 | && state != AUDIT_FAIL_PANIC) | 340 | && state != AUDIT_FAIL_PANIC) |
| 359 | return -EINVAL; | 341 | return -EINVAL; |
| 360 | 342 | ||
| 361 | return audit_do_config_change("audit_failure", &audit_failure, state, | 343 | return audit_do_config_change("audit_failure", &audit_failure, state); |
| 362 | loginuid, sessionid, sid); | ||
| 363 | } | 344 | } |
| 364 | 345 | ||
| 365 | /* | 346 | /* |
| @@ -417,34 +398,53 @@ static void kauditd_send_skb(struct sk_buff *skb) | |||
| 417 | consume_skb(skb); | 398 | consume_skb(skb); |
| 418 | } | 399 | } |
| 419 | 400 | ||
| 420 | static int kauditd_thread(void *dummy) | 401 | /* |
| 402 | * flush_hold_queue - empty the hold queue if auditd appears | ||
| 403 | * | ||
| 404 | * If auditd just started, drain the queue of messages already | ||
| 405 | * sent to syslog/printk. Remember loss here is ok. We already | ||
| 406 | * called audit_log_lost() if it didn't go out normally. so the | ||
| 407 | * race between the skb_dequeue and the next check for audit_pid | ||
| 408 | * doesn't matter. | ||
| 409 | * | ||
| 410 | * If you ever find kauditd to be too slow we can get a perf win | ||
| 411 | * by doing our own locking and keeping better track if there | ||
| 412 | * are messages in this queue. I don't see the need now, but | ||
| 413 | * in 5 years when I want to play with this again I'll see this | ||
| 414 | * note and still have no friggin idea what i'm thinking today. | ||
| 415 | */ | ||
| 416 | static void flush_hold_queue(void) | ||
| 421 | { | 417 | { |
| 422 | struct sk_buff *skb; | 418 | struct sk_buff *skb; |
| 423 | 419 | ||
| 420 | if (!audit_default || !audit_pid) | ||
| 421 | return; | ||
| 422 | |||
| 423 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 424 | if (likely(!skb)) | ||
| 425 | return; | ||
| 426 | |||
| 427 | while (skb && audit_pid) { | ||
| 428 | kauditd_send_skb(skb); | ||
| 429 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 430 | } | ||
| 431 | |||
| 432 | /* | ||
| 433 | * if auditd just disappeared but we | ||
| 434 | * dequeued an skb we need to drop ref | ||
| 435 | */ | ||
| 436 | if (skb) | ||
| 437 | consume_skb(skb); | ||
| 438 | } | ||
| 439 | |||
| 440 | static int kauditd_thread(void *dummy) | ||
| 441 | { | ||
| 424 | set_freezable(); | 442 | set_freezable(); |
| 425 | while (!kthread_should_stop()) { | 443 | while (!kthread_should_stop()) { |
| 426 | /* | 444 | struct sk_buff *skb; |
| 427 | * if auditd just started drain the queue of messages already | 445 | DECLARE_WAITQUEUE(wait, current); |
| 428 | * sent to syslog/printk. remember loss here is ok. we already | 446 | |
| 429 | * called audit_log_lost() if it didn't go out normally. so the | 447 | flush_hold_queue(); |
| 430 | * race between the skb_dequeue and the next check for audit_pid | ||
| 431 | * doesn't matter. | ||
| 432 | * | ||
| 433 | * if you ever find kauditd to be too slow we can get a perf win | ||
| 434 | * by doing our own locking and keeping better track if there | ||
| 435 | * are messages in this queue. I don't see the need now, but | ||
| 436 | * in 5 years when I want to play with this again I'll see this | ||
| 437 | * note and still have no friggin idea what i'm thinking today. | ||
| 438 | */ | ||
| 439 | if (audit_default && audit_pid) { | ||
| 440 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 441 | if (unlikely(skb)) { | ||
| 442 | while (skb && audit_pid) { | ||
| 443 | kauditd_send_skb(skb); | ||
| 444 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 445 | } | ||
| 446 | } | ||
| 447 | } | ||
| 448 | 448 | ||
| 449 | skb = skb_dequeue(&audit_skb_queue); | 449 | skb = skb_dequeue(&audit_skb_queue); |
| 450 | wake_up(&audit_backlog_wait); | 450 | wake_up(&audit_backlog_wait); |
| @@ -453,19 +453,18 @@ static int kauditd_thread(void *dummy) | |||
| 453 | kauditd_send_skb(skb); | 453 | kauditd_send_skb(skb); |
| 454 | else | 454 | else |
| 455 | audit_printk_skb(skb); | 455 | audit_printk_skb(skb); |
| 456 | } else { | 456 | continue; |
| 457 | DECLARE_WAITQUEUE(wait, current); | 457 | } |
| 458 | set_current_state(TASK_INTERRUPTIBLE); | 458 | set_current_state(TASK_INTERRUPTIBLE); |
| 459 | add_wait_queue(&kauditd_wait, &wait); | 459 | add_wait_queue(&kauditd_wait, &wait); |
| 460 | |||
| 461 | if (!skb_queue_len(&audit_skb_queue)) { | ||
| 462 | try_to_freeze(); | ||
| 463 | schedule(); | ||
| 464 | } | ||
| 465 | 460 | ||
| 466 | __set_current_state(TASK_RUNNING); | 461 | if (!skb_queue_len(&audit_skb_queue)) { |
| 467 | remove_wait_queue(&kauditd_wait, &wait); | 462 | try_to_freeze(); |
| 463 | schedule(); | ||
| 468 | } | 464 | } |
| 465 | |||
| 466 | __set_current_state(TASK_RUNNING); | ||
| 467 | remove_wait_queue(&kauditd_wait, &wait); | ||
| 469 | } | 468 | } |
| 470 | return 0; | 469 | return 0; |
| 471 | } | 470 | } |
| @@ -579,13 +578,14 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
| 579 | return -EPERM; | 578 | return -EPERM; |
| 580 | 579 | ||
| 581 | switch (msg_type) { | 580 | switch (msg_type) { |
| 582 | case AUDIT_GET: | ||
| 583 | case AUDIT_LIST: | 581 | case AUDIT_LIST: |
| 584 | case AUDIT_LIST_RULES: | ||
| 585 | case AUDIT_SET: | ||
| 586 | case AUDIT_ADD: | 582 | case AUDIT_ADD: |
| 587 | case AUDIT_ADD_RULE: | ||
| 588 | case AUDIT_DEL: | 583 | case AUDIT_DEL: |
| 584 | return -EOPNOTSUPP; | ||
| 585 | case AUDIT_GET: | ||
| 586 | case AUDIT_SET: | ||
| 587 | case AUDIT_LIST_RULES: | ||
| 588 | case AUDIT_ADD_RULE: | ||
| 589 | case AUDIT_DEL_RULE: | 589 | case AUDIT_DEL_RULE: |
| 590 | case AUDIT_SIGNAL_INFO: | 590 | case AUDIT_SIGNAL_INFO: |
| 591 | case AUDIT_TTY_GET: | 591 | case AUDIT_TTY_GET: |
| @@ -608,12 +608,10 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
| 608 | return err; | 608 | return err; |
| 609 | } | 609 | } |
| 610 | 610 | ||
| 611 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | 611 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) |
| 612 | kuid_t auid, u32 ses, u32 sid) | ||
| 613 | { | 612 | { |
| 614 | int rc = 0; | 613 | int rc = 0; |
| 615 | char *ctx = NULL; | 614 | uid_t uid = from_kuid(&init_user_ns, current_uid()); |
| 616 | u32 len; | ||
| 617 | 615 | ||
| 618 | if (!audit_enabled) { | 616 | if (!audit_enabled) { |
| 619 | *ab = NULL; | 617 | *ab = NULL; |
| @@ -623,33 +621,21 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | |||
| 623 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | 621 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
| 624 | if (unlikely(!*ab)) | 622 | if (unlikely(!*ab)) |
| 625 | return rc; | 623 | return rc; |
| 626 | audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u", | 624 | audit_log_format(*ab, "pid=%d uid=%u", task_tgid_vnr(current), uid); |
| 627 | task_tgid_vnr(current), | 625 | audit_log_session_info(*ab); |
| 628 | from_kuid(&init_user_ns, current_uid()), | 626 | audit_log_task_context(*ab); |
| 629 | from_kuid(&init_user_ns, auid), ses); | ||
| 630 | if (sid) { | ||
| 631 | rc = security_secid_to_secctx(sid, &ctx, &len); | ||
| 632 | if (rc) | ||
| 633 | audit_log_format(*ab, " ssid=%u", sid); | ||
| 634 | else { | ||
| 635 | audit_log_format(*ab, " subj=%s", ctx); | ||
| 636 | security_release_secctx(ctx, len); | ||
| 637 | } | ||
| 638 | } | ||
| 639 | 627 | ||
| 640 | return rc; | 628 | return rc; |
| 641 | } | 629 | } |
| 642 | 630 | ||
| 643 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 631 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
| 644 | { | 632 | { |
| 645 | u32 seq, sid; | 633 | u32 seq; |
| 646 | void *data; | 634 | void *data; |
| 647 | struct audit_status *status_get, status_set; | 635 | struct audit_status *status_get, status_set; |
| 648 | int err; | 636 | int err; |
| 649 | struct audit_buffer *ab; | 637 | struct audit_buffer *ab; |
| 650 | u16 msg_type = nlh->nlmsg_type; | 638 | u16 msg_type = nlh->nlmsg_type; |
| 651 | kuid_t loginuid; /* loginuid of sender */ | ||
| 652 | u32 sessionid; | ||
| 653 | struct audit_sig_info *sig_data; | 639 | struct audit_sig_info *sig_data; |
| 654 | char *ctx = NULL; | 640 | char *ctx = NULL; |
| 655 | u32 len; | 641 | u32 len; |
| @@ -668,9 +654,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 668 | return err; | 654 | return err; |
| 669 | } | 655 | } |
| 670 | } | 656 | } |
| 671 | loginuid = audit_get_loginuid(current); | ||
| 672 | sessionid = audit_get_sessionid(current); | ||
| 673 | security_task_getsecid(current, &sid); | ||
| 674 | seq = nlh->nlmsg_seq; | 657 | seq = nlh->nlmsg_seq; |
| 675 | data = nlmsg_data(nlh); | 658 | data = nlmsg_data(nlh); |
| 676 | 659 | ||
| @@ -691,14 +674,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 691 | return -EINVAL; | 674 | return -EINVAL; |
| 692 | status_get = (struct audit_status *)data; | 675 | status_get = (struct audit_status *)data; |
| 693 | if (status_get->mask & AUDIT_STATUS_ENABLED) { | 676 | if (status_get->mask & AUDIT_STATUS_ENABLED) { |
| 694 | err = audit_set_enabled(status_get->enabled, | 677 | err = audit_set_enabled(status_get->enabled); |
| 695 | loginuid, sessionid, sid); | ||
| 696 | if (err < 0) | 678 | if (err < 0) |
| 697 | return err; | 679 | return err; |
| 698 | } | 680 | } |
| 699 | if (status_get->mask & AUDIT_STATUS_FAILURE) { | 681 | if (status_get->mask & AUDIT_STATUS_FAILURE) { |
| 700 | err = audit_set_failure(status_get->failure, | 682 | err = audit_set_failure(status_get->failure); |
| 701 | loginuid, sessionid, sid); | ||
| 702 | if (err < 0) | 683 | if (err < 0) |
| 703 | return err; | 684 | return err; |
| 704 | } | 685 | } |
| @@ -706,22 +687,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 706 | int new_pid = status_get->pid; | 687 | int new_pid = status_get->pid; |
| 707 | 688 | ||
| 708 | if (audit_enabled != AUDIT_OFF) | 689 | if (audit_enabled != AUDIT_OFF) |
| 709 | audit_log_config_change("audit_pid", new_pid, | 690 | audit_log_config_change("audit_pid", new_pid, audit_pid, 1); |
| 710 | audit_pid, loginuid, | ||
| 711 | sessionid, sid, 1); | ||
| 712 | |||
| 713 | audit_pid = new_pid; | 691 | audit_pid = new_pid; |
| 714 | audit_nlk_portid = NETLINK_CB(skb).portid; | 692 | audit_nlk_portid = NETLINK_CB(skb).portid; |
| 715 | } | 693 | } |
| 716 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { | 694 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { |
| 717 | err = audit_set_rate_limit(status_get->rate_limit, | 695 | err = audit_set_rate_limit(status_get->rate_limit); |
| 718 | loginuid, sessionid, sid); | ||
| 719 | if (err < 0) | 696 | if (err < 0) |
| 720 | return err; | 697 | return err; |
| 721 | } | 698 | } |
| 722 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) | 699 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) |
| 723 | err = audit_set_backlog_limit(status_get->backlog_limit, | 700 | err = audit_set_backlog_limit(status_get->backlog_limit); |
| 724 | loginuid, sessionid, sid); | ||
| 725 | break; | 701 | break; |
| 726 | case AUDIT_USER: | 702 | case AUDIT_USER: |
| 727 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: | 703 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: |
| @@ -729,25 +705,22 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 729 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) | 705 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) |
| 730 | return 0; | 706 | return 0; |
| 731 | 707 | ||
| 732 | err = audit_filter_user(); | 708 | err = audit_filter_user(msg_type); |
| 733 | if (err == 1) { | 709 | if (err == 1) { |
| 734 | err = 0; | 710 | err = 0; |
| 735 | if (msg_type == AUDIT_USER_TTY) { | 711 | if (msg_type == AUDIT_USER_TTY) { |
| 736 | err = tty_audit_push_task(current, loginuid, | 712 | err = tty_audit_push_current(); |
| 737 | sessionid); | ||
| 738 | if (err) | 713 | if (err) |
| 739 | break; | 714 | break; |
| 740 | } | 715 | } |
| 741 | audit_log_common_recv_msg(&ab, msg_type, | 716 | audit_log_common_recv_msg(&ab, msg_type); |
| 742 | loginuid, sessionid, sid); | ||
| 743 | |||
| 744 | if (msg_type != AUDIT_USER_TTY) | 717 | if (msg_type != AUDIT_USER_TTY) |
| 745 | audit_log_format(ab, " msg='%.1024s'", | 718 | audit_log_format(ab, " msg='%.1024s'", |
| 746 | (char *)data); | 719 | (char *)data); |
| 747 | else { | 720 | else { |
| 748 | int size; | 721 | int size; |
| 749 | 722 | ||
| 750 | audit_log_format(ab, " msg="); | 723 | audit_log_format(ab, " data="); |
| 751 | size = nlmsg_len(nlh); | 724 | size = nlmsg_len(nlh); |
| 752 | if (size > 0 && | 725 | if (size > 0 && |
| 753 | ((unsigned char *)data)[size - 1] == '\0') | 726 | ((unsigned char *)data)[size - 1] == '\0') |
| @@ -758,50 +731,24 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 758 | audit_log_end(ab); | 731 | audit_log_end(ab); |
| 759 | } | 732 | } |
| 760 | break; | 733 | break; |
| 761 | case AUDIT_ADD: | ||
| 762 | case AUDIT_DEL: | ||
| 763 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) | ||
| 764 | return -EINVAL; | ||
| 765 | if (audit_enabled == AUDIT_LOCKED) { | ||
| 766 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, | ||
| 767 | loginuid, sessionid, sid); | ||
| 768 | |||
| 769 | audit_log_format(ab, " audit_enabled=%d res=0", | ||
| 770 | audit_enabled); | ||
| 771 | audit_log_end(ab); | ||
| 772 | return -EPERM; | ||
| 773 | } | ||
| 774 | /* fallthrough */ | ||
| 775 | case AUDIT_LIST: | ||
| 776 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid, | ||
| 777 | seq, data, nlmsg_len(nlh), | ||
| 778 | loginuid, sessionid, sid); | ||
| 779 | break; | ||
| 780 | case AUDIT_ADD_RULE: | 734 | case AUDIT_ADD_RULE: |
| 781 | case AUDIT_DEL_RULE: | 735 | case AUDIT_DEL_RULE: |
| 782 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) | 736 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) |
| 783 | return -EINVAL; | 737 | return -EINVAL; |
| 784 | if (audit_enabled == AUDIT_LOCKED) { | 738 | if (audit_enabled == AUDIT_LOCKED) { |
| 785 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, | 739 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); |
| 786 | loginuid, sessionid, sid); | 740 | audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled); |
| 787 | |||
| 788 | audit_log_format(ab, " audit_enabled=%d res=0", | ||
| 789 | audit_enabled); | ||
| 790 | audit_log_end(ab); | 741 | audit_log_end(ab); |
| 791 | return -EPERM; | 742 | return -EPERM; |
| 792 | } | 743 | } |
| 793 | /* fallthrough */ | 744 | /* fallthrough */ |
| 794 | case AUDIT_LIST_RULES: | 745 | case AUDIT_LIST_RULES: |
| 795 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid, | 746 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid, |
| 796 | seq, data, nlmsg_len(nlh), | 747 | seq, data, nlmsg_len(nlh)); |
| 797 | loginuid, sessionid, sid); | ||
| 798 | break; | 748 | break; |
| 799 | case AUDIT_TRIM: | 749 | case AUDIT_TRIM: |
| 800 | audit_trim_trees(); | 750 | audit_trim_trees(); |
| 801 | 751 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); | |
| 802 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, | ||
| 803 | loginuid, sessionid, sid); | ||
| 804 | |||
| 805 | audit_log_format(ab, " op=trim res=1"); | 752 | audit_log_format(ab, " op=trim res=1"); |
| 806 | audit_log_end(ab); | 753 | audit_log_end(ab); |
| 807 | break; | 754 | break; |
| @@ -831,8 +778,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 831 | /* OK, here comes... */ | 778 | /* OK, here comes... */ |
| 832 | err = audit_tag_tree(old, new); | 779 | err = audit_tag_tree(old, new); |
| 833 | 780 | ||
| 834 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, | 781 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); |
| 835 | loginuid, sessionid, sid); | ||
| 836 | 782 | ||
| 837 | audit_log_format(ab, " op=make_equiv old="); | 783 | audit_log_format(ab, " op=make_equiv old="); |
| 838 | audit_log_untrustedstring(ab, old); | 784 | audit_log_untrustedstring(ab, old); |
| @@ -871,27 +817,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 871 | struct audit_tty_status s; | 817 | struct audit_tty_status s; |
| 872 | struct task_struct *tsk = current; | 818 | struct task_struct *tsk = current; |
| 873 | 819 | ||
| 874 | spin_lock_irq(&tsk->sighand->siglock); | 820 | spin_lock(&tsk->sighand->siglock); |
| 875 | s.enabled = tsk->signal->audit_tty != 0; | 821 | s.enabled = tsk->signal->audit_tty != 0; |
| 876 | spin_unlock_irq(&tsk->sighand->siglock); | 822 | s.log_passwd = tsk->signal->audit_tty_log_passwd; |
| 823 | spin_unlock(&tsk->sighand->siglock); | ||
| 877 | 824 | ||
| 878 | audit_send_reply(NETLINK_CB(skb).portid, seq, | 825 | audit_send_reply(NETLINK_CB(skb).portid, seq, |
| 879 | AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); | 826 | AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); |
| 880 | break; | 827 | break; |
| 881 | } | 828 | } |
| 882 | case AUDIT_TTY_SET: { | 829 | case AUDIT_TTY_SET: { |
| 883 | struct audit_tty_status *s; | 830 | struct audit_tty_status s; |
| 884 | struct task_struct *tsk = current; | 831 | struct task_struct *tsk = current; |
| 885 | 832 | ||
| 886 | if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) | 833 | memset(&s, 0, sizeof(s)); |
| 887 | return -EINVAL; | 834 | /* guard against past and future API changes */ |
| 888 | s = data; | 835 | memcpy(&s, data, min(sizeof(s), (size_t)nlh->nlmsg_len)); |
| 889 | if (s->enabled != 0 && s->enabled != 1) | 836 | if ((s.enabled != 0 && s.enabled != 1) || |
| 837 | (s.log_passwd != 0 && s.log_passwd != 1)) | ||
| 890 | return -EINVAL; | 838 | return -EINVAL; |
| 891 | 839 | ||
| 892 | spin_lock_irq(&tsk->sighand->siglock); | 840 | spin_lock(&tsk->sighand->siglock); |
| 893 | tsk->signal->audit_tty = s->enabled != 0; | 841 | tsk->signal->audit_tty = s.enabled; |
| 894 | spin_unlock_irq(&tsk->sighand->siglock); | 842 | tsk->signal->audit_tty_log_passwd = s.log_passwd; |
| 843 | spin_unlock(&tsk->sighand->siglock); | ||
| 895 | break; | 844 | break; |
| 896 | } | 845 | } |
| 897 | default: | 846 | default: |
| @@ -1434,6 +1383,14 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix, | |||
| 1434 | kfree(pathname); | 1383 | kfree(pathname); |
| 1435 | } | 1384 | } |
| 1436 | 1385 | ||
| 1386 | void audit_log_session_info(struct audit_buffer *ab) | ||
| 1387 | { | ||
| 1388 | u32 sessionid = audit_get_sessionid(current); | ||
| 1389 | uid_t auid = from_kuid(&init_user_ns, audit_get_loginuid(current)); | ||
| 1390 | |||
| 1391 | audit_log_format(ab, " auid=%u ses=%u\n", auid, sessionid); | ||
| 1392 | } | ||
| 1393 | |||
| 1437 | void audit_log_key(struct audit_buffer *ab, char *key) | 1394 | void audit_log_key(struct audit_buffer *ab, char *key) |
| 1438 | { | 1395 | { |
| 1439 | audit_log_format(ab, " key="); | 1396 | audit_log_format(ab, " key="); |
| @@ -1443,6 +1400,224 @@ void audit_log_key(struct audit_buffer *ab, char *key) | |||
| 1443 | audit_log_format(ab, "(null)"); | 1400 | audit_log_format(ab, "(null)"); |
| 1444 | } | 1401 | } |
| 1445 | 1402 | ||
| 1403 | void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) | ||
| 1404 | { | ||
| 1405 | int i; | ||
| 1406 | |||
| 1407 | audit_log_format(ab, " %s=", prefix); | ||
| 1408 | CAP_FOR_EACH_U32(i) { | ||
| 1409 | audit_log_format(ab, "%08x", | ||
| 1410 | cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]); | ||
| 1411 | } | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) | ||
| 1415 | { | ||
| 1416 | kernel_cap_t *perm = &name->fcap.permitted; | ||
| 1417 | kernel_cap_t *inh = &name->fcap.inheritable; | ||
| 1418 | int log = 0; | ||
| 1419 | |||
| 1420 | if (!cap_isclear(*perm)) { | ||
| 1421 | audit_log_cap(ab, "cap_fp", perm); | ||
| 1422 | log = 1; | ||
| 1423 | } | ||
| 1424 | if (!cap_isclear(*inh)) { | ||
| 1425 | audit_log_cap(ab, "cap_fi", inh); | ||
| 1426 | log = 1; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | if (log) | ||
| 1430 | audit_log_format(ab, " cap_fe=%d cap_fver=%x", | ||
| 1431 | name->fcap.fE, name->fcap_ver); | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | static inline int audit_copy_fcaps(struct audit_names *name, | ||
| 1435 | const struct dentry *dentry) | ||
| 1436 | { | ||
| 1437 | struct cpu_vfs_cap_data caps; | ||
| 1438 | int rc; | ||
| 1439 | |||
| 1440 | if (!dentry) | ||
| 1441 | return 0; | ||
| 1442 | |||
| 1443 | rc = get_vfs_caps_from_disk(dentry, &caps); | ||
| 1444 | if (rc) | ||
| 1445 | return rc; | ||
| 1446 | |||
| 1447 | name->fcap.permitted = caps.permitted; | ||
| 1448 | name->fcap.inheritable = caps.inheritable; | ||
| 1449 | name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); | ||
| 1450 | name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> | ||
| 1451 | VFS_CAP_REVISION_SHIFT; | ||
| 1452 | |||
| 1453 | return 0; | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | /* Copy inode data into an audit_names. */ | ||
| 1457 | void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, | ||
| 1458 | const struct inode *inode) | ||
| 1459 | { | ||
| 1460 | name->ino = inode->i_ino; | ||
| 1461 | name->dev = inode->i_sb->s_dev; | ||
| 1462 | name->mode = inode->i_mode; | ||
| 1463 | name->uid = inode->i_uid; | ||
| 1464 | name->gid = inode->i_gid; | ||
| 1465 | name->rdev = inode->i_rdev; | ||
| 1466 | security_inode_getsecid(inode, &name->osid); | ||
| 1467 | audit_copy_fcaps(name, dentry); | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | /** | ||
| 1471 | * audit_log_name - produce AUDIT_PATH record from struct audit_names | ||
| 1472 | * @context: audit_context for the task | ||
| 1473 | * @n: audit_names structure with reportable details | ||
| 1474 | * @path: optional path to report instead of audit_names->name | ||
| 1475 | * @record_num: record number to report when handling a list of names | ||
| 1476 | * @call_panic: optional pointer to int that will be updated if secid fails | ||
| 1477 | */ | ||
| 1478 | void audit_log_name(struct audit_context *context, struct audit_names *n, | ||
| 1479 | struct path *path, int record_num, int *call_panic) | ||
| 1480 | { | ||
| 1481 | struct audit_buffer *ab; | ||
| 1482 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); | ||
| 1483 | if (!ab) | ||
| 1484 | return; | ||
| 1485 | |||
| 1486 | audit_log_format(ab, "item=%d", record_num); | ||
| 1487 | |||
| 1488 | if (path) | ||
| 1489 | audit_log_d_path(ab, " name=", path); | ||
| 1490 | else if (n->name) { | ||
| 1491 | switch (n->name_len) { | ||
| 1492 | case AUDIT_NAME_FULL: | ||
| 1493 | /* log the full path */ | ||
| 1494 | audit_log_format(ab, " name="); | ||
| 1495 | audit_log_untrustedstring(ab, n->name->name); | ||
| 1496 | break; | ||
| 1497 | case 0: | ||
| 1498 | /* name was specified as a relative path and the | ||
| 1499 | * directory component is the cwd */ | ||
| 1500 | audit_log_d_path(ab, " name=", &context->pwd); | ||
| 1501 | break; | ||
| 1502 | default: | ||
| 1503 | /* log the name's directory component */ | ||
| 1504 | audit_log_format(ab, " name="); | ||
| 1505 | audit_log_n_untrustedstring(ab, n->name->name, | ||
| 1506 | n->name_len); | ||
| 1507 | } | ||
| 1508 | } else | ||
| 1509 | audit_log_format(ab, " name=(null)"); | ||
| 1510 | |||
| 1511 | if (n->ino != (unsigned long)-1) { | ||
| 1512 | audit_log_format(ab, " inode=%lu" | ||
| 1513 | " dev=%02x:%02x mode=%#ho" | ||
| 1514 | " ouid=%u ogid=%u rdev=%02x:%02x", | ||
| 1515 | n->ino, | ||
| 1516 | MAJOR(n->dev), | ||
| 1517 | MINOR(n->dev), | ||
| 1518 | n->mode, | ||
| 1519 | from_kuid(&init_user_ns, n->uid), | ||
| 1520 | from_kgid(&init_user_ns, n->gid), | ||
| 1521 | MAJOR(n->rdev), | ||
| 1522 | MINOR(n->rdev)); | ||
| 1523 | } | ||
| 1524 | if (n->osid != 0) { | ||
| 1525 | char *ctx = NULL; | ||
| 1526 | u32 len; | ||
| 1527 | if (security_secid_to_secctx( | ||
| 1528 | n->osid, &ctx, &len)) { | ||
| 1529 | audit_log_format(ab, " osid=%u", n->osid); | ||
| 1530 | if (call_panic) | ||
| 1531 | *call_panic = 2; | ||
| 1532 | } else { | ||
| 1533 | audit_log_format(ab, " obj=%s", ctx); | ||
| 1534 | security_release_secctx(ctx, len); | ||
| 1535 | } | ||
| 1536 | } | ||
| 1537 | |||
| 1538 | audit_log_fcaps(ab, n); | ||
| 1539 | audit_log_end(ab); | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | int audit_log_task_context(struct audit_buffer *ab) | ||
| 1543 | { | ||
| 1544 | char *ctx = NULL; | ||
| 1545 | unsigned len; | ||
| 1546 | int error; | ||
| 1547 | u32 sid; | ||
| 1548 | |||
| 1549 | security_task_getsecid(current, &sid); | ||
| 1550 | if (!sid) | ||
| 1551 | return 0; | ||
| 1552 | |||
| 1553 | error = security_secid_to_secctx(sid, &ctx, &len); | ||
| 1554 | if (error) { | ||
| 1555 | if (error != -EINVAL) | ||
| 1556 | goto error_path; | ||
| 1557 | return 0; | ||
| 1558 | } | ||
| 1559 | |||
| 1560 | audit_log_format(ab, " subj=%s", ctx); | ||
| 1561 | security_release_secctx(ctx, len); | ||
| 1562 | return 0; | ||
| 1563 | |||
| 1564 | error_path: | ||
| 1565 | audit_panic("error in audit_log_task_context"); | ||
| 1566 | return error; | ||
| 1567 | } | ||
| 1568 | EXPORT_SYMBOL(audit_log_task_context); | ||
| 1569 | |||
| 1570 | void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) | ||
| 1571 | { | ||
| 1572 | const struct cred *cred; | ||
| 1573 | char name[sizeof(tsk->comm)]; | ||
| 1574 | struct mm_struct *mm = tsk->mm; | ||
| 1575 | char *tty; | ||
| 1576 | |||
| 1577 | if (!ab) | ||
| 1578 | return; | ||
| 1579 | |||
| 1580 | /* tsk == current */ | ||
| 1581 | cred = current_cred(); | ||
| 1582 | |||
| 1583 | spin_lock_irq(&tsk->sighand->siglock); | ||
| 1584 | if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) | ||
| 1585 | tty = tsk->signal->tty->name; | ||
| 1586 | else | ||
| 1587 | tty = "(none)"; | ||
| 1588 | spin_unlock_irq(&tsk->sighand->siglock); | ||
| 1589 | |||
| 1590 | audit_log_format(ab, | ||
| 1591 | " ppid=%ld pid=%d auid=%u uid=%u gid=%u" | ||
| 1592 | " euid=%u suid=%u fsuid=%u" | ||
| 1593 | " egid=%u sgid=%u fsgid=%u ses=%u tty=%s", | ||
| 1594 | sys_getppid(), | ||
| 1595 | tsk->pid, | ||
| 1596 | from_kuid(&init_user_ns, audit_get_loginuid(tsk)), | ||
| 1597 | from_kuid(&init_user_ns, cred->uid), | ||
| 1598 | from_kgid(&init_user_ns, cred->gid), | ||
| 1599 | from_kuid(&init_user_ns, cred->euid), | ||
| 1600 | from_kuid(&init_user_ns, cred->suid), | ||
| 1601 | from_kuid(&init_user_ns, cred->fsuid), | ||
| 1602 | from_kgid(&init_user_ns, cred->egid), | ||
| 1603 | from_kgid(&init_user_ns, cred->sgid), | ||
| 1604 | from_kgid(&init_user_ns, cred->fsgid), | ||
| 1605 | audit_get_sessionid(tsk), tty); | ||
| 1606 | |||
| 1607 | get_task_comm(name, tsk); | ||
| 1608 | audit_log_format(ab, " comm="); | ||
| 1609 | audit_log_untrustedstring(ab, name); | ||
| 1610 | |||
| 1611 | if (mm) { | ||
| 1612 | down_read(&mm->mmap_sem); | ||
| 1613 | if (mm->exe_file) | ||
| 1614 | audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); | ||
| 1615 | up_read(&mm->mmap_sem); | ||
| 1616 | } | ||
| 1617 | audit_log_task_context(ab); | ||
| 1618 | } | ||
| 1619 | EXPORT_SYMBOL(audit_log_task_info); | ||
| 1620 | |||
| 1446 | /** | 1621 | /** |
| 1447 | * audit_log_link_denied - report a link restriction denial | 1622 | * audit_log_link_denied - report a link restriction denial |
| 1448 | * @operation: specific link opreation | 1623 | * @operation: specific link opreation |
| @@ -1451,19 +1626,28 @@ void audit_log_key(struct audit_buffer *ab, char *key) | |||
| 1451 | void audit_log_link_denied(const char *operation, struct path *link) | 1626 | void audit_log_link_denied(const char *operation, struct path *link) |
| 1452 | { | 1627 | { |
| 1453 | struct audit_buffer *ab; | 1628 | struct audit_buffer *ab; |
| 1629 | struct audit_names *name; | ||
| 1630 | |||
| 1631 | name = kzalloc(sizeof(*name), GFP_NOFS); | ||
| 1632 | if (!name) | ||
| 1633 | return; | ||
| 1454 | 1634 | ||
| 1635 | /* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */ | ||
| 1455 | ab = audit_log_start(current->audit_context, GFP_KERNEL, | 1636 | ab = audit_log_start(current->audit_context, GFP_KERNEL, |
| 1456 | AUDIT_ANOM_LINK); | 1637 | AUDIT_ANOM_LINK); |
| 1457 | if (!ab) | 1638 | if (!ab) |
| 1458 | return; | 1639 | goto out; |
| 1459 | audit_log_format(ab, "op=%s action=denied", operation); | 1640 | audit_log_format(ab, "op=%s", operation); |
| 1460 | audit_log_format(ab, " pid=%d comm=", current->pid); | 1641 | audit_log_task_info(ab, current); |
| 1461 | audit_log_untrustedstring(ab, current->comm); | 1642 | audit_log_format(ab, " res=0"); |
| 1462 | audit_log_d_path(ab, " path=", link); | ||
| 1463 | audit_log_format(ab, " dev="); | ||
| 1464 | audit_log_untrustedstring(ab, link->dentry->d_inode->i_sb->s_id); | ||
| 1465 | audit_log_format(ab, " ino=%lu", link->dentry->d_inode->i_ino); | ||
| 1466 | audit_log_end(ab); | 1643 | audit_log_end(ab); |
| 1644 | |||
| 1645 | /* Generate AUDIT_PATH record with object. */ | ||
| 1646 | name->type = AUDIT_TYPE_NORMAL; | ||
| 1647 | audit_copy_inode(name, link->dentry, link->dentry->d_inode); | ||
| 1648 | audit_log_name(current->audit_context, name, link, 0, NULL); | ||
| 1649 | out: | ||
| 1650 | kfree(name); | ||
| 1467 | } | 1651 | } |
| 1468 | 1652 | ||
| 1469 | /** | 1653 | /** |
diff --git a/kernel/audit.h b/kernel/audit.h index 11468d99dad0..1c95131ef760 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
| 23 | #include <linux/audit.h> | 23 | #include <linux/audit.h> |
| 24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
| 25 | #include <uapi/linux/mqueue.h> | ||
| 25 | 26 | ||
| 26 | /* 0 = no checking | 27 | /* 0 = no checking |
| 27 | 1 = put_count checking | 28 | 1 = put_count checking |
| @@ -29,6 +30,11 @@ | |||
| 29 | */ | 30 | */ |
| 30 | #define AUDIT_DEBUG 0 | 31 | #define AUDIT_DEBUG 0 |
| 31 | 32 | ||
| 33 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | ||
| 34 | * for saving names from getname(). If we get more names we will allocate | ||
| 35 | * a name dynamically and also add those to the list anchored by names_list. */ | ||
| 36 | #define AUDIT_NAMES 5 | ||
| 37 | |||
| 32 | /* At task start time, the audit_state is set in the audit_context using | 38 | /* At task start time, the audit_state is set in the audit_context using |
| 33 | a per-task filter. At syscall entry, the audit_state is augmented by | 39 | a per-task filter. At syscall entry, the audit_state is augmented by |
| 34 | the syscall filter. */ | 40 | the syscall filter. */ |
| @@ -59,8 +65,158 @@ struct audit_entry { | |||
| 59 | struct audit_krule rule; | 65 | struct audit_krule rule; |
| 60 | }; | 66 | }; |
| 61 | 67 | ||
| 68 | struct audit_cap_data { | ||
| 69 | kernel_cap_t permitted; | ||
| 70 | kernel_cap_t inheritable; | ||
| 71 | union { | ||
| 72 | unsigned int fE; /* effective bit of file cap */ | ||
| 73 | kernel_cap_t effective; /* effective set of process */ | ||
| 74 | }; | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* When fs/namei.c:getname() is called, we store the pointer in name and | ||
| 78 | * we don't let putname() free it (instead we free all of the saved | ||
| 79 | * pointers at syscall exit time). | ||
| 80 | * | ||
| 81 | * Further, in fs/namei.c:path_lookup() we store the inode and device. | ||
| 82 | */ | ||
| 83 | struct audit_names { | ||
| 84 | struct list_head list; /* audit_context->names_list */ | ||
| 85 | |||
| 86 | struct filename *name; | ||
| 87 | int name_len; /* number of chars to log */ | ||
| 88 | bool name_put; /* call __putname()? */ | ||
| 89 | |||
| 90 | unsigned long ino; | ||
| 91 | dev_t dev; | ||
| 92 | umode_t mode; | ||
| 93 | kuid_t uid; | ||
| 94 | kgid_t gid; | ||
| 95 | dev_t rdev; | ||
| 96 | u32 osid; | ||
| 97 | struct audit_cap_data fcap; | ||
| 98 | unsigned int fcap_ver; | ||
| 99 | unsigned char type; /* record type */ | ||
| 100 | /* | ||
| 101 | * This was an allocated audit_names and not from the array of | ||
| 102 | * names allocated in the task audit context. Thus this name | ||
| 103 | * should be freed on syscall exit. | ||
| 104 | */ | ||
| 105 | bool should_free; | ||
| 106 | }; | ||
| 107 | |||
| 108 | /* The per-task audit context. */ | ||
| 109 | struct audit_context { | ||
| 110 | int dummy; /* must be the first element */ | ||
| 111 | int in_syscall; /* 1 if task is in a syscall */ | ||
| 112 | enum audit_state state, current_state; | ||
| 113 | unsigned int serial; /* serial number for record */ | ||
| 114 | int major; /* syscall number */ | ||
| 115 | struct timespec ctime; /* time of syscall entry */ | ||
| 116 | unsigned long argv[4]; /* syscall arguments */ | ||
| 117 | long return_code;/* syscall return code */ | ||
| 118 | u64 prio; | ||
| 119 | int return_valid; /* return code is valid */ | ||
| 120 | /* | ||
| 121 | * The names_list is the list of all audit_names collected during this | ||
| 122 | * syscall. The first AUDIT_NAMES entries in the names_list will | ||
| 123 | * actually be from the preallocated_names array for performance | ||
| 124 | * reasons. Except during allocation they should never be referenced | ||
| 125 | * through the preallocated_names array and should only be found/used | ||
| 126 | * by running the names_list. | ||
| 127 | */ | ||
| 128 | struct audit_names preallocated_names[AUDIT_NAMES]; | ||
| 129 | int name_count; /* total records in names_list */ | ||
| 130 | struct list_head names_list; /* struct audit_names->list anchor */ | ||
| 131 | char *filterkey; /* key for rule that triggered record */ | ||
| 132 | struct path pwd; | ||
| 133 | struct audit_aux_data *aux; | ||
| 134 | struct audit_aux_data *aux_pids; | ||
| 135 | struct sockaddr_storage *sockaddr; | ||
| 136 | size_t sockaddr_len; | ||
| 137 | /* Save things to print about task_struct */ | ||
| 138 | pid_t pid, ppid; | ||
| 139 | kuid_t uid, euid, suid, fsuid; | ||
| 140 | kgid_t gid, egid, sgid, fsgid; | ||
| 141 | unsigned long personality; | ||
| 142 | int arch; | ||
| 143 | |||
| 144 | pid_t target_pid; | ||
| 145 | kuid_t target_auid; | ||
| 146 | kuid_t target_uid; | ||
| 147 | unsigned int target_sessionid; | ||
| 148 | u32 target_sid; | ||
| 149 | char target_comm[TASK_COMM_LEN]; | ||
| 150 | |||
| 151 | struct audit_tree_refs *trees, *first_trees; | ||
| 152 | struct list_head killed_trees; | ||
| 153 | int tree_count; | ||
| 154 | |||
| 155 | int type; | ||
| 156 | union { | ||
| 157 | struct { | ||
| 158 | int nargs; | ||
| 159 | long args[6]; | ||
| 160 | } socketcall; | ||
| 161 | struct { | ||
| 162 | kuid_t uid; | ||
| 163 | kgid_t gid; | ||
| 164 | umode_t mode; | ||
| 165 | u32 osid; | ||
| 166 | int has_perm; | ||
| 167 | uid_t perm_uid; | ||
| 168 | gid_t perm_gid; | ||
| 169 | umode_t perm_mode; | ||
| 170 | unsigned long qbytes; | ||
| 171 | } ipc; | ||
| 172 | struct { | ||
| 173 | mqd_t mqdes; | ||
| 174 | struct mq_attr mqstat; | ||
| 175 | } mq_getsetattr; | ||
| 176 | struct { | ||
| 177 | mqd_t mqdes; | ||
| 178 | int sigev_signo; | ||
| 179 | } mq_notify; | ||
| 180 | struct { | ||
| 181 | mqd_t mqdes; | ||
| 182 | size_t msg_len; | ||
| 183 | unsigned int msg_prio; | ||
| 184 | struct timespec abs_timeout; | ||
| 185 | } mq_sendrecv; | ||
| 186 | struct { | ||
| 187 | int oflag; | ||
| 188 | umode_t mode; | ||
| 189 | struct mq_attr attr; | ||
| 190 | } mq_open; | ||
| 191 | struct { | ||
| 192 | pid_t pid; | ||
| 193 | struct audit_cap_data cap; | ||
| 194 | } capset; | ||
| 195 | struct { | ||
| 196 | int fd; | ||
| 197 | int flags; | ||
| 198 | } mmap; | ||
| 199 | }; | ||
| 200 | int fds[2]; | ||
| 201 | |||
| 202 | #if AUDIT_DEBUG | ||
| 203 | int put_count; | ||
| 204 | int ino_count; | ||
| 205 | #endif | ||
| 206 | }; | ||
| 207 | |||
| 62 | extern int audit_ever_enabled; | 208 | extern int audit_ever_enabled; |
| 63 | 209 | ||
| 210 | extern void audit_copy_inode(struct audit_names *name, | ||
| 211 | const struct dentry *dentry, | ||
| 212 | const struct inode *inode); | ||
| 213 | extern void audit_log_cap(struct audit_buffer *ab, char *prefix, | ||
| 214 | kernel_cap_t *cap); | ||
| 215 | extern void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name); | ||
| 216 | extern void audit_log_name(struct audit_context *context, | ||
| 217 | struct audit_names *n, struct path *path, | ||
| 218 | int record_num, int *call_panic); | ||
| 219 | |||
| 64 | extern int audit_pid; | 220 | extern int audit_pid; |
| 65 | 221 | ||
| 66 | #define AUDIT_INODE_BUCKETS 32 | 222 | #define AUDIT_INODE_BUCKETS 32 |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 267436826c3b..83a2970295d1 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -310,121 +310,83 @@ static u32 audit_to_op(u32 op) | |||
| 310 | return n; | 310 | return n; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | 313 | /* check if an audit field is valid */ | |
| 314 | /* Translate struct audit_rule to kernel's rule respresentation. | 314 | static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) |
| 315 | * Exists for backward compatibility with userspace. */ | ||
| 316 | static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | ||
| 317 | { | 315 | { |
| 318 | struct audit_entry *entry; | 316 | switch(f->type) { |
| 319 | int err = 0; | 317 | case AUDIT_MSGTYPE: |
| 320 | int i; | 318 | if (entry->rule.listnr != AUDIT_FILTER_TYPE && |
| 321 | 319 | entry->rule.listnr != AUDIT_FILTER_USER) | |
| 322 | entry = audit_to_entry_common(rule); | 320 | return -EINVAL; |
| 323 | if (IS_ERR(entry)) | 321 | break; |
| 324 | goto exit_nofree; | 322 | }; |
| 325 | |||
| 326 | for (i = 0; i < rule->field_count; i++) { | ||
| 327 | struct audit_field *f = &entry->rule.fields[i]; | ||
| 328 | u32 n; | ||
| 329 | |||
| 330 | n = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS); | ||
| 331 | |||
| 332 | /* Support for legacy operators where | ||
| 333 | * AUDIT_NEGATE bit signifies != and otherwise assumes == */ | ||
| 334 | if (n & AUDIT_NEGATE) | ||
| 335 | f->op = Audit_not_equal; | ||
| 336 | else if (!n) | ||
| 337 | f->op = Audit_equal; | ||
| 338 | else | ||
| 339 | f->op = audit_to_op(n); | ||
| 340 | |||
| 341 | entry->rule.vers_ops = (n & AUDIT_OPERATORS) ? 2 : 1; | ||
| 342 | |||
| 343 | f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS); | ||
| 344 | f->val = rule->values[i]; | ||
| 345 | f->uid = INVALID_UID; | ||
| 346 | f->gid = INVALID_GID; | ||
| 347 | |||
| 348 | err = -EINVAL; | ||
| 349 | if (f->op == Audit_bad) | ||
| 350 | goto exit_free; | ||
| 351 | |||
| 352 | switch(f->type) { | ||
| 353 | default: | ||
| 354 | goto exit_free; | ||
| 355 | case AUDIT_UID: | ||
| 356 | case AUDIT_EUID: | ||
| 357 | case AUDIT_SUID: | ||
| 358 | case AUDIT_FSUID: | ||
| 359 | case AUDIT_LOGINUID: | ||
| 360 | /* bit ops not implemented for uid comparisons */ | ||
| 361 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 362 | goto exit_free; | ||
| 363 | |||
| 364 | f->uid = make_kuid(current_user_ns(), f->val); | ||
| 365 | if (!uid_valid(f->uid)) | ||
| 366 | goto exit_free; | ||
| 367 | break; | ||
| 368 | case AUDIT_GID: | ||
| 369 | case AUDIT_EGID: | ||
| 370 | case AUDIT_SGID: | ||
| 371 | case AUDIT_FSGID: | ||
| 372 | /* bit ops not implemented for gid comparisons */ | ||
| 373 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 374 | goto exit_free; | ||
| 375 | |||
| 376 | f->gid = make_kgid(current_user_ns(), f->val); | ||
| 377 | if (!gid_valid(f->gid)) | ||
| 378 | goto exit_free; | ||
| 379 | break; | ||
| 380 | case AUDIT_PID: | ||
| 381 | case AUDIT_PERS: | ||
| 382 | case AUDIT_MSGTYPE: | ||
| 383 | case AUDIT_PPID: | ||
| 384 | case AUDIT_DEVMAJOR: | ||
| 385 | case AUDIT_DEVMINOR: | ||
| 386 | case AUDIT_EXIT: | ||
| 387 | case AUDIT_SUCCESS: | ||
| 388 | /* bit ops are only useful on syscall args */ | ||
| 389 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 390 | goto exit_free; | ||
| 391 | break; | ||
| 392 | case AUDIT_ARG0: | ||
| 393 | case AUDIT_ARG1: | ||
| 394 | case AUDIT_ARG2: | ||
| 395 | case AUDIT_ARG3: | ||
| 396 | break; | ||
| 397 | /* arch is only allowed to be = or != */ | ||
| 398 | case AUDIT_ARCH: | ||
| 399 | if (f->op != Audit_not_equal && f->op != Audit_equal) | ||
| 400 | goto exit_free; | ||
| 401 | entry->rule.arch_f = f; | ||
| 402 | break; | ||
| 403 | case AUDIT_PERM: | ||
| 404 | if (f->val & ~15) | ||
| 405 | goto exit_free; | ||
| 406 | break; | ||
| 407 | case AUDIT_FILETYPE: | ||
| 408 | if (f->val & ~S_IFMT) | ||
| 409 | goto exit_free; | ||
| 410 | break; | ||
| 411 | case AUDIT_INODE: | ||
| 412 | err = audit_to_inode(&entry->rule, f); | ||
| 413 | if (err) | ||
| 414 | goto exit_free; | ||
| 415 | break; | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 419 | if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal) | ||
| 420 | entry->rule.inode_f = NULL; | ||
| 421 | |||
| 422 | exit_nofree: | ||
| 423 | return entry; | ||
| 424 | 323 | ||
| 425 | exit_free: | 324 | switch(f->type) { |
| 426 | audit_free_rule(entry); | 325 | default: |
| 427 | return ERR_PTR(err); | 326 | return -EINVAL; |
| 327 | case AUDIT_UID: | ||
| 328 | case AUDIT_EUID: | ||
| 329 | case AUDIT_SUID: | ||
| 330 | case AUDIT_FSUID: | ||
| 331 | case AUDIT_LOGINUID: | ||
| 332 | case AUDIT_OBJ_UID: | ||
| 333 | case AUDIT_GID: | ||
| 334 | case AUDIT_EGID: | ||
| 335 | case AUDIT_SGID: | ||
| 336 | case AUDIT_FSGID: | ||
| 337 | case AUDIT_OBJ_GID: | ||
| 338 | case AUDIT_PID: | ||
| 339 | case AUDIT_PERS: | ||
| 340 | case AUDIT_MSGTYPE: | ||
| 341 | case AUDIT_PPID: | ||
| 342 | case AUDIT_DEVMAJOR: | ||
| 343 | case AUDIT_DEVMINOR: | ||
| 344 | case AUDIT_EXIT: | ||
| 345 | case AUDIT_SUCCESS: | ||
| 346 | /* bit ops are only useful on syscall args */ | ||
| 347 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 348 | return -EINVAL; | ||
| 349 | break; | ||
| 350 | case AUDIT_ARG0: | ||
| 351 | case AUDIT_ARG1: | ||
| 352 | case AUDIT_ARG2: | ||
| 353 | case AUDIT_ARG3: | ||
| 354 | case AUDIT_SUBJ_USER: | ||
| 355 | case AUDIT_SUBJ_ROLE: | ||
| 356 | case AUDIT_SUBJ_TYPE: | ||
| 357 | case AUDIT_SUBJ_SEN: | ||
| 358 | case AUDIT_SUBJ_CLR: | ||
| 359 | case AUDIT_OBJ_USER: | ||
| 360 | case AUDIT_OBJ_ROLE: | ||
| 361 | case AUDIT_OBJ_TYPE: | ||
| 362 | case AUDIT_OBJ_LEV_LOW: | ||
| 363 | case AUDIT_OBJ_LEV_HIGH: | ||
| 364 | case AUDIT_WATCH: | ||
| 365 | case AUDIT_DIR: | ||
| 366 | case AUDIT_FILTERKEY: | ||
| 367 | break; | ||
| 368 | case AUDIT_LOGINUID_SET: | ||
| 369 | if ((f->val != 0) && (f->val != 1)) | ||
| 370 | return -EINVAL; | ||
| 371 | /* FALL THROUGH */ | ||
| 372 | case AUDIT_ARCH: | ||
| 373 | if (f->op != Audit_not_equal && f->op != Audit_equal) | ||
| 374 | return -EINVAL; | ||
| 375 | break; | ||
| 376 | case AUDIT_PERM: | ||
| 377 | if (f->val & ~15) | ||
| 378 | return -EINVAL; | ||
| 379 | break; | ||
| 380 | case AUDIT_FILETYPE: | ||
| 381 | if (f->val & ~S_IFMT) | ||
| 382 | return -EINVAL; | ||
| 383 | break; | ||
| 384 | case AUDIT_FIELD_COMPARE: | ||
| 385 | if (f->val > AUDIT_MAX_FIELD_COMPARE) | ||
| 386 | return -EINVAL; | ||
| 387 | break; | ||
| 388 | }; | ||
| 389 | return 0; | ||
| 428 | } | 390 | } |
| 429 | 391 | ||
| 430 | /* Translate struct audit_rule_data to kernel's rule respresentation. */ | 392 | /* Translate struct audit_rule_data to kernel's rule respresentation. */ |
| @@ -459,17 +421,25 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 459 | f->gid = INVALID_GID; | 421 | f->gid = INVALID_GID; |
| 460 | f->lsm_str = NULL; | 422 | f->lsm_str = NULL; |
| 461 | f->lsm_rule = NULL; | 423 | f->lsm_rule = NULL; |
| 462 | switch(f->type) { | 424 | |
| 425 | /* Support legacy tests for a valid loginuid */ | ||
| 426 | if ((f->type == AUDIT_LOGINUID) && (f->val == 4294967295)) { | ||
| 427 | f->type = AUDIT_LOGINUID_SET; | ||
| 428 | f->val = 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | err = audit_field_valid(entry, f); | ||
| 432 | if (err) | ||
| 433 | goto exit_free; | ||
| 434 | |||
| 435 | err = -EINVAL; | ||
| 436 | switch (f->type) { | ||
| 437 | case AUDIT_LOGINUID: | ||
| 463 | case AUDIT_UID: | 438 | case AUDIT_UID: |
| 464 | case AUDIT_EUID: | 439 | case AUDIT_EUID: |
| 465 | case AUDIT_SUID: | 440 | case AUDIT_SUID: |
| 466 | case AUDIT_FSUID: | 441 | case AUDIT_FSUID: |
| 467 | case AUDIT_LOGINUID: | ||
| 468 | case AUDIT_OBJ_UID: | 442 | case AUDIT_OBJ_UID: |
| 469 | /* bit ops not implemented for uid comparisons */ | ||
| 470 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 471 | goto exit_free; | ||
| 472 | |||
| 473 | f->uid = make_kuid(current_user_ns(), f->val); | 443 | f->uid = make_kuid(current_user_ns(), f->val); |
| 474 | if (!uid_valid(f->uid)) | 444 | if (!uid_valid(f->uid)) |
| 475 | goto exit_free; | 445 | goto exit_free; |
| @@ -479,27 +449,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 479 | case AUDIT_SGID: | 449 | case AUDIT_SGID: |
| 480 | case AUDIT_FSGID: | 450 | case AUDIT_FSGID: |
| 481 | case AUDIT_OBJ_GID: | 451 | case AUDIT_OBJ_GID: |
| 482 | /* bit ops not implemented for gid comparisons */ | ||
| 483 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 484 | goto exit_free; | ||
| 485 | |||
| 486 | f->gid = make_kgid(current_user_ns(), f->val); | 452 | f->gid = make_kgid(current_user_ns(), f->val); |
| 487 | if (!gid_valid(f->gid)) | 453 | if (!gid_valid(f->gid)) |
| 488 | goto exit_free; | 454 | goto exit_free; |
| 489 | break; | 455 | break; |
| 490 | case AUDIT_PID: | ||
| 491 | case AUDIT_PERS: | ||
| 492 | case AUDIT_MSGTYPE: | ||
| 493 | case AUDIT_PPID: | ||
| 494 | case AUDIT_DEVMAJOR: | ||
| 495 | case AUDIT_DEVMINOR: | ||
| 496 | case AUDIT_EXIT: | ||
| 497 | case AUDIT_SUCCESS: | ||
| 498 | case AUDIT_ARG0: | ||
| 499 | case AUDIT_ARG1: | ||
| 500 | case AUDIT_ARG2: | ||
| 501 | case AUDIT_ARG3: | ||
| 502 | break; | ||
| 503 | case AUDIT_ARCH: | 456 | case AUDIT_ARCH: |
| 504 | entry->rule.arch_f = f; | 457 | entry->rule.arch_f = f; |
| 505 | break; | 458 | break; |
| @@ -570,20 +523,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 570 | entry->rule.buflen += f->val; | 523 | entry->rule.buflen += f->val; |
| 571 | entry->rule.filterkey = str; | 524 | entry->rule.filterkey = str; |
| 572 | break; | 525 | break; |
| 573 | case AUDIT_PERM: | ||
| 574 | if (f->val & ~15) | ||
| 575 | goto exit_free; | ||
| 576 | break; | ||
| 577 | case AUDIT_FILETYPE: | ||
| 578 | if (f->val & ~S_IFMT) | ||
| 579 | goto exit_free; | ||
| 580 | break; | ||
| 581 | case AUDIT_FIELD_COMPARE: | ||
| 582 | if (f->val > AUDIT_MAX_FIELD_COMPARE) | ||
| 583 | goto exit_free; | ||
| 584 | break; | ||
| 585 | default: | ||
| 586 | goto exit_free; | ||
| 587 | } | 526 | } |
| 588 | } | 527 | } |
| 589 | 528 | ||
| @@ -613,36 +552,6 @@ static inline size_t audit_pack_string(void **bufp, const char *str) | |||
| 613 | return len; | 552 | return len; |
| 614 | } | 553 | } |
| 615 | 554 | ||
| 616 | /* Translate kernel rule respresentation to struct audit_rule. | ||
| 617 | * Exists for backward compatibility with userspace. */ | ||
| 618 | static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule) | ||
| 619 | { | ||
| 620 | struct audit_rule *rule; | ||
| 621 | int i; | ||
| 622 | |||
| 623 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); | ||
| 624 | if (unlikely(!rule)) | ||
| 625 | return NULL; | ||
| 626 | |||
| 627 | rule->flags = krule->flags | krule->listnr; | ||
| 628 | rule->action = krule->action; | ||
| 629 | rule->field_count = krule->field_count; | ||
| 630 | for (i = 0; i < rule->field_count; i++) { | ||
| 631 | rule->values[i] = krule->fields[i].val; | ||
| 632 | rule->fields[i] = krule->fields[i].type; | ||
| 633 | |||
| 634 | if (krule->vers_ops == 1) { | ||
| 635 | if (krule->fields[i].op == Audit_not_equal) | ||
| 636 | rule->fields[i] |= AUDIT_NEGATE; | ||
| 637 | } else { | ||
| 638 | rule->fields[i] |= audit_ops[krule->fields[i].op]; | ||
| 639 | } | ||
| 640 | } | ||
| 641 | for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i]; | ||
| 642 | |||
| 643 | return rule; | ||
| 644 | } | ||
| 645 | |||
| 646 | /* Translate kernel rule respresentation to struct audit_rule_data. */ | 555 | /* Translate kernel rule respresentation to struct audit_rule_data. */ |
| 647 | static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) | 556 | static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) |
| 648 | { | 557 | { |
| @@ -1055,35 +964,6 @@ out: | |||
| 1055 | return ret; | 964 | return ret; |
| 1056 | } | 965 | } |
| 1057 | 966 | ||
| 1058 | /* List rules using struct audit_rule. Exists for backward | ||
| 1059 | * compatibility with userspace. */ | ||
| 1060 | static void audit_list(int pid, int seq, struct sk_buff_head *q) | ||
| 1061 | { | ||
| 1062 | struct sk_buff *skb; | ||
| 1063 | struct audit_krule *r; | ||
| 1064 | int i; | ||
| 1065 | |||
| 1066 | /* This is a blocking read, so use audit_filter_mutex instead of rcu | ||
| 1067 | * iterator to sync with list writers. */ | ||
| 1068 | for (i=0; i<AUDIT_NR_FILTERS; i++) { | ||
| 1069 | list_for_each_entry(r, &audit_rules_list[i], list) { | ||
| 1070 | struct audit_rule *rule; | ||
| 1071 | |||
| 1072 | rule = audit_krule_to_rule(r); | ||
| 1073 | if (unlikely(!rule)) | ||
| 1074 | break; | ||
| 1075 | skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1, | ||
| 1076 | rule, sizeof(*rule)); | ||
| 1077 | if (skb) | ||
| 1078 | skb_queue_tail(q, skb); | ||
| 1079 | kfree(rule); | ||
| 1080 | } | ||
| 1081 | } | ||
| 1082 | skb = audit_make_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0); | ||
| 1083 | if (skb) | ||
| 1084 | skb_queue_tail(q, skb); | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | /* List rules using struct audit_rule_data. */ | 967 | /* List rules using struct audit_rule_data. */ |
| 1088 | static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) | 968 | static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) |
| 1089 | { | 969 | { |
| @@ -1113,11 +993,11 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) | |||
| 1113 | } | 993 | } |
| 1114 | 994 | ||
| 1115 | /* Log rule additions and removals */ | 995 | /* Log rule additions and removals */ |
| 1116 | static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, | 996 | static void audit_log_rule_change(char *action, struct audit_krule *rule, int res) |
| 1117 | char *action, struct audit_krule *rule, | ||
| 1118 | int res) | ||
| 1119 | { | 997 | { |
| 1120 | struct audit_buffer *ab; | 998 | struct audit_buffer *ab; |
| 999 | uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current)); | ||
| 1000 | u32 sessionid = audit_get_sessionid(current); | ||
| 1121 | 1001 | ||
| 1122 | if (!audit_enabled) | 1002 | if (!audit_enabled) |
| 1123 | return; | 1003 | return; |
| @@ -1125,18 +1005,8 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, | |||
| 1125 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 1005 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 1126 | if (!ab) | 1006 | if (!ab) |
| 1127 | return; | 1007 | return; |
| 1128 | audit_log_format(ab, "auid=%u ses=%u", | 1008 | audit_log_format(ab, "auid=%u ses=%u" ,loginuid, sessionid); |
| 1129 | from_kuid(&init_user_ns, loginuid), sessionid); | 1009 | audit_log_task_context(ab); |
| 1130 | if (sid) { | ||
| 1131 | char *ctx = NULL; | ||
| 1132 | u32 len; | ||
| 1133 | if (security_secid_to_secctx(sid, &ctx, &len)) | ||
| 1134 | audit_log_format(ab, " ssid=%u", sid); | ||
| 1135 | else { | ||
| 1136 | audit_log_format(ab, " subj=%s", ctx); | ||
| 1137 | security_release_secctx(ctx, len); | ||
| 1138 | } | ||
| 1139 | } | ||
| 1140 | audit_log_format(ab, " op="); | 1010 | audit_log_format(ab, " op="); |
| 1141 | audit_log_string(ab, action); | 1011 | audit_log_string(ab, action); |
| 1142 | audit_log_key(ab, rule->filterkey); | 1012 | audit_log_key(ab, rule->filterkey); |
| @@ -1155,8 +1025,7 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, | |||
| 1155 | * @sessionid: sessionid for netlink audit message | 1025 | * @sessionid: sessionid for netlink audit message |
| 1156 | * @sid: SE Linux Security ID of sender | 1026 | * @sid: SE Linux Security ID of sender |
| 1157 | */ | 1027 | */ |
| 1158 | int audit_receive_filter(int type, int pid, int seq, void *data, | 1028 | int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz) |
| 1159 | size_t datasz, kuid_t loginuid, u32 sessionid, u32 sid) | ||
| 1160 | { | 1029 | { |
| 1161 | struct task_struct *tsk; | 1030 | struct task_struct *tsk; |
| 1162 | struct audit_netlink_list *dest; | 1031 | struct audit_netlink_list *dest; |
| @@ -1164,7 +1033,6 @@ int audit_receive_filter(int type, int pid, int seq, void *data, | |||
| 1164 | struct audit_entry *entry; | 1033 | struct audit_entry *entry; |
| 1165 | 1034 | ||
| 1166 | switch (type) { | 1035 | switch (type) { |
| 1167 | case AUDIT_LIST: | ||
| 1168 | case AUDIT_LIST_RULES: | 1036 | case AUDIT_LIST_RULES: |
| 1169 | /* We can't just spew out the rules here because we might fill | 1037 | /* We can't just spew out the rules here because we might fill |
| 1170 | * the available socket buffer space and deadlock waiting for | 1038 | * the available socket buffer space and deadlock waiting for |
| @@ -1179,10 +1047,7 @@ int audit_receive_filter(int type, int pid, int seq, void *data, | |||
| 1179 | skb_queue_head_init(&dest->q); | 1047 | skb_queue_head_init(&dest->q); |
| 1180 | 1048 | ||
| 1181 | mutex_lock(&audit_filter_mutex); | 1049 | mutex_lock(&audit_filter_mutex); |
| 1182 | if (type == AUDIT_LIST) | 1050 | audit_list_rules(pid, seq, &dest->q); |
| 1183 | audit_list(pid, seq, &dest->q); | ||
| 1184 | else | ||
| 1185 | audit_list_rules(pid, seq, &dest->q); | ||
| 1186 | mutex_unlock(&audit_filter_mutex); | 1051 | mutex_unlock(&audit_filter_mutex); |
| 1187 | 1052 | ||
| 1188 | tsk = kthread_run(audit_send_list, dest, "audit_send_list"); | 1053 | tsk = kthread_run(audit_send_list, dest, "audit_send_list"); |
| @@ -1192,35 +1057,23 @@ int audit_receive_filter(int type, int pid, int seq, void *data, | |||
| 1192 | err = PTR_ERR(tsk); | 1057 | err = PTR_ERR(tsk); |
| 1193 | } | 1058 | } |
| 1194 | break; | 1059 | break; |
| 1195 | case AUDIT_ADD: | ||
| 1196 | case AUDIT_ADD_RULE: | 1060 | case AUDIT_ADD_RULE: |
| 1197 | if (type == AUDIT_ADD) | 1061 | entry = audit_data_to_entry(data, datasz); |
| 1198 | entry = audit_rule_to_entry(data); | ||
| 1199 | else | ||
| 1200 | entry = audit_data_to_entry(data, datasz); | ||
| 1201 | if (IS_ERR(entry)) | 1062 | if (IS_ERR(entry)) |
| 1202 | return PTR_ERR(entry); | 1063 | return PTR_ERR(entry); |
| 1203 | 1064 | ||
| 1204 | err = audit_add_rule(entry); | 1065 | err = audit_add_rule(entry); |
| 1205 | audit_log_rule_change(loginuid, sessionid, sid, "add rule", | 1066 | audit_log_rule_change("add rule", &entry->rule, !err); |
| 1206 | &entry->rule, !err); | ||
| 1207 | |||
| 1208 | if (err) | 1067 | if (err) |
| 1209 | audit_free_rule(entry); | 1068 | audit_free_rule(entry); |
| 1210 | break; | 1069 | break; |
| 1211 | case AUDIT_DEL: | ||
| 1212 | case AUDIT_DEL_RULE: | 1070 | case AUDIT_DEL_RULE: |
| 1213 | if (type == AUDIT_DEL) | 1071 | entry = audit_data_to_entry(data, datasz); |
| 1214 | entry = audit_rule_to_entry(data); | ||
| 1215 | else | ||
| 1216 | entry = audit_data_to_entry(data, datasz); | ||
| 1217 | if (IS_ERR(entry)) | 1072 | if (IS_ERR(entry)) |
| 1218 | return PTR_ERR(entry); | 1073 | return PTR_ERR(entry); |
| 1219 | 1074 | ||
| 1220 | err = audit_del_rule(entry); | 1075 | err = audit_del_rule(entry); |
| 1221 | audit_log_rule_change(loginuid, sessionid, sid, "remove rule", | 1076 | audit_log_rule_change("remove rule", &entry->rule, !err); |
| 1222 | &entry->rule, !err); | ||
| 1223 | |||
| 1224 | audit_free_rule(entry); | 1077 | audit_free_rule(entry); |
| 1225 | break; | 1078 | break; |
| 1226 | default: | 1079 | default: |
| @@ -1358,7 +1211,7 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen) | |||
| 1358 | return strncmp(p, dname, dlen); | 1211 | return strncmp(p, dname, dlen); |
| 1359 | } | 1212 | } |
| 1360 | 1213 | ||
| 1361 | static int audit_filter_user_rules(struct audit_krule *rule, | 1214 | static int audit_filter_user_rules(struct audit_krule *rule, int type, |
| 1362 | enum audit_state *state) | 1215 | enum audit_state *state) |
| 1363 | { | 1216 | { |
| 1364 | int i; | 1217 | int i; |
| @@ -1382,6 +1235,13 @@ static int audit_filter_user_rules(struct audit_krule *rule, | |||
| 1382 | result = audit_uid_comparator(audit_get_loginuid(current), | 1235 | result = audit_uid_comparator(audit_get_loginuid(current), |
| 1383 | f->op, f->uid); | 1236 | f->op, f->uid); |
| 1384 | break; | 1237 | break; |
| 1238 | case AUDIT_LOGINUID_SET: | ||
| 1239 | result = audit_comparator(audit_loginuid_set(current), | ||
| 1240 | f->op, f->val); | ||
| 1241 | break; | ||
| 1242 | case AUDIT_MSGTYPE: | ||
| 1243 | result = audit_comparator(type, f->op, f->val); | ||
| 1244 | break; | ||
| 1385 | case AUDIT_SUBJ_USER: | 1245 | case AUDIT_SUBJ_USER: |
| 1386 | case AUDIT_SUBJ_ROLE: | 1246 | case AUDIT_SUBJ_ROLE: |
| 1387 | case AUDIT_SUBJ_TYPE: | 1247 | case AUDIT_SUBJ_TYPE: |
| @@ -1408,7 +1268,7 @@ static int audit_filter_user_rules(struct audit_krule *rule, | |||
| 1408 | return 1; | 1268 | return 1; |
| 1409 | } | 1269 | } |
| 1410 | 1270 | ||
| 1411 | int audit_filter_user(void) | 1271 | int audit_filter_user(int type) |
| 1412 | { | 1272 | { |
| 1413 | enum audit_state state = AUDIT_DISABLED; | 1273 | enum audit_state state = AUDIT_DISABLED; |
| 1414 | struct audit_entry *e; | 1274 | struct audit_entry *e; |
| @@ -1416,7 +1276,7 @@ int audit_filter_user(void) | |||
| 1416 | 1276 | ||
| 1417 | rcu_read_lock(); | 1277 | rcu_read_lock(); |
| 1418 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { | 1278 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { |
| 1419 | if (audit_filter_user_rules(&e->rule, &state)) { | 1279 | if (audit_filter_user_rules(&e->rule, type, &state)) { |
| 1420 | if (state == AUDIT_DISABLED) | 1280 | if (state == AUDIT_DISABLED) |
| 1421 | ret = 0; | 1281 | ret = 0; |
| 1422 | break; | 1282 | break; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index c68229411a7c..3c8a601324a2 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -76,11 +76,6 @@ | |||
| 76 | #define AUDITSC_SUCCESS 1 | 76 | #define AUDITSC_SUCCESS 1 |
| 77 | #define AUDITSC_FAILURE 2 | 77 | #define AUDITSC_FAILURE 2 |
| 78 | 78 | ||
| 79 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | ||
| 80 | * for saving names from getname(). If we get more names we will allocate | ||
| 81 | * a name dynamically and also add those to the list anchored by names_list. */ | ||
| 82 | #define AUDIT_NAMES 5 | ||
| 83 | |||
| 84 | /* no execve audit message should be longer than this (userspace limits) */ | 79 | /* no execve audit message should be longer than this (userspace limits) */ |
| 85 | #define MAX_EXECVE_AUDIT_LEN 7500 | 80 | #define MAX_EXECVE_AUDIT_LEN 7500 |
| 86 | 81 | ||
| @@ -90,44 +85,6 @@ int audit_n_rules; | |||
| 90 | /* determines whether we collect data for signals sent */ | 85 | /* determines whether we collect data for signals sent */ |
| 91 | int audit_signals; | 86 | int audit_signals; |
| 92 | 87 | ||
| 93 | struct audit_cap_data { | ||
| 94 | kernel_cap_t permitted; | ||
| 95 | kernel_cap_t inheritable; | ||
| 96 | union { | ||
| 97 | unsigned int fE; /* effective bit of a file capability */ | ||
| 98 | kernel_cap_t effective; /* effective set of a process */ | ||
| 99 | }; | ||
| 100 | }; | ||
| 101 | |||
| 102 | /* When fs/namei.c:getname() is called, we store the pointer in name and | ||
| 103 | * we don't let putname() free it (instead we free all of the saved | ||
| 104 | * pointers at syscall exit time). | ||
| 105 | * | ||
| 106 | * Further, in fs/namei.c:path_lookup() we store the inode and device. | ||
| 107 | */ | ||
| 108 | struct audit_names { | ||
| 109 | struct list_head list; /* audit_context->names_list */ | ||
| 110 | struct filename *name; | ||
| 111 | unsigned long ino; | ||
| 112 | dev_t dev; | ||
| 113 | umode_t mode; | ||
| 114 | kuid_t uid; | ||
| 115 | kgid_t gid; | ||
| 116 | dev_t rdev; | ||
| 117 | u32 osid; | ||
| 118 | struct audit_cap_data fcap; | ||
| 119 | unsigned int fcap_ver; | ||
| 120 | int name_len; /* number of name's characters to log */ | ||
| 121 | unsigned char type; /* record type */ | ||
| 122 | bool name_put; /* call __putname() for this name */ | ||
| 123 | /* | ||
| 124 | * This was an allocated audit_names and not from the array of | ||
| 125 | * names allocated in the task audit context. Thus this name | ||
| 126 | * should be freed on syscall exit | ||
| 127 | */ | ||
| 128 | bool should_free; | ||
| 129 | }; | ||
| 130 | |||
| 131 | struct audit_aux_data { | 88 | struct audit_aux_data { |
| 132 | struct audit_aux_data *next; | 89 | struct audit_aux_data *next; |
| 133 | int type; | 90 | int type; |
| @@ -175,106 +132,6 @@ struct audit_tree_refs { | |||
| 175 | struct audit_chunk *c[31]; | 132 | struct audit_chunk *c[31]; |
| 176 | }; | 133 | }; |
| 177 | 134 | ||
| 178 | /* The per-task audit context. */ | ||
| 179 | struct audit_context { | ||
| 180 | int dummy; /* must be the first element */ | ||
| 181 | int in_syscall; /* 1 if task is in a syscall */ | ||
| 182 | enum audit_state state, current_state; | ||
| 183 | unsigned int serial; /* serial number for record */ | ||
| 184 | int major; /* syscall number */ | ||
| 185 | struct timespec ctime; /* time of syscall entry */ | ||
| 186 | unsigned long argv[4]; /* syscall arguments */ | ||
| 187 | long return_code;/* syscall return code */ | ||
| 188 | u64 prio; | ||
| 189 | int return_valid; /* return code is valid */ | ||
| 190 | /* | ||
| 191 | * The names_list is the list of all audit_names collected during this | ||
| 192 | * syscall. The first AUDIT_NAMES entries in the names_list will | ||
| 193 | * actually be from the preallocated_names array for performance | ||
| 194 | * reasons. Except during allocation they should never be referenced | ||
| 195 | * through the preallocated_names array and should only be found/used | ||
| 196 | * by running the names_list. | ||
| 197 | */ | ||
| 198 | struct audit_names preallocated_names[AUDIT_NAMES]; | ||
| 199 | int name_count; /* total records in names_list */ | ||
| 200 | struct list_head names_list; /* anchor for struct audit_names->list */ | ||
| 201 | char * filterkey; /* key for rule that triggered record */ | ||
| 202 | struct path pwd; | ||
| 203 | struct audit_aux_data *aux; | ||
| 204 | struct audit_aux_data *aux_pids; | ||
| 205 | struct sockaddr_storage *sockaddr; | ||
| 206 | size_t sockaddr_len; | ||
| 207 | /* Save things to print about task_struct */ | ||
| 208 | pid_t pid, ppid; | ||
| 209 | kuid_t uid, euid, suid, fsuid; | ||
| 210 | kgid_t gid, egid, sgid, fsgid; | ||
| 211 | unsigned long personality; | ||
| 212 | int arch; | ||
| 213 | |||
| 214 | pid_t target_pid; | ||
| 215 | kuid_t target_auid; | ||
| 216 | kuid_t target_uid; | ||
| 217 | unsigned int target_sessionid; | ||
| 218 | u32 target_sid; | ||
| 219 | char target_comm[TASK_COMM_LEN]; | ||
| 220 | |||
| 221 | struct audit_tree_refs *trees, *first_trees; | ||
| 222 | struct list_head killed_trees; | ||
| 223 | int tree_count; | ||
| 224 | |||
| 225 | int type; | ||
| 226 | union { | ||
| 227 | struct { | ||
| 228 | int nargs; | ||
| 229 | long args[6]; | ||
| 230 | } socketcall; | ||
| 231 | struct { | ||
| 232 | kuid_t uid; | ||
| 233 | kgid_t gid; | ||
| 234 | umode_t mode; | ||
| 235 | u32 osid; | ||
| 236 | int has_perm; | ||
| 237 | uid_t perm_uid; | ||
| 238 | gid_t perm_gid; | ||
| 239 | umode_t perm_mode; | ||
| 240 | unsigned long qbytes; | ||
| 241 | } ipc; | ||
| 242 | struct { | ||
| 243 | mqd_t mqdes; | ||
| 244 | struct mq_attr mqstat; | ||
| 245 | } mq_getsetattr; | ||
| 246 | struct { | ||
| 247 | mqd_t mqdes; | ||
| 248 | int sigev_signo; | ||
| 249 | } mq_notify; | ||
| 250 | struct { | ||
| 251 | mqd_t mqdes; | ||
| 252 | size_t msg_len; | ||
| 253 | unsigned int msg_prio; | ||
| 254 | struct timespec abs_timeout; | ||
| 255 | } mq_sendrecv; | ||
| 256 | struct { | ||
| 257 | int oflag; | ||
| 258 | umode_t mode; | ||
| 259 | struct mq_attr attr; | ||
| 260 | } mq_open; | ||
| 261 | struct { | ||
| 262 | pid_t pid; | ||
| 263 | struct audit_cap_data cap; | ||
| 264 | } capset; | ||
| 265 | struct { | ||
| 266 | int fd; | ||
| 267 | int flags; | ||
| 268 | } mmap; | ||
| 269 | }; | ||
| 270 | int fds[2]; | ||
| 271 | |||
| 272 | #if AUDIT_DEBUG | ||
| 273 | int put_count; | ||
| 274 | int ino_count; | ||
| 275 | #endif | ||
| 276 | }; | ||
| 277 | |||
| 278 | static inline int open_arg(int flags, int mask) | 135 | static inline int open_arg(int flags, int mask) |
| 279 | { | 136 | { |
| 280 | int n = ACC_MODE(flags); | 137 | int n = ACC_MODE(flags); |
| @@ -633,9 +490,23 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 633 | break; | 490 | break; |
| 634 | case AUDIT_GID: | 491 | case AUDIT_GID: |
| 635 | result = audit_gid_comparator(cred->gid, f->op, f->gid); | 492 | result = audit_gid_comparator(cred->gid, f->op, f->gid); |
| 493 | if (f->op == Audit_equal) { | ||
| 494 | if (!result) | ||
| 495 | result = in_group_p(f->gid); | ||
| 496 | } else if (f->op == Audit_not_equal) { | ||
| 497 | if (result) | ||
| 498 | result = !in_group_p(f->gid); | ||
| 499 | } | ||
| 636 | break; | 500 | break; |
| 637 | case AUDIT_EGID: | 501 | case AUDIT_EGID: |
| 638 | result = audit_gid_comparator(cred->egid, f->op, f->gid); | 502 | result = audit_gid_comparator(cred->egid, f->op, f->gid); |
| 503 | if (f->op == Audit_equal) { | ||
| 504 | if (!result) | ||
| 505 | result = in_egroup_p(f->gid); | ||
| 506 | } else if (f->op == Audit_not_equal) { | ||
| 507 | if (result) | ||
| 508 | result = !in_egroup_p(f->gid); | ||
| 509 | } | ||
| 639 | break; | 510 | break; |
| 640 | case AUDIT_SGID: | 511 | case AUDIT_SGID: |
| 641 | result = audit_gid_comparator(cred->sgid, f->op, f->gid); | 512 | result = audit_gid_comparator(cred->sgid, f->op, f->gid); |
| @@ -742,6 +613,9 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 742 | if (ctx) | 613 | if (ctx) |
| 743 | result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); | 614 | result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); |
| 744 | break; | 615 | break; |
| 616 | case AUDIT_LOGINUID_SET: | ||
| 617 | result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val); | ||
| 618 | break; | ||
| 745 | case AUDIT_SUBJ_USER: | 619 | case AUDIT_SUBJ_USER: |
| 746 | case AUDIT_SUBJ_ROLE: | 620 | case AUDIT_SUBJ_ROLE: |
| 747 | case AUDIT_SUBJ_TYPE: | 621 | case AUDIT_SUBJ_TYPE: |
| @@ -987,6 +861,8 @@ static inline void audit_free_names(struct audit_context *context) | |||
| 987 | 861 | ||
| 988 | #if AUDIT_DEBUG == 2 | 862 | #if AUDIT_DEBUG == 2 |
| 989 | if (context->put_count + context->ino_count != context->name_count) { | 863 | if (context->put_count + context->ino_count != context->name_count) { |
| 864 | int i = 0; | ||
| 865 | |||
| 990 | printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" | 866 | printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" |
| 991 | " name_count=%d put_count=%d" | 867 | " name_count=%d put_count=%d" |
| 992 | " ino_count=%d [NOT freeing]\n", | 868 | " ino_count=%d [NOT freeing]\n", |
| @@ -995,7 +871,7 @@ static inline void audit_free_names(struct audit_context *context) | |||
| 995 | context->name_count, context->put_count, | 871 | context->name_count, context->put_count, |
| 996 | context->ino_count); | 872 | context->ino_count); |
| 997 | list_for_each_entry(n, &context->names_list, list) { | 873 | list_for_each_entry(n, &context->names_list, list) { |
| 998 | printk(KERN_ERR "names[%d] = %p = %s\n", i, | 874 | printk(KERN_ERR "names[%d] = %p = %s\n", i++, |
| 999 | n->name, n->name->name ?: "(null)"); | 875 | n->name, n->name->name ?: "(null)"); |
| 1000 | } | 876 | } |
| 1001 | dump_stack(); | 877 | dump_stack(); |
| @@ -1010,7 +886,7 @@ static inline void audit_free_names(struct audit_context *context) | |||
| 1010 | list_for_each_entry_safe(n, next, &context->names_list, list) { | 886 | list_for_each_entry_safe(n, next, &context->names_list, list) { |
| 1011 | list_del(&n->list); | 887 | list_del(&n->list); |
| 1012 | if (n->name && n->name_put) | 888 | if (n->name && n->name_put) |
| 1013 | __putname(n->name); | 889 | final_putname(n->name); |
| 1014 | if (n->should_free) | 890 | if (n->should_free) |
| 1015 | kfree(n); | 891 | kfree(n); |
| 1016 | } | 892 | } |
| @@ -1093,88 +969,6 @@ static inline void audit_free_context(struct audit_context *context) | |||
| 1093 | kfree(context); | 969 | kfree(context); |
| 1094 | } | 970 | } |
| 1095 | 971 | ||
| 1096 | void audit_log_task_context(struct audit_buffer *ab) | ||
| 1097 | { | ||
| 1098 | char *ctx = NULL; | ||
| 1099 | unsigned len; | ||
| 1100 | int error; | ||
| 1101 | u32 sid; | ||
| 1102 | |||
| 1103 | security_task_getsecid(current, &sid); | ||
| 1104 | if (!sid) | ||
| 1105 | return; | ||
| 1106 | |||
| 1107 | error = security_secid_to_secctx(sid, &ctx, &len); | ||
| 1108 | if (error) { | ||
| 1109 | if (error != -EINVAL) | ||
| 1110 | goto error_path; | ||
| 1111 | return; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | audit_log_format(ab, " subj=%s", ctx); | ||
| 1115 | security_release_secctx(ctx, len); | ||
| 1116 | return; | ||
| 1117 | |||
| 1118 | error_path: | ||
| 1119 | audit_panic("error in audit_log_task_context"); | ||
| 1120 | return; | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | EXPORT_SYMBOL(audit_log_task_context); | ||
| 1124 | |||
| 1125 | void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) | ||
| 1126 | { | ||
| 1127 | const struct cred *cred; | ||
| 1128 | char name[sizeof(tsk->comm)]; | ||
| 1129 | struct mm_struct *mm = tsk->mm; | ||
| 1130 | char *tty; | ||
| 1131 | |||
| 1132 | if (!ab) | ||
| 1133 | return; | ||
| 1134 | |||
| 1135 | /* tsk == current */ | ||
| 1136 | cred = current_cred(); | ||
| 1137 | |||
| 1138 | spin_lock_irq(&tsk->sighand->siglock); | ||
| 1139 | if (tsk->signal && tsk->signal->tty) | ||
| 1140 | tty = tsk->signal->tty->name; | ||
| 1141 | else | ||
| 1142 | tty = "(none)"; | ||
| 1143 | spin_unlock_irq(&tsk->sighand->siglock); | ||
| 1144 | |||
| 1145 | |||
| 1146 | audit_log_format(ab, | ||
| 1147 | " ppid=%ld pid=%d auid=%u uid=%u gid=%u" | ||
| 1148 | " euid=%u suid=%u fsuid=%u" | ||
| 1149 | " egid=%u sgid=%u fsgid=%u ses=%u tty=%s", | ||
| 1150 | sys_getppid(), | ||
| 1151 | tsk->pid, | ||
| 1152 | from_kuid(&init_user_ns, tsk->loginuid), | ||
| 1153 | from_kuid(&init_user_ns, cred->uid), | ||
| 1154 | from_kgid(&init_user_ns, cred->gid), | ||
| 1155 | from_kuid(&init_user_ns, cred->euid), | ||
| 1156 | from_kuid(&init_user_ns, cred->suid), | ||
| 1157 | from_kuid(&init_user_ns, cred->fsuid), | ||
| 1158 | from_kgid(&init_user_ns, cred->egid), | ||
| 1159 | from_kgid(&init_user_ns, cred->sgid), | ||
| 1160 | from_kgid(&init_user_ns, cred->fsgid), | ||
| 1161 | tsk->sessionid, tty); | ||
| 1162 | |||
| 1163 | get_task_comm(name, tsk); | ||
| 1164 | audit_log_format(ab, " comm="); | ||
| 1165 | audit_log_untrustedstring(ab, name); | ||
| 1166 | |||
| 1167 | if (mm) { | ||
| 1168 | down_read(&mm->mmap_sem); | ||
| 1169 | if (mm->exe_file) | ||
| 1170 | audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); | ||
| 1171 | up_read(&mm->mmap_sem); | ||
| 1172 | } | ||
| 1173 | audit_log_task_context(ab); | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | EXPORT_SYMBOL(audit_log_task_info); | ||
| 1177 | |||
| 1178 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, | 972 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, |
| 1179 | kuid_t auid, kuid_t uid, unsigned int sessionid, | 973 | kuid_t auid, kuid_t uid, unsigned int sessionid, |
| 1180 | u32 sid, char *comm) | 974 | u32 sid, char *comm) |
| @@ -1191,12 +985,14 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid, | |||
| 1191 | audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, | 985 | audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, |
| 1192 | from_kuid(&init_user_ns, auid), | 986 | from_kuid(&init_user_ns, auid), |
| 1193 | from_kuid(&init_user_ns, uid), sessionid); | 987 | from_kuid(&init_user_ns, uid), sessionid); |
| 1194 | if (security_secid_to_secctx(sid, &ctx, &len)) { | 988 | if (sid) { |
| 1195 | audit_log_format(ab, " obj=(none)"); | 989 | if (security_secid_to_secctx(sid, &ctx, &len)) { |
| 1196 | rc = 1; | 990 | audit_log_format(ab, " obj=(none)"); |
| 1197 | } else { | 991 | rc = 1; |
| 1198 | audit_log_format(ab, " obj=%s", ctx); | 992 | } else { |
| 1199 | security_release_secctx(ctx, len); | 993 | audit_log_format(ab, " obj=%s", ctx); |
| 994 | security_release_secctx(ctx, len); | ||
| 995 | } | ||
| 1200 | } | 996 | } |
| 1201 | audit_log_format(ab, " ocomm="); | 997 | audit_log_format(ab, " ocomm="); |
| 1202 | audit_log_untrustedstring(ab, comm); | 998 | audit_log_untrustedstring(ab, comm); |
| @@ -1390,35 +1186,6 @@ static void audit_log_execve_info(struct audit_context *context, | |||
| 1390 | kfree(buf); | 1186 | kfree(buf); |
| 1391 | } | 1187 | } |
| 1392 | 1188 | ||
| 1393 | static void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) | ||
| 1394 | { | ||
| 1395 | int i; | ||
| 1396 | |||
| 1397 | audit_log_format(ab, " %s=", prefix); | ||
| 1398 | CAP_FOR_EACH_U32(i) { | ||
| 1399 | audit_log_format(ab, "%08x", cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]); | ||
| 1400 | } | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) | ||
| 1404 | { | ||
| 1405 | kernel_cap_t *perm = &name->fcap.permitted; | ||
| 1406 | kernel_cap_t *inh = &name->fcap.inheritable; | ||
| 1407 | int log = 0; | ||
| 1408 | |||
| 1409 | if (!cap_isclear(*perm)) { | ||
| 1410 | audit_log_cap(ab, "cap_fp", perm); | ||
| 1411 | log = 1; | ||
| 1412 | } | ||
| 1413 | if (!cap_isclear(*inh)) { | ||
| 1414 | audit_log_cap(ab, "cap_fi", inh); | ||
| 1415 | log = 1; | ||
| 1416 | } | ||
| 1417 | |||
| 1418 | if (log) | ||
| 1419 | audit_log_format(ab, " cap_fe=%d cap_fver=%x", name->fcap.fE, name->fcap_ver); | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | static void show_special(struct audit_context *context, int *call_panic) | 1189 | static void show_special(struct audit_context *context, int *call_panic) |
| 1423 | { | 1190 | { |
| 1424 | struct audit_buffer *ab; | 1191 | struct audit_buffer *ab; |
| @@ -1516,68 +1283,6 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
| 1516 | audit_log_end(ab); | 1283 | audit_log_end(ab); |
| 1517 | } | 1284 | } |
| 1518 | 1285 | ||
| 1519 | static void audit_log_name(struct audit_context *context, struct audit_names *n, | ||
| 1520 | int record_num, int *call_panic) | ||
| 1521 | { | ||
| 1522 | struct audit_buffer *ab; | ||
| 1523 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); | ||
| 1524 | if (!ab) | ||
| 1525 | return; /* audit_panic has been called */ | ||
| 1526 | |||
| 1527 | audit_log_format(ab, "item=%d", record_num); | ||
| 1528 | |||
| 1529 | if (n->name) { | ||
| 1530 | switch (n->name_len) { | ||
| 1531 | case AUDIT_NAME_FULL: | ||
| 1532 | /* log the full path */ | ||
| 1533 | audit_log_format(ab, " name="); | ||
| 1534 | audit_log_untrustedstring(ab, n->name->name); | ||
| 1535 | break; | ||
| 1536 | case 0: | ||
| 1537 | /* name was specified as a relative path and the | ||
| 1538 | * directory component is the cwd */ | ||
| 1539 | audit_log_d_path(ab, " name=", &context->pwd); | ||
| 1540 | break; | ||
| 1541 | default: | ||
| 1542 | /* log the name's directory component */ | ||
| 1543 | audit_log_format(ab, " name="); | ||
| 1544 | audit_log_n_untrustedstring(ab, n->name->name, | ||
| 1545 | n->name_len); | ||
| 1546 | } | ||
| 1547 | } else | ||
| 1548 | audit_log_format(ab, " name=(null)"); | ||
| 1549 | |||
| 1550 | if (n->ino != (unsigned long)-1) { | ||
| 1551 | audit_log_format(ab, " inode=%lu" | ||
| 1552 | " dev=%02x:%02x mode=%#ho" | ||
| 1553 | " ouid=%u ogid=%u rdev=%02x:%02x", | ||
| 1554 | n->ino, | ||
| 1555 | MAJOR(n->dev), | ||
| 1556 | MINOR(n->dev), | ||
| 1557 | n->mode, | ||
| 1558 | from_kuid(&init_user_ns, n->uid), | ||
| 1559 | from_kgid(&init_user_ns, n->gid), | ||
| 1560 | MAJOR(n->rdev), | ||
| 1561 | MINOR(n->rdev)); | ||
| 1562 | } | ||
| 1563 | if (n->osid != 0) { | ||
| 1564 | char *ctx = NULL; | ||
| 1565 | u32 len; | ||
| 1566 | if (security_secid_to_secctx( | ||
| 1567 | n->osid, &ctx, &len)) { | ||
| 1568 | audit_log_format(ab, " osid=%u", n->osid); | ||
| 1569 | *call_panic = 2; | ||
| 1570 | } else { | ||
| 1571 | audit_log_format(ab, " obj=%s", ctx); | ||
| 1572 | security_release_secctx(ctx, len); | ||
| 1573 | } | ||
| 1574 | } | ||
| 1575 | |||
| 1576 | audit_log_fcaps(ab, n); | ||
| 1577 | |||
| 1578 | audit_log_end(ab); | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) | 1286 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) |
| 1582 | { | 1287 | { |
| 1583 | int i, call_panic = 0; | 1288 | int i, call_panic = 0; |
| @@ -1695,7 +1400,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1695 | 1400 | ||
| 1696 | i = 0; | 1401 | i = 0; |
| 1697 | list_for_each_entry(n, &context->names_list, list) | 1402 | list_for_each_entry(n, &context->names_list, list) |
| 1698 | audit_log_name(context, n, i++, &call_panic); | 1403 | audit_log_name(context, n, NULL, i++, &call_panic); |
| 1699 | 1404 | ||
| 1700 | /* Send end of event record to help user space know we are finished */ | 1405 | /* Send end of event record to help user space know we are finished */ |
| 1701 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); | 1406 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); |
| @@ -2030,18 +1735,18 @@ void audit_putname(struct filename *name) | |||
| 2030 | BUG_ON(!context); | 1735 | BUG_ON(!context); |
| 2031 | if (!context->in_syscall) { | 1736 | if (!context->in_syscall) { |
| 2032 | #if AUDIT_DEBUG == 2 | 1737 | #if AUDIT_DEBUG == 2 |
| 2033 | printk(KERN_ERR "%s:%d(:%d): __putname(%p)\n", | 1738 | printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n", |
| 2034 | __FILE__, __LINE__, context->serial, name); | 1739 | __FILE__, __LINE__, context->serial, name); |
| 2035 | if (context->name_count) { | 1740 | if (context->name_count) { |
| 2036 | struct audit_names *n; | 1741 | struct audit_names *n; |
| 2037 | int i; | 1742 | int i = 0; |
| 2038 | 1743 | ||
| 2039 | list_for_each_entry(n, &context->names_list, list) | 1744 | list_for_each_entry(n, &context->names_list, list) |
| 2040 | printk(KERN_ERR "name[%d] = %p = %s\n", i, | 1745 | printk(KERN_ERR "name[%d] = %p = %s\n", i++, |
| 2041 | n->name, n->name->name ?: "(null)"); | 1746 | n->name, n->name->name ?: "(null)"); |
| 2042 | } | 1747 | } |
| 2043 | #endif | 1748 | #endif |
| 2044 | __putname(name); | 1749 | final_putname(name); |
| 2045 | } | 1750 | } |
| 2046 | #if AUDIT_DEBUG | 1751 | #if AUDIT_DEBUG |
| 2047 | else { | 1752 | else { |
| @@ -2060,41 +1765,6 @@ void audit_putname(struct filename *name) | |||
| 2060 | #endif | 1765 | #endif |
| 2061 | } | 1766 | } |
| 2062 | 1767 | ||
| 2063 | static inline int audit_copy_fcaps(struct audit_names *name, const struct dentry *dentry) | ||
| 2064 | { | ||
| 2065 | struct cpu_vfs_cap_data caps; | ||
| 2066 | int rc; | ||
| 2067 | |||
| 2068 | if (!dentry) | ||
| 2069 | return 0; | ||
| 2070 | |||
| 2071 | rc = get_vfs_caps_from_disk(dentry, &caps); | ||
| 2072 | if (rc) | ||
| 2073 | return rc; | ||
| 2074 | |||
| 2075 | name->fcap.permitted = caps.permitted; | ||
| 2076 | name->fcap.inheritable = caps.inheritable; | ||
| 2077 | name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); | ||
| 2078 | name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; | ||
| 2079 | |||
| 2080 | return 0; | ||
| 2081 | } | ||
| 2082 | |||
| 2083 | |||
| 2084 | /* Copy inode data into an audit_names. */ | ||
| 2085 | static void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, | ||
| 2086 | const struct inode *inode) | ||
| 2087 | { | ||
| 2088 | name->ino = inode->i_ino; | ||
| 2089 | name->dev = inode->i_sb->s_dev; | ||
| 2090 | name->mode = inode->i_mode; | ||
| 2091 | name->uid = inode->i_uid; | ||
| 2092 | name->gid = inode->i_gid; | ||
| 2093 | name->rdev = inode->i_rdev; | ||
| 2094 | security_inode_getsecid(inode, &name->osid); | ||
| 2095 | audit_copy_fcaps(name, dentry); | ||
| 2096 | } | ||
| 2097 | |||
| 2098 | /** | 1768 | /** |
| 2099 | * __audit_inode - store the inode and device from a lookup | 1769 | * __audit_inode - store the inode and device from a lookup |
| 2100 | * @name: name being audited | 1770 | * @name: name being audited |
| @@ -2303,7 +1973,7 @@ int audit_set_loginuid(kuid_t loginuid) | |||
| 2303 | unsigned int sessionid; | 1973 | unsigned int sessionid; |
| 2304 | 1974 | ||
| 2305 | #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE | 1975 | #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE |
| 2306 | if (uid_valid(task->loginuid)) | 1976 | if (audit_loginuid_set(task)) |
| 2307 | return -EPERM; | 1977 | return -EPERM; |
| 2308 | #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ | 1978 | #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ |
| 2309 | if (!capable(CAP_AUDIT_CONTROL)) | 1979 | if (!capable(CAP_AUDIT_CONTROL)) |
| @@ -2471,17 +2141,20 @@ int __audit_bprm(struct linux_binprm *bprm) | |||
| 2471 | 2141 | ||
| 2472 | /** | 2142 | /** |
| 2473 | * audit_socketcall - record audit data for sys_socketcall | 2143 | * audit_socketcall - record audit data for sys_socketcall |
| 2474 | * @nargs: number of args | 2144 | * @nargs: number of args, which should not be more than AUDITSC_ARGS. |
| 2475 | * @args: args array | 2145 | * @args: args array |
| 2476 | * | 2146 | * |
| 2477 | */ | 2147 | */ |
| 2478 | void __audit_socketcall(int nargs, unsigned long *args) | 2148 | int __audit_socketcall(int nargs, unsigned long *args) |
| 2479 | { | 2149 | { |
| 2480 | struct audit_context *context = current->audit_context; | 2150 | struct audit_context *context = current->audit_context; |
| 2481 | 2151 | ||
| 2152 | if (nargs <= 0 || nargs > AUDITSC_ARGS || !args) | ||
| 2153 | return -EINVAL; | ||
| 2482 | context->type = AUDIT_SOCKETCALL; | 2154 | context->type = AUDIT_SOCKETCALL; |
| 2483 | context->socketcall.nargs = nargs; | 2155 | context->socketcall.nargs = nargs; |
| 2484 | memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long)); | 2156 | memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long)); |
| 2157 | return 0; | ||
| 2485 | } | 2158 | } |
| 2486 | 2159 | ||
| 2487 | /** | 2160 | /** |
diff --git a/net/socket.c b/net/socket.c index b416093997da..6b94633ca61d 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -2412,7 +2412,7 @@ static const unsigned char nargs[21] = { | |||
| 2412 | 2412 | ||
| 2413 | SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) | 2413 | SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) |
| 2414 | { | 2414 | { |
| 2415 | unsigned long a[6]; | 2415 | unsigned long a[AUDITSC_ARGS]; |
| 2416 | unsigned long a0, a1; | 2416 | unsigned long a0, a1; |
| 2417 | int err; | 2417 | int err; |
| 2418 | unsigned int len; | 2418 | unsigned int len; |
| @@ -2428,7 +2428,9 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) | |||
| 2428 | if (copy_from_user(a, args, len)) | 2428 | if (copy_from_user(a, args, len)) |
| 2429 | return -EFAULT; | 2429 | return -EFAULT; |
| 2430 | 2430 | ||
| 2431 | audit_socketcall(nargs[call] / sizeof(unsigned long), a); | 2431 | err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); |
| 2432 | if (err) | ||
| 2433 | return err; | ||
| 2432 | 2434 | ||
| 2433 | a0 = a[0]; | 2435 | a0 = a[0]; |
| 2434 | a1 = a[1]; | 2436 | a1 = a[1]; |
