diff options
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 168 |
1 files changed, 127 insertions, 41 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index ae40ac8c39e7..1bd8827a0102 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -85,6 +85,9 @@ extern int audit_enabled; | |||
85 | /* Indicates that audit should log the full pathname. */ | 85 | /* Indicates that audit should log the full pathname. */ |
86 | #define AUDIT_NAME_FULL -1 | 86 | #define AUDIT_NAME_FULL -1 |
87 | 87 | ||
88 | /* number of audit rules */ | ||
89 | int audit_n_rules; | ||
90 | |||
88 | /* When fs/namei.c:getname() is called, we store the pointer in name and | 91 | /* When fs/namei.c:getname() is called, we store the pointer in name and |
89 | * we don't let putname() free it (instead we free all of the saved | 92 | * we don't let putname() free it (instead we free all of the saved |
90 | * pointers at syscall exit time). | 93 | * pointers at syscall exit time). |
@@ -174,6 +177,7 @@ struct audit_aux_data_path { | |||
174 | 177 | ||
175 | /* The per-task audit context. */ | 178 | /* The per-task audit context. */ |
176 | struct audit_context { | 179 | struct audit_context { |
180 | int dummy; /* must be the first element */ | ||
177 | int in_syscall; /* 1 if task is in a syscall */ | 181 | int in_syscall; /* 1 if task is in a syscall */ |
178 | enum audit_state state; | 182 | enum audit_state state; |
179 | unsigned int serial; /* serial number for record */ | 183 | unsigned int serial; /* serial number for record */ |
@@ -205,6 +209,54 @@ struct audit_context { | |||
205 | #endif | 209 | #endif |
206 | }; | 210 | }; |
207 | 211 | ||
212 | #define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE]) | ||
213 | static inline int open_arg(int flags, int mask) | ||
214 | { | ||
215 | int n = ACC_MODE(flags); | ||
216 | if (flags & (O_TRUNC | O_CREAT)) | ||
217 | n |= AUDIT_PERM_WRITE; | ||
218 | return n & mask; | ||
219 | } | ||
220 | |||
221 | static int audit_match_perm(struct audit_context *ctx, int mask) | ||
222 | { | ||
223 | unsigned n = ctx->major; | ||
224 | switch (audit_classify_syscall(ctx->arch, n)) { | ||
225 | case 0: /* native */ | ||
226 | if ((mask & AUDIT_PERM_WRITE) && | ||
227 | audit_match_class(AUDIT_CLASS_WRITE, n)) | ||
228 | return 1; | ||
229 | if ((mask & AUDIT_PERM_READ) && | ||
230 | audit_match_class(AUDIT_CLASS_READ, n)) | ||
231 | return 1; | ||
232 | if ((mask & AUDIT_PERM_ATTR) && | ||
233 | audit_match_class(AUDIT_CLASS_CHATTR, n)) | ||
234 | return 1; | ||
235 | return 0; | ||
236 | case 1: /* 32bit on biarch */ | ||
237 | if ((mask & AUDIT_PERM_WRITE) && | ||
238 | audit_match_class(AUDIT_CLASS_WRITE_32, n)) | ||
239 | return 1; | ||
240 | if ((mask & AUDIT_PERM_READ) && | ||
241 | audit_match_class(AUDIT_CLASS_READ_32, n)) | ||
242 | return 1; | ||
243 | if ((mask & AUDIT_PERM_ATTR) && | ||
244 | audit_match_class(AUDIT_CLASS_CHATTR_32, n)) | ||
245 | return 1; | ||
246 | return 0; | ||
247 | case 2: /* open */ | ||
248 | return mask & ACC_MODE(ctx->argv[1]); | ||
249 | case 3: /* openat */ | ||
250 | return mask & ACC_MODE(ctx->argv[2]); | ||
251 | case 4: /* socketcall */ | ||
252 | return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND); | ||
253 | case 5: /* execve */ | ||
254 | return mask & AUDIT_PERM_EXEC; | ||
255 | default: | ||
256 | return 0; | ||
257 | } | ||
258 | } | ||
259 | |||
208 | /* Determine if any context name data matches a rule's watch data */ | 260 | /* Determine if any context name data matches a rule's watch data */ |
209 | /* Compare a task_struct with an audit_rule. Return 1 on match, 0 | 261 | /* Compare a task_struct with an audit_rule. Return 1 on match, 0 |
210 | * otherwise. */ | 262 | * otherwise. */ |
@@ -393,6 +445,9 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
393 | /* ignore this field for filtering */ | 445 | /* ignore this field for filtering */ |
394 | result = 1; | 446 | result = 1; |
395 | break; | 447 | break; |
448 | case AUDIT_PERM: | ||
449 | result = audit_match_perm(ctx, f->val); | ||
450 | break; | ||
396 | } | 451 | } |
397 | 452 | ||
398 | if (!result) | 453 | if (!result) |
@@ -514,7 +569,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
514 | context->return_valid = return_valid; | 569 | context->return_valid = return_valid; |
515 | context->return_code = return_code; | 570 | context->return_code = return_code; |
516 | 571 | ||
517 | if (context->in_syscall && !context->auditable) { | 572 | if (context->in_syscall && !context->dummy && !context->auditable) { |
518 | enum audit_state state; | 573 | enum audit_state state; |
519 | 574 | ||
520 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); | 575 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); |
@@ -530,17 +585,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
530 | } | 585 | } |
531 | 586 | ||
532 | get_context: | 587 | get_context: |
533 | context->pid = tsk->pid; | 588 | |
534 | context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ | ||
535 | context->uid = tsk->uid; | ||
536 | context->gid = tsk->gid; | ||
537 | context->euid = tsk->euid; | ||
538 | context->suid = tsk->suid; | ||
539 | context->fsuid = tsk->fsuid; | ||
540 | context->egid = tsk->egid; | ||
541 | context->sgid = tsk->sgid; | ||
542 | context->fsgid = tsk->fsgid; | ||
543 | context->personality = tsk->personality; | ||
544 | tsk->audit_context = NULL; | 589 | tsk->audit_context = NULL; |
545 | return context; | 590 | return context; |
546 | } | 591 | } |
@@ -749,6 +794,17 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
749 | const char *tty; | 794 | const char *tty; |
750 | 795 | ||
751 | /* tsk == current */ | 796 | /* tsk == current */ |
797 | context->pid = tsk->pid; | ||
798 | context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ | ||
799 | context->uid = tsk->uid; | ||
800 | context->gid = tsk->gid; | ||
801 | context->euid = tsk->euid; | ||
802 | context->suid = tsk->suid; | ||
803 | context->fsuid = tsk->fsuid; | ||
804 | context->egid = tsk->egid; | ||
805 | context->sgid = tsk->sgid; | ||
806 | context->fsgid = tsk->fsgid; | ||
807 | context->personality = tsk->personality; | ||
752 | 808 | ||
753 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); | 809 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); |
754 | if (!ab) | 810 | if (!ab) |
@@ -1066,7 +1122,8 @@ void audit_syscall_entry(int arch, int major, | |||
1066 | context->argv[3] = a4; | 1122 | context->argv[3] = a4; |
1067 | 1123 | ||
1068 | state = context->state; | 1124 | state = context->state; |
1069 | if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT) | 1125 | context->dummy = !audit_n_rules; |
1126 | if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)) | ||
1070 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); | 1127 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); |
1071 | if (likely(state == AUDIT_DISABLED)) | 1128 | if (likely(state == AUDIT_DISABLED)) |
1072 | return; | 1129 | return; |
@@ -1199,14 +1256,18 @@ void audit_putname(const char *name) | |||
1199 | #endif | 1256 | #endif |
1200 | } | 1257 | } |
1201 | 1258 | ||
1202 | static void audit_inode_context(int idx, const struct inode *inode) | 1259 | /* Copy inode data into an audit_names. */ |
1260 | static void audit_copy_inode(struct audit_names *name, const struct inode *inode) | ||
1203 | { | 1261 | { |
1204 | struct audit_context *context = current->audit_context; | 1262 | name->ino = inode->i_ino; |
1205 | 1263 | name->dev = inode->i_sb->s_dev; | |
1206 | selinux_get_inode_sid(inode, &context->names[idx].osid); | 1264 | name->mode = inode->i_mode; |
1265 | name->uid = inode->i_uid; | ||
1266 | name->gid = inode->i_gid; | ||
1267 | name->rdev = inode->i_rdev; | ||
1268 | selinux_get_inode_sid(inode, &name->osid); | ||
1207 | } | 1269 | } |
1208 | 1270 | ||
1209 | |||
1210 | /** | 1271 | /** |
1211 | * audit_inode - store the inode and device from a lookup | 1272 | * audit_inode - store the inode and device from a lookup |
1212 | * @name: name being audited | 1273 | * @name: name being audited |
@@ -1240,20 +1301,14 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
1240 | ++context->ino_count; | 1301 | ++context->ino_count; |
1241 | #endif | 1302 | #endif |
1242 | } | 1303 | } |
1243 | context->names[idx].ino = inode->i_ino; | 1304 | audit_copy_inode(&context->names[idx], inode); |
1244 | context->names[idx].dev = inode->i_sb->s_dev; | ||
1245 | context->names[idx].mode = inode->i_mode; | ||
1246 | context->names[idx].uid = inode->i_uid; | ||
1247 | context->names[idx].gid = inode->i_gid; | ||
1248 | context->names[idx].rdev = inode->i_rdev; | ||
1249 | audit_inode_context(idx, inode); | ||
1250 | } | 1305 | } |
1251 | 1306 | ||
1252 | /** | 1307 | /** |
1253 | * audit_inode_child - collect inode info for created/removed objects | 1308 | * audit_inode_child - collect inode info for created/removed objects |
1254 | * @dname: inode's dentry name | 1309 | * @dname: inode's dentry name |
1255 | * @inode: inode being audited | 1310 | * @inode: inode being audited |
1256 | * @pino: inode number of dentry parent | 1311 | * @parent: inode of dentry parent |
1257 | * | 1312 | * |
1258 | * For syscalls that create or remove filesystem objects, audit_inode | 1313 | * For syscalls that create or remove filesystem objects, audit_inode |
1259 | * can only collect information for the filesystem object's parent. | 1314 | * can only collect information for the filesystem object's parent. |
@@ -1264,7 +1319,7 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
1264 | * unsuccessful attempts. | 1319 | * unsuccessful attempts. |
1265 | */ | 1320 | */ |
1266 | void __audit_inode_child(const char *dname, const struct inode *inode, | 1321 | void __audit_inode_child(const char *dname, const struct inode *inode, |
1267 | unsigned long pino) | 1322 | const struct inode *parent) |
1268 | { | 1323 | { |
1269 | int idx; | 1324 | int idx; |
1270 | struct audit_context *context = current->audit_context; | 1325 | struct audit_context *context = current->audit_context; |
@@ -1278,7 +1333,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, | |||
1278 | if (!dname) | 1333 | if (!dname) |
1279 | goto update_context; | 1334 | goto update_context; |
1280 | for (idx = 0; idx < context->name_count; idx++) | 1335 | for (idx = 0; idx < context->name_count; idx++) |
1281 | if (context->names[idx].ino == pino) { | 1336 | if (context->names[idx].ino == parent->i_ino) { |
1282 | const char *name = context->names[idx].name; | 1337 | const char *name = context->names[idx].name; |
1283 | 1338 | ||
1284 | if (!name) | 1339 | if (!name) |
@@ -1302,16 +1357,47 @@ update_context: | |||
1302 | context->names[idx].name_len = AUDIT_NAME_FULL; | 1357 | context->names[idx].name_len = AUDIT_NAME_FULL; |
1303 | context->names[idx].name_put = 0; /* don't call __putname() */ | 1358 | context->names[idx].name_put = 0; /* don't call __putname() */ |
1304 | 1359 | ||
1305 | if (inode) { | 1360 | if (!inode) |
1306 | context->names[idx].ino = inode->i_ino; | 1361 | context->names[idx].ino = (unsigned long)-1; |
1307 | context->names[idx].dev = inode->i_sb->s_dev; | 1362 | else |
1308 | context->names[idx].mode = inode->i_mode; | 1363 | audit_copy_inode(&context->names[idx], inode); |
1309 | context->names[idx].uid = inode->i_uid; | 1364 | |
1310 | context->names[idx].gid = inode->i_gid; | 1365 | /* A parent was not found in audit_names, so copy the inode data for the |
1311 | context->names[idx].rdev = inode->i_rdev; | 1366 | * provided parent. */ |
1312 | audit_inode_context(idx, inode); | 1367 | if (!found_name) { |
1313 | } else | 1368 | idx = context->name_count++; |
1314 | context->names[idx].ino = (unsigned long)-1; | 1369 | #if AUDIT_DEBUG |
1370 | context->ino_count++; | ||
1371 | #endif | ||
1372 | audit_copy_inode(&context->names[idx], parent); | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1376 | /** | ||
1377 | * audit_inode_update - update inode info for last collected name | ||
1378 | * @inode: inode being audited | ||
1379 | * | ||
1380 | * When open() is called on an existing object with the O_CREAT flag, the inode | ||
1381 | * data audit initially collects is incorrect. This additional hook ensures | ||
1382 | * audit has the inode data for the actual object to be opened. | ||
1383 | */ | ||
1384 | void __audit_inode_update(const struct inode *inode) | ||
1385 | { | ||
1386 | struct audit_context *context = current->audit_context; | ||
1387 | int idx; | ||
1388 | |||
1389 | if (!context->in_syscall || !inode) | ||
1390 | return; | ||
1391 | |||
1392 | if (context->name_count == 0) { | ||
1393 | context->name_count++; | ||
1394 | #if AUDIT_DEBUG | ||
1395 | context->ino_count++; | ||
1396 | #endif | ||
1397 | } | ||
1398 | idx = context->name_count - 1; | ||
1399 | |||
1400 | audit_copy_inode(&context->names[idx], inode); | ||
1315 | } | 1401 | } |
1316 | 1402 | ||
1317 | /** | 1403 | /** |
@@ -1642,7 +1728,7 @@ int audit_bprm(struct linux_binprm *bprm) | |||
1642 | unsigned long p, next; | 1728 | unsigned long p, next; |
1643 | void *to; | 1729 | void *to; |
1644 | 1730 | ||
1645 | if (likely(!audit_enabled || !context)) | 1731 | if (likely(!audit_enabled || !context || context->dummy)) |
1646 | return 0; | 1732 | return 0; |
1647 | 1733 | ||
1648 | ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, | 1734 | ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, |
@@ -1680,7 +1766,7 @@ int audit_socketcall(int nargs, unsigned long *args) | |||
1680 | struct audit_aux_data_socketcall *ax; | 1766 | struct audit_aux_data_socketcall *ax; |
1681 | struct audit_context *context = current->audit_context; | 1767 | struct audit_context *context = current->audit_context; |
1682 | 1768 | ||
1683 | if (likely(!context)) | 1769 | if (likely(!context || context->dummy)) |
1684 | return 0; | 1770 | return 0; |
1685 | 1771 | ||
1686 | ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); | 1772 | ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); |
@@ -1708,7 +1794,7 @@ int audit_sockaddr(int len, void *a) | |||
1708 | struct audit_aux_data_sockaddr *ax; | 1794 | struct audit_aux_data_sockaddr *ax; |
1709 | struct audit_context *context = current->audit_context; | 1795 | struct audit_context *context = current->audit_context; |
1710 | 1796 | ||
1711 | if (likely(!context)) | 1797 | if (likely(!context || context->dummy)) |
1712 | return 0; | 1798 | return 0; |
1713 | 1799 | ||
1714 | ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); | 1800 | ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); |