diff options
Diffstat (limited to 'kernel/auditsc.c')
| -rw-r--r-- | kernel/auditsc.c | 117 |
1 files changed, 76 insertions, 41 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index ae40ac8c39e7..efc1b74bebf3 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 */ |
| @@ -514,7 +518,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
| 514 | context->return_valid = return_valid; | 518 | context->return_valid = return_valid; |
| 515 | context->return_code = return_code; | 519 | context->return_code = return_code; |
| 516 | 520 | ||
| 517 | if (context->in_syscall && !context->auditable) { | 521 | if (context->in_syscall && !context->dummy && !context->auditable) { |
| 518 | enum audit_state state; | 522 | enum audit_state state; |
| 519 | 523 | ||
| 520 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); | 524 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); |
| @@ -530,17 +534,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
| 530 | } | 534 | } |
| 531 | 535 | ||
| 532 | get_context: | 536 | get_context: |
| 533 | context->pid = tsk->pid; | 537 | |
| 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; | 538 | tsk->audit_context = NULL; |
| 545 | return context; | 539 | return context; |
| 546 | } | 540 | } |
| @@ -749,6 +743,17 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 749 | const char *tty; | 743 | const char *tty; |
| 750 | 744 | ||
| 751 | /* tsk == current */ | 745 | /* tsk == current */ |
| 746 | context->pid = tsk->pid; | ||
| 747 | context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ | ||
| 748 | context->uid = tsk->uid; | ||
| 749 | context->gid = tsk->gid; | ||
| 750 | context->euid = tsk->euid; | ||
| 751 | context->suid = tsk->suid; | ||
| 752 | context->fsuid = tsk->fsuid; | ||
| 753 | context->egid = tsk->egid; | ||
| 754 | context->sgid = tsk->sgid; | ||
| 755 | context->fsgid = tsk->fsgid; | ||
| 756 | context->personality = tsk->personality; | ||
| 752 | 757 | ||
| 753 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); | 758 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); |
| 754 | if (!ab) | 759 | if (!ab) |
| @@ -1066,7 +1071,8 @@ void audit_syscall_entry(int arch, int major, | |||
| 1066 | context->argv[3] = a4; | 1071 | context->argv[3] = a4; |
| 1067 | 1072 | ||
| 1068 | state = context->state; | 1073 | state = context->state; |
| 1069 | if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT) | 1074 | context->dummy = !audit_n_rules; |
| 1075 | if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)) | ||
| 1070 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); | 1076 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); |
| 1071 | if (likely(state == AUDIT_DISABLED)) | 1077 | if (likely(state == AUDIT_DISABLED)) |
| 1072 | return; | 1078 | return; |
| @@ -1199,14 +1205,18 @@ void audit_putname(const char *name) | |||
| 1199 | #endif | 1205 | #endif |
| 1200 | } | 1206 | } |
| 1201 | 1207 | ||
| 1202 | static void audit_inode_context(int idx, const struct inode *inode) | 1208 | /* Copy inode data into an audit_names. */ |
| 1209 | static void audit_copy_inode(struct audit_names *name, const struct inode *inode) | ||
| 1203 | { | 1210 | { |
| 1204 | struct audit_context *context = current->audit_context; | 1211 | name->ino = inode->i_ino; |
| 1205 | 1212 | name->dev = inode->i_sb->s_dev; | |
| 1206 | selinux_get_inode_sid(inode, &context->names[idx].osid); | 1213 | name->mode = inode->i_mode; |
| 1214 | name->uid = inode->i_uid; | ||
| 1215 | name->gid = inode->i_gid; | ||
| 1216 | name->rdev = inode->i_rdev; | ||
| 1217 | selinux_get_inode_sid(inode, &name->osid); | ||
| 1207 | } | 1218 | } |
| 1208 | 1219 | ||
| 1209 | |||
| 1210 | /** | 1220 | /** |
| 1211 | * audit_inode - store the inode and device from a lookup | 1221 | * audit_inode - store the inode and device from a lookup |
| 1212 | * @name: name being audited | 1222 | * @name: name being audited |
| @@ -1240,20 +1250,14 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
| 1240 | ++context->ino_count; | 1250 | ++context->ino_count; |
| 1241 | #endif | 1251 | #endif |
| 1242 | } | 1252 | } |
| 1243 | context->names[idx].ino = inode->i_ino; | 1253 | 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 | } | 1254 | } |
| 1251 | 1255 | ||
| 1252 | /** | 1256 | /** |
| 1253 | * audit_inode_child - collect inode info for created/removed objects | 1257 | * audit_inode_child - collect inode info for created/removed objects |
| 1254 | * @dname: inode's dentry name | 1258 | * @dname: inode's dentry name |
| 1255 | * @inode: inode being audited | 1259 | * @inode: inode being audited |
| 1256 | * @pino: inode number of dentry parent | 1260 | * @parent: inode of dentry parent |
| 1257 | * | 1261 | * |
| 1258 | * For syscalls that create or remove filesystem objects, audit_inode | 1262 | * For syscalls that create or remove filesystem objects, audit_inode |
| 1259 | * can only collect information for the filesystem object's parent. | 1263 | * can only collect information for the filesystem object's parent. |
| @@ -1264,7 +1268,7 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
| 1264 | * unsuccessful attempts. | 1268 | * unsuccessful attempts. |
| 1265 | */ | 1269 | */ |
| 1266 | void __audit_inode_child(const char *dname, const struct inode *inode, | 1270 | void __audit_inode_child(const char *dname, const struct inode *inode, |
| 1267 | unsigned long pino) | 1271 | const struct inode *parent) |
| 1268 | { | 1272 | { |
| 1269 | int idx; | 1273 | int idx; |
| 1270 | struct audit_context *context = current->audit_context; | 1274 | struct audit_context *context = current->audit_context; |
| @@ -1278,7 +1282,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, | |||
| 1278 | if (!dname) | 1282 | if (!dname) |
| 1279 | goto update_context; | 1283 | goto update_context; |
| 1280 | for (idx = 0; idx < context->name_count; idx++) | 1284 | for (idx = 0; idx < context->name_count; idx++) |
| 1281 | if (context->names[idx].ino == pino) { | 1285 | if (context->names[idx].ino == parent->i_ino) { |
| 1282 | const char *name = context->names[idx].name; | 1286 | const char *name = context->names[idx].name; |
| 1283 | 1287 | ||
| 1284 | if (!name) | 1288 | if (!name) |
| @@ -1302,16 +1306,47 @@ update_context: | |||
| 1302 | context->names[idx].name_len = AUDIT_NAME_FULL; | 1306 | context->names[idx].name_len = AUDIT_NAME_FULL; |
| 1303 | context->names[idx].name_put = 0; /* don't call __putname() */ | 1307 | context->names[idx].name_put = 0; /* don't call __putname() */ |
| 1304 | 1308 | ||
| 1305 | if (inode) { | 1309 | if (!inode) |
| 1306 | context->names[idx].ino = inode->i_ino; | 1310 | context->names[idx].ino = (unsigned long)-1; |
| 1307 | context->names[idx].dev = inode->i_sb->s_dev; | 1311 | else |
| 1308 | context->names[idx].mode = inode->i_mode; | 1312 | audit_copy_inode(&context->names[idx], inode); |
| 1309 | context->names[idx].uid = inode->i_uid; | 1313 | |
| 1310 | context->names[idx].gid = inode->i_gid; | 1314 | /* A parent was not found in audit_names, so copy the inode data for the |
| 1311 | context->names[idx].rdev = inode->i_rdev; | 1315 | * provided parent. */ |
| 1312 | audit_inode_context(idx, inode); | 1316 | if (!found_name) { |
| 1313 | } else | 1317 | idx = context->name_count++; |
| 1314 | context->names[idx].ino = (unsigned long)-1; | 1318 | #if AUDIT_DEBUG |
| 1319 | context->ino_count++; | ||
| 1320 | #endif | ||
| 1321 | audit_copy_inode(&context->names[idx], parent); | ||
| 1322 | } | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | /** | ||
| 1326 | * audit_inode_update - update inode info for last collected name | ||
| 1327 | * @inode: inode being audited | ||
| 1328 | * | ||
| 1329 | * When open() is called on an existing object with the O_CREAT flag, the inode | ||
| 1330 | * data audit initially collects is incorrect. This additional hook ensures | ||
| 1331 | * audit has the inode data for the actual object to be opened. | ||
| 1332 | */ | ||
| 1333 | void __audit_inode_update(const struct inode *inode) | ||
| 1334 | { | ||
| 1335 | struct audit_context *context = current->audit_context; | ||
| 1336 | int idx; | ||
| 1337 | |||
| 1338 | if (!context->in_syscall || !inode) | ||
| 1339 | return; | ||
| 1340 | |||
| 1341 | if (context->name_count == 0) { | ||
| 1342 | context->name_count++; | ||
| 1343 | #if AUDIT_DEBUG | ||
| 1344 | context->ino_count++; | ||
| 1345 | #endif | ||
| 1346 | } | ||
| 1347 | idx = context->name_count - 1; | ||
| 1348 | |||
| 1349 | audit_copy_inode(&context->names[idx], inode); | ||
| 1315 | } | 1350 | } |
| 1316 | 1351 | ||
| 1317 | /** | 1352 | /** |
| @@ -1642,7 +1677,7 @@ int audit_bprm(struct linux_binprm *bprm) | |||
| 1642 | unsigned long p, next; | 1677 | unsigned long p, next; |
| 1643 | void *to; | 1678 | void *to; |
| 1644 | 1679 | ||
| 1645 | if (likely(!audit_enabled || !context)) | 1680 | if (likely(!audit_enabled || !context || context->dummy)) |
| 1646 | return 0; | 1681 | return 0; |
| 1647 | 1682 | ||
| 1648 | ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, | 1683 | ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, |
| @@ -1680,7 +1715,7 @@ int audit_socketcall(int nargs, unsigned long *args) | |||
| 1680 | struct audit_aux_data_socketcall *ax; | 1715 | struct audit_aux_data_socketcall *ax; |
| 1681 | struct audit_context *context = current->audit_context; | 1716 | struct audit_context *context = current->audit_context; |
| 1682 | 1717 | ||
| 1683 | if (likely(!context)) | 1718 | if (likely(!context || context->dummy)) |
| 1684 | return 0; | 1719 | return 0; |
| 1685 | 1720 | ||
| 1686 | ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); | 1721 | ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); |
| @@ -1708,7 +1743,7 @@ int audit_sockaddr(int len, void *a) | |||
| 1708 | struct audit_aux_data_sockaddr *ax; | 1743 | struct audit_aux_data_sockaddr *ax; |
| 1709 | struct audit_context *context = current->audit_context; | 1744 | struct audit_context *context = current->audit_context; |
| 1710 | 1745 | ||
| 1711 | if (likely(!context)) | 1746 | if (likely(!context || context->dummy)) |
| 1712 | return 0; | 1747 | return 0; |
| 1713 | 1748 | ||
| 1714 | ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); | 1749 | ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); |
